set_work_tree: use chdir_notify
When we change to the top of the working tree, we manually re-adjust $GIT_DIR and call set_git_dir() again, in order to update any relative git-dir we'd compute earlier. Instead of the work-tree code having to know to call the git-dir code, let's use the new chdir_notify interface. There are two spots that need updating, with a few subtleties in each: 1. the set_git_dir() code needs to chdir_notify_register() so it can be told when to update its path. Technically we could push this down into repo_set_gitdir(), so that even repository structs besides the_repository could benefit from this. But that opens up a lot of complications: - we'd still need to touch set_git_dir(), because it does some other setup (like setting $GIT_DIR in the environment) - submodules using other repository structs get cleaned up, which means we'd need to remove them from the chdir_notify list - it's unlikely to fix any bugs, since we shouldn't generally chdir() in the middle of working on a submodule 2. setup_work_tree now needs to call chdir_notify(), and can lose its manual set_git_dir() call. Note that at first glance it looks like this undoes the absolute-to-relative optimization added by044bbbcb63
(Make git_dir a path relative to work_tree in setup_work_tree(), 2008-06-19). But for the most part that optimization was just _undoing_ the relative-to-absolute conversion which the function was doing earlier (and which is now gone). It is true that if you already have an absolute git_dir that the setup_work_tree() function will no longer make it relative as a side effect. But: - we generally do have relative git-dir's due to the way the discovery code works - if we really care about making git-dir's relative when possible, then we should be relativizing them earlier (e.g., when we see an absolute $GIT_DIR we could turn it relative, whether we are going to chdir into a worktree or not). That would cover all cases, including ones that044bbbcb63
did not. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
2b5ed37365
commit
8500e0de3f
@ -13,6 +13,7 @@
|
||||
#include "refs.h"
|
||||
#include "fmt-merge-msg.h"
|
||||
#include "commit.h"
|
||||
#include "chdir-notify.h"
|
||||
|
||||
int trust_executable_bit = 1;
|
||||
int trust_ctime = 1;
|
||||
@ -296,7 +297,7 @@ char *get_graft_file(void)
|
||||
return the_repository->graft_file;
|
||||
}
|
||||
|
||||
void set_git_dir(const char *path)
|
||||
static void set_git_dir_1(const char *path)
|
||||
{
|
||||
if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
|
||||
die("could not set GIT_DIR to '%s'", path);
|
||||
@ -304,6 +305,26 @@ void set_git_dir(const char *path)
|
||||
setup_git_env();
|
||||
}
|
||||
|
||||
static void update_relative_gitdir(const char *name,
|
||||
const char *old_cwd,
|
||||
const char *new_cwd,
|
||||
void *data)
|
||||
{
|
||||
char *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());
|
||||
trace_printf_key(&trace_setup_key,
|
||||
"setup: move $GIT_DIR to '%s'",
|
||||
path);
|
||||
set_git_dir_1(path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
void set_git_dir(const char *path)
|
||||
{
|
||||
set_git_dir_1(path);
|
||||
if (!is_absolute_path(path))
|
||||
chdir_notify_register(NULL, update_relative_gitdir, NULL);
|
||||
}
|
||||
|
||||
const char *get_log_output_encoding(void)
|
||||
{
|
||||
return git_log_output_encoding ? git_log_output_encoding
|
||||
|
9
setup.c
9
setup.c
@ -3,6 +3,7 @@
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "string-list.h"
|
||||
#include "chdir-notify.h"
|
||||
|
||||
static int inside_git_dir = -1;
|
||||
static int inside_work_tree = -1;
|
||||
@ -378,7 +379,7 @@ int is_inside_work_tree(void)
|
||||
|
||||
void setup_work_tree(void)
|
||||
{
|
||||
const char *work_tree, *git_dir;
|
||||
const char *work_tree;
|
||||
static int initialized = 0;
|
||||
|
||||
if (initialized)
|
||||
@ -388,10 +389,7 @@ void setup_work_tree(void)
|
||||
die(_("unable to set up work tree using invalid config"));
|
||||
|
||||
work_tree = get_git_work_tree();
|
||||
git_dir = get_git_dir();
|
||||
if (!is_absolute_path(git_dir))
|
||||
git_dir = real_path(get_git_dir());
|
||||
if (!work_tree || chdir(work_tree))
|
||||
if (!work_tree || chdir_notify(work_tree))
|
||||
die(_("this operation must be run in a work tree"));
|
||||
|
||||
/*
|
||||
@ -401,7 +399,6 @@ void setup_work_tree(void)
|
||||
if (getenv(GIT_WORK_TREE_ENVIRONMENT))
|
||||
setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
|
||||
|
||||
set_git_dir(remove_leading_path(git_dir, work_tree));
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user