Skip to content

Commit 8500e0d

Browse files
peffgitster
authored andcommitted
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 by 044bbbc (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 that 044bbbc did not. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2b5ed37 commit 8500e0d

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

environment.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "refs.h"
1414
#include "fmt-merge-msg.h"
1515
#include "commit.h"
16+
#include "chdir-notify.h"
1617

1718
int trust_executable_bit = 1;
1819
int trust_ctime = 1;
@@ -296,14 +297,34 @@ char *get_graft_file(void)
296297
return the_repository->graft_file;
297298
}
298299

299-
void set_git_dir(const char *path)
300+
static void set_git_dir_1(const char *path)
300301
{
301302
if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
302303
die("could not set GIT_DIR to '%s'", path);
303304
repo_set_gitdir(the_repository, path);
304305
setup_git_env();
305306
}
306307

308+
static void update_relative_gitdir(const char *name,
309+
const char *old_cwd,
310+
const char *new_cwd,
311+
void *data)
312+
{
313+
char *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());
314+
trace_printf_key(&trace_setup_key,
315+
"setup: move $GIT_DIR to '%s'",
316+
path);
317+
set_git_dir_1(path);
318+
free(path);
319+
}
320+
321+
void set_git_dir(const char *path)
322+
{
323+
set_git_dir_1(path);
324+
if (!is_absolute_path(path))
325+
chdir_notify_register(NULL, update_relative_gitdir, NULL);
326+
}
327+
307328
const char *get_log_output_encoding(void)
308329
{
309330
return git_log_output_encoding ? git_log_output_encoding

setup.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "config.h"
44
#include "dir.h"
55
#include "string-list.h"
6+
#include "chdir-notify.h"
67

78
static int inside_git_dir = -1;
89
static int inside_work_tree = -1;
@@ -378,7 +379,7 @@ int is_inside_work_tree(void)
378379

379380
void setup_work_tree(void)
380381
{
381-
const char *work_tree, *git_dir;
382+
const char *work_tree;
382383
static int initialized = 0;
383384

384385
if (initialized)
@@ -388,10 +389,7 @@ void setup_work_tree(void)
388389
die(_("unable to set up work tree using invalid config"));
389390

390391
work_tree = get_git_work_tree();
391-
git_dir = get_git_dir();
392-
if (!is_absolute_path(git_dir))
393-
git_dir = real_path(get_git_dir());
394-
if (!work_tree || chdir(work_tree))
392+
if (!work_tree || chdir_notify(work_tree))
395393
die(_("this operation must be run in a work tree"));
396394

397395
/*
@@ -401,7 +399,6 @@ void setup_work_tree(void)
401399
if (getenv(GIT_WORK_TREE_ENVIRONMENT))
402400
setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
403401

404-
set_git_dir(remove_leading_path(git_dir, work_tree));
405402
initialized = 1;
406403
}
407404

0 commit comments

Comments
 (0)