summaryrefslogtreecommitdiff
path: root/git.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-02-17 10:13:31 -0800
committerJunio C Hamano <gitster@pobox.com>2016-02-17 10:13:31 -0800
commitdbda66b0e283494c35958316c9b1c47b6e6c9f59 (patch)
treecfbee1f5d4982aa377386aafc2661568dbc2e70a /git.c
parentf60ccdd98c3f1183922b43478b629049408849ff (diff)
parent8384c139cb9409fb3cf5ef70afff263917581258 (diff)
downloadgit-dbda66b0e283494c35958316c9b1c47b6e6c9f59.tar.gz
Merge branch 'nd/clear-gitenv-upon-use-of-alias'
The automatic typo correction applied to an alias was broken with a recent change already in 'master'. * nd/clear-gitenv-upon-use-of-alias: restore_env(): free the saved environment variable once we are done git: simplify environment save/restore logic git: protect against unbalanced calls to {save,restore}_env() git: remove an early return from save_env_before_alias()
Diffstat (limited to 'git.c')
-rw-r--r--git.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/git.c b/git.c
index da278c3d41..6c64c9430e 100644
--- a/git.c
+++ b/git.c
@@ -25,14 +25,14 @@ static const char *env_names[] = {
GIT_PREFIX_ENVIRONMENT
};
static char *orig_env[4];
-static int saved_env_before_alias;
+static int save_restore_env_balance;
static void save_env_before_alias(void)
{
int i;
- if (saved_env_before_alias)
- return;
- saved_env_before_alias = 1;
+
+ assert(save_restore_env_balance == 0);
+ save_restore_env_balance = 1;
orig_cwd = xgetcwd();
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
orig_env[i] = getenv(env_names[i]);
@@ -44,6 +44,9 @@ static void save_env_before_alias(void)
static void restore_env(int external_alias)
{
int i;
+
+ assert(save_restore_env_balance == 1);
+ save_restore_env_balance = 0;
if (!external_alias && orig_cwd && chdir(orig_cwd))
die_errno("could not move to %s", orig_cwd);
free(orig_cwd);
@@ -51,10 +54,12 @@ static void restore_env(int external_alias)
if (external_alias &&
!strcmp(env_names[i], GIT_PREFIX_ENVIRONMENT))
continue;
- if (orig_env[i])
+ if (orig_env[i]) {
setenv(env_names[i], orig_env[i], 1);
- else
+ free(orig_env[i]);
+ } else {
unsetenv(env_names[i]);
+ }
}
}
@@ -531,16 +536,8 @@ static void handle_builtin(int argc, const char **argv)
}
builtin = get_builtin(cmd);
- if (builtin) {
- /*
- * XXX: if we can figure out cases where it is _safe_
- * to do, we can avoid spawning a new process when
- * saved_env_before_alias is true
- * (i.e. setup_git_dir* has been run once)
- */
- if (!saved_env_before_alias)
- exit(run_builtin(builtin, argc, argv));
- }
+ if (builtin)
+ exit(run_builtin(builtin, argc, argv));
}
static void execv_dashed_external(const char **argv)
@@ -584,8 +581,17 @@ static int run_argv(int *argcp, const char ***argv)
int done_alias = 0;
while (1) {
- /* See if it's a builtin */
- handle_builtin(*argcp, *argv);
+ /*
+ * If we tried alias and futzed with our environment,
+ * it no longer is safe to invoke builtins directly in
+ * general. We have to spawn them as dashed externals.
+ *
+ * NEEDSWORK: if we can figure out cases
+ * where it is safe to do, we can avoid spawning a new
+ * process.
+ */
+ if (!done_alias)
+ handle_builtin(*argcp, *argv);
/* .. then try the external ones */
execv_dashed_external(*argv);