Skip to content

Commit

Permalink
Fix "aliases vs pre-command hook" issue
Browse files Browse the repository at this point in the history
It was reported that the pre-command hook is not called as expected when
running aliases in subdirectories.

Turns out that handle_alias() nastily initializes the Git directory, and
then tries (incompletely) to restore the state beforehand.

Let's do a more thorough job at restoring the state.

An alternative approach would be to avoid calling
setup_git_directory_gently() *just* to read the alias' expansion, using
discover_git_directory_gently(). But that method is fraught with peril, as
e.g. "external" aliases, i.e. aliases starting with an exclamation point
expect to be called in the top-level directory of the current worktree
(and set GIT_PREFIX accordingly), if any.

Signed-off-by: Johannes Schindelin <johasc@microsoft.com>
  • Loading branch information
dscho committed May 12, 2017
1 parent 75fb913 commit 2d859ba
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cache.h
Expand Up @@ -485,6 +485,8 @@ extern const char *get_git_namespace(void);
extern const char *strip_namespace(const char *namespaced_ref);
extern const char *get_super_prefix(void);
extern const char *get_git_work_tree(void);
extern void save_git_dir_before_alias(void);
extern void restore_git_dir_after_alias(void);

/*
* Return true if the given path is a git directory; note that this _just_
Expand Down
12 changes: 11 additions & 1 deletion environment.c
Expand Up @@ -102,7 +102,7 @@ static size_t namespace_len;

static const char *super_prefix;

static const char *git_dir, *git_common_dir;
static const char *git_dir, *git_common_dir, *saved_git_dir;
static char *git_object_dir, *git_index_file, *git_graft_file;
int git_db_env, git_index_env, git_graft_env, git_common_dir_env;

Expand Down Expand Up @@ -196,6 +196,16 @@ static void setup_git_env(void)
set_alternate_shallow_file(shallow_file, 0);
}

void save_git_dir_before_alias(void)
{
saved_git_dir = git_dir;
}

void restore_git_dir_after_alias(void)
{
git_dir = saved_git_dir;
}

int is_bare_repository(void)
{
/* if core.bare is not 'false', let's see if there is a work tree */
Expand Down
5 changes: 5 additions & 0 deletions git.c
Expand Up @@ -26,13 +26,16 @@ static const char *env_names[] = {
};
static char *orig_env[4];
static int save_restore_env_balance;
static struct startup_info orig_startup_info;

static void save_env_before_alias(void)
{
int i;

assert(save_restore_env_balance == 0);
save_restore_env_balance = 1;
orig_startup_info = *startup_info;
save_git_dir_before_alias();
orig_cwd = xgetcwd();
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
orig_env[i] = getenv(env_names[i]);
Expand All @@ -46,6 +49,8 @@ static void restore_env(int external_alias)

assert(save_restore_env_balance == 1);
save_restore_env_balance = 0;
*startup_info = orig_startup_info;
restore_git_dir_after_alias();
if (!external_alias && orig_cwd && chdir(orig_cwd))
die_errno("could not move to %s", orig_cwd);
free(orig_cwd);
Expand Down
13 changes: 13 additions & 0 deletions t/t0400-pre-command-hook.sh
Expand Up @@ -40,4 +40,17 @@ test_expect_success 'in a subdirectory' '
test_path_is_file sub/i-was-here
'

test_expect_success 'in a subdirectory, using an alias' '
git reset --hard &&
echo "echo \"\$@; \$(pwd)\" >>log" |
write_script .git/hooks/pre-command &&
mkdir -p sub &&
(
cd sub &&
git -c alias.r="rebase HEAD" r
) &&
test_path_is_missing log &&
test_line_count = 2 sub/log
'

test_done

0 comments on commit 2d859ba

Please sign in to comment.