mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
![Ramkumar Ramachandra](/assets/img/avatar_default.png)
By improving the relative_path() algorithm, e02ca72
(path.c:
refactor relative_path(), not only strip prefix, 2013-06-25)
uncovered a latent bug in Emacs. While most editor applications
like cat and vim handle non-canonicalized relative paths fine, emacs
does not. This is due to a long-standing bug in emacs, where it
refuses to resolve symlinks in the supplied path:
#!/bin/sh
cd /tmp
mkdir z z/a z/b
echo moodle >z/a/file
ln -s z/b
cd b
emacs ../a/file # fail: attempts to open /tmp/a/file
Even if emacs were to be patched to fix this bug, it may be nicer to
help users running older versions.
Note that this can potentially regress for users of all editors,
when they ask "what file am I editing?" to the editor, as it is
likely to answer with an unsightly long full path.
Co-authored-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
71 lines
1.5 KiB
C
71 lines
1.5 KiB
C
#include "cache.h"
|
|
#include "strbuf.h"
|
|
#include "run-command.h"
|
|
#include "sigchain.h"
|
|
|
|
#ifndef DEFAULT_EDITOR
|
|
#define DEFAULT_EDITOR "vi"
|
|
#endif
|
|
|
|
const char *git_editor(void)
|
|
{
|
|
const char *editor = getenv("GIT_EDITOR");
|
|
const char *terminal = getenv("TERM");
|
|
int terminal_is_dumb = !terminal || !strcmp(terminal, "dumb");
|
|
|
|
if (!editor && editor_program)
|
|
editor = editor_program;
|
|
if (!editor && !terminal_is_dumb)
|
|
editor = getenv("VISUAL");
|
|
if (!editor)
|
|
editor = getenv("EDITOR");
|
|
|
|
if (!editor && terminal_is_dumb)
|
|
return NULL;
|
|
|
|
if (!editor)
|
|
editor = DEFAULT_EDITOR;
|
|
|
|
return editor;
|
|
}
|
|
|
|
int launch_editor(const char *path, struct strbuf *buffer, const char *const *env)
|
|
{
|
|
const char *editor = git_editor();
|
|
|
|
if (!editor)
|
|
return error("Terminal is dumb, but EDITOR unset");
|
|
|
|
if (strcmp(editor, ":")) {
|
|
const char *args[] = { editor, real_path(path), NULL };
|
|
struct child_process p;
|
|
int ret, sig;
|
|
|
|
memset(&p, 0, sizeof(p));
|
|
p.argv = args;
|
|
p.env = env;
|
|
p.use_shell = 1;
|
|
if (start_command(&p) < 0)
|
|
return error("unable to start editor '%s'", editor);
|
|
|
|
sigchain_push(SIGINT, SIG_IGN);
|
|
sigchain_push(SIGQUIT, SIG_IGN);
|
|
ret = finish_command(&p);
|
|
sig = ret - 128;
|
|
sigchain_pop(SIGINT);
|
|
sigchain_pop(SIGQUIT);
|
|
if (sig == SIGINT || sig == SIGQUIT)
|
|
raise(sig);
|
|
if (ret)
|
|
return error("There was a problem with the editor '%s'.",
|
|
editor);
|
|
}
|
|
|
|
if (!buffer)
|
|
return 0;
|
|
if (strbuf_read_file(buffer, path, 0) < 0)
|
|
return error("could not read file '%s': %s",
|
|
path, strerror(errno));
|
|
return 0;
|
|
}
|