Skip to content

Commit

Permalink
setup.c: re-fix d95138e (setup: set env $GIT_WORK_TREE when ..
Browse files Browse the repository at this point in the history
Commit d95138e [1] attempted to fix a .git file problem by
setting GIT_WORK_TREE whenever GIT_DIR is set. It sounded harmless
because we handle GIT_DIR and GIT_WORK_TREE side by side for most
commands, with two exceptions: git-init and git-clone.

"git clone" is not happy with d95138e. This command ignores GIT_DIR
but respects GIT_WORK_TREE [2] [3] which means it used to run fine
from a hook, where GIT_DIR was set but GIT_WORK_TREE was not (*).
With d95138e, GIT_WORK_TREE is set all the time and git-clone
interprets that as "I give you order to put the worktree here",
usually against the user's intention.

The solution in d95138e is reverted earlier, and instead we reuse
the solution from c056261 [4].  It fixed another setup-messed-
up-by-alias by saving and restoring env and spawning a new process,
but for git-clone and git-init only.

Now we conclude that setup-messed-up-by-alias is always evil. So the
env restoration is done for _all_ commands, including external ones,
whenever aliases are involved. It fixes what d95138e tried to fix,
without upsetting git-clone-inside-hooks.

The test from d95138e remains to verify it's not broken by this. A new
test is added to make sure git-clone-inside-hooks remains happy.

(*) GIT_WORK_TREE was not set _most of the time_. In some cases
    GIT_WORK_TREE is set and git-clone will behave differently. The
    use of GIT_WORK_TREE to direct git-clone to put work tree
    elsewhere looks like a mistake because it causes surprises this
    way. But that's a separate story.

[1] d95138e (setup: set env $GIT_WORK_TREE when work tree is set, like
             $GIT_DIR - 2015-06-26)
[2] 2beebd2 (clone: create intermediate directories of destination
             repo - 2008-06-25)
[3] 20ccef4 (make git-clone GIT_WORK_TREE aware - 2007-07-06)
[4] c056261 (git potty: restore environments after alias expansion -
             2014-06-08)

Reported-by: Anthony Sottile <asottile@umich.edu>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed Dec 22, 2015
1 parent 0d5466d commit 86d26f2
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 12 deletions.
23 changes: 12 additions & 11 deletions git.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
static int handle_alias(int *argcp, const char ***argv)
{
int envchanged = 0, ret = 0, saved_errno = errno;
const char *subdir;
int count, option_count;
const char **new_argv;
const char *alias_command;
char *alias_string;
int unused_nongit;

save_env_before_alias();
subdir = setup_git_directory_gently(&unused_nongit);
setup_git_directory_gently(&unused_nongit);

alias_command = (*argv)[0];
alias_string = alias_lookup(alias_command);
Expand Down Expand Up @@ -292,8 +291,7 @@ static int handle_alias(int *argcp, const char ***argv)
ret = 1;
}

if (subdir && chdir(subdir))
die_errno("Cannot change to '%s'", subdir);
restore_env();

errno = saved_errno;

Expand All @@ -308,7 +306,6 @@ static int handle_alias(int *argcp, const char ***argv)
* RUN_SETUP for reading from the configuration file.
*/
#define NEED_WORK_TREE (1<<3)
#define NO_SETUP (1<<4)

struct cmd_struct {
const char *cmd;
Expand Down Expand Up @@ -389,7 +386,7 @@ static struct cmd_struct commands[] = {
{ "cherry", cmd_cherry, RUN_SETUP },
{ "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
{ "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
{ "clone", cmd_clone, NO_SETUP },
{ "clone", cmd_clone },
{ "column", cmd_column, RUN_SETUP_GENTLY },
{ "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
Expand All @@ -415,8 +412,8 @@ static struct cmd_struct commands[] = {
{ "hash-object", cmd_hash_object },
{ "help", cmd_help },
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
{ "init", cmd_init_db, NO_SETUP },
{ "init-db", cmd_init_db, NO_SETUP },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
{ "interpret-trailers", cmd_interpret_trailers, RUN_SETUP },
{ "log", cmd_log, RUN_SETUP },
{ "ls-files", cmd_ls_files, RUN_SETUP },
Expand Down Expand Up @@ -528,9 +525,13 @@ static void handle_builtin(int argc, const char **argv)

builtin = get_builtin(cmd);
if (builtin) {
if (saved_env_before_alias && (builtin->option & NO_SETUP))
restore_env();
else
/*
* 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));
}
}
Expand Down
2 changes: 1 addition & 1 deletion t/t0002-gitfile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ test_expect_success 'check rev-list' '
test "$SHA" = "$(git rev-list HEAD)"
'

test_expect_failure 'setup_git_dir twice in subdir' '
test_expect_success 'setup_git_dir twice in subdir' '
git init sgd &&
(
cd sgd &&
Expand Down
23 changes: 23 additions & 0 deletions t/t5601-clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ test_expect_success 'clone respects GIT_WORK_TREE' '
'

test_expect_success 'clone from hooks' '
test_create_repo r0 &&
cd r0 &&
test_commit initial &&
cd .. &&
git init r1 &&
cd r1 &&
cat >.git/hooks/pre-commit <<-\EOF &&
#!/bin/sh
git clone ../r0 ../r2
exit 1
EOF
chmod u+x .git/hooks/pre-commit &&
: >file &&
git add file &&
test_must_fail git commit -m invoke-hook &&
cd .. &&
test_cmp r0/.git/HEAD r2/.git/HEAD &&
test_cmp r0/initial.t r2/initial.t
'

test_expect_success 'clone creates intermediate directories' '
git clone src long/path/to/dst &&
Expand Down

0 comments on commit 86d26f2

Please sign in to comment.