From: Matthias Lederhofer <matled@gmx.net>
To: git@vger.kernel.org
Subject: [PATCH] make git barf when an alias changes environment variables
Date: Fri, 8 Jun 2007 22:57:55 +0200 [thread overview]
Message-ID: <20070608205755.GA21901@moooo.ath.cx> (raw)
Aliases changing environment variables (GIT_DIR or
GIT_WORK_TREE) can cause problems:
git has to use GIT_DIR to read the aliases from the config.
After running handle_options for the alias the options of the
alias may have changed environment variables. Depending on
the implementation of setenv the memory location obtained
through getenv earlier may contain the old value or the new
value (or even be used for something else?). To avoid these
problems git errors out if an alias uses any option which
changes environment variables.
Signed-off-by: Matthias Lederhofer <matled@gmx.net>
---
This is on top of ml/worktree even though the problem is also present in
master. It could also be split into one patch which can be applied to
master directly and another one adding the missing parts in the
ml/worktree branch.
Another option instead of dying would be to execute git again. I
decided not to because of
(1) It causes problems with aliases starting the pager: After the exec
git wouldn't know that the pager is running and colors would be
missing.
(2) Up to now aliases not starting with '!' have recursion detection
and are only evaluated as aliases once. Executing git again would
break this.
Example:
Here is an example how to break git aliases, it works with libc of
FreeBSD but not with glibc. libc of FreeBSD reuses the old location
for the environment variable if the new value is smaller than the old
one.
There is a repository in a/.git and a repository in b/.git. Both have
valid HEADs:
% git --git-dir a/.git rev-list --pretty=oneline HEAD
496a0d181f6878ddda8926103a7cf28a668c46ef a
% git --git-dir b/.git rev-list --pretty=oneline HEAD
3c2858eded8ae7ff964549f85f479808d185283c b
Set up some aliases using --git-dir:
% git --git-dir a/.git config alias.works \
'--git-dir a/.git rev-list --pretty=oneline HEAD'
% git --git-dir a/.git config alias.breaks \
'--git-dir b/.git rev-list --pretty=oneline HEAD'
% git --git-dir a/.git config alias.good
'!git --git-dir b/.git rev-list --pretty=oneline HEAD'
The first one works because the value of the environment variable does
not change, the second one does not work because git reads the ref
HEAD from b/.git but searches the object in a/.git. The third one
always works.
% git --git-dir a/.git works
496a0d181f6878ddda8926103a7cf28a668c46ef a
% git --git-dir a/.git breaks
fatal: bad object HEAD
[1] 15643 exit 128 git --git-dir a/.git breaks
% git --git-dir a/.git good
3c2858eded8ae7ff964549f85f479808d185283c b
With the patch:
% git --git-dir a/.git breaks
fatal: alias 'breaks' changes environment variables
You can use '!git' in the alias to do this.
[1] 17295 exit 128 git --git-dir a/.git breaks
---
git.c | 22 ++++++++++++++++++----
1 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/git.c b/git.c
index cd3910a..33edd62 100644
--- a/git.c
+++ b/git.c
@@ -28,7 +28,7 @@ static void prepend_to_path(const char *dir, int len)
free(path);
}
-static int handle_options(const char*** argv, int* argc)
+static int handle_options(const char*** argv, int* argc, int* envchanged)
{
int handled = 0;
@@ -64,24 +64,34 @@ static int handle_options(const char*** argv, int* argc)
usage(git_usage_string);
}
setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
+ if (envchanged)
+ *envchanged = 1;
(*argv)++;
(*argc)--;
handled++;
} else if (!prefixcmp(cmd, "--git-dir=")) {
setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
+ if (envchanged)
+ *envchanged = 1;
} else if (!strcmp(cmd, "--work-tree")) {
if (*argc < 2) {
fprintf(stderr, "No directory given for --work-tree.\n" );
usage(git_usage_string);
}
setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
+ if (envchanged)
+ *envchanged = 1;
(*argv)++;
(*argc)--;
} else if (!prefixcmp(cmd, "--work-tree=")) {
setenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
+ if (envchanged)
+ *envchanged = 1;
} else if (!strcmp(cmd, "--bare")) {
static char git_dir[PATH_MAX+1];
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 1);
+ if (envchanged)
+ *envchanged = 1;
} else {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(git_usage_string);
@@ -160,7 +170,7 @@ static int split_cmdline(char *cmdline, const char ***argv)
static int handle_alias(int *argcp, const char ***argv)
{
- int nongit = 0, ret = 0, saved_errno = errno;
+ int nongit = 0, envchanged = 0, ret = 0, saved_errno = errno;
const char *subdir;
int count, option_count;
const char** new_argv;
@@ -181,7 +191,11 @@ static int handle_alias(int *argcp, const char ***argv)
alias_string + 1, alias_command);
}
count = split_cmdline(alias_string, &new_argv);
- option_count = handle_options(&new_argv, &count);
+ option_count = handle_options(&new_argv, &count, &envchanged);
+ if (envchanged)
+ die("alias '%s' changes environment variables\n"
+ "You can use '!git' in the alias to do this.",
+ alias_command);
memmove(new_argv - option_count, new_argv,
count * sizeof(char *));
new_argv -= option_count;
@@ -375,7 +389,7 @@ int main(int argc, const char **argv, char **envp)
/* Look for flags.. */
argv++;
argc--;
- handle_options(&argv, &argc);
+ handle_options(&argv, &argc, NULL);
if (argc > 0) {
if (!prefixcmp(argv[0], "--"))
argv[0] += 2;
--
1.5.2.1.888.gd5e4e
next reply other threads:[~2007-06-08 20:58 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-08 20:57 Matthias Lederhofer [this message]
2007-06-13 5:21 ` [PATCH] make git barf when an alias changes environment variables Junio C Hamano
2007-06-13 5:41 ` Matthias Lederhofer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070608205755.GA21901@moooo.ath.cx \
--to=matled@gmx.net \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).