From: Duy Nguyen <pclouds@xxxxxxxxx> When the current directory is moved, all relative paths may become invalid because they are still relative to the old current directory. At this point in setup_work_tree() many objects have been initialized and some keep relative paths in their data structure. $GIT_DIR and $GIT_WORK_TREE for example are the two examples which are dealt with explicitly in this code: $GIT_WORK_TREE is reset to "." and set_git_dir() is called the second time with a new relative path. Introduce a more generic mechanism to let all code get notified and do the path adjustment themselves instead of pulling all path adjustment logic in here. The $GIT_DIR and $GIT_WORK_TREE adjustments will removed from this code in later patches. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- cache.h | 5 +++++ setup.c | 27 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/cache.h b/cache.h index 05f32c9659..895abe7e7e 100644 --- a/cache.h +++ b/cache.h @@ -522,6 +522,11 @@ extern void set_git_work_tree(const char *tree); #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" +typedef void (*cwd_updated_fn)(const char *old_cwd, + const char *new_cwd, + void *cb_data); +void add_cwd_update_callback(cwd_updated_fn fn, void *cb_data); +void removet_cwd_update_callback(cwd_updated_fn fn, void *cb_data); extern void setup_adjust_path(const char *name, char **path, const char *old_cwd, const char *new_cwd); diff --git a/setup.c b/setup.c index e26f44185e..e340ee2130 100644 --- a/setup.c +++ b/setup.c @@ -376,6 +376,24 @@ int is_inside_work_tree(void) return inside_work_tree; } +struct cwd_update_callback { + cwd_updated_fn fn; + void *cb_data; +}; + +static struct cwd_update_callback *cwd_callbacks; +static int nr_cwd_callbacks; + +void add_cwd_update_callback(cwd_updated_fn fn, void *cb_data) +{ + struct cwd_update_callback *cb; + + REALLOC_ARRAY(cwd_callbacks, nr_cwd_callbacks + 1); + cb = cwd_callbacks + nr_cwd_callbacks++; + cb->fn = fn; + cb->cb_data = cb_data; +} + void setup_adjust_path(const char *name, char **path, const char *old_cwd, const char *new_cwd) @@ -398,8 +416,10 @@ void setup_adjust_path(const char *name, char **path, void setup_work_tree(void) { - const char *work_tree, *git_dir; static int initialized = 0; + const char *work_tree, *git_dir; + struct strbuf old_cwd = STRBUF_INIT; + int i; if (initialized) return; @@ -411,6 +431,7 @@ void setup_work_tree(void) git_dir = get_git_dir(); if (!is_absolute_path(git_dir)) git_dir = real_path(get_git_dir()); + strbuf_get_pwd_cwd(&old_cwd); if (!work_tree || chdir(work_tree)) die(_("this operation must be run in a work tree")); @@ -421,6 +442,10 @@ void setup_work_tree(void) if (getenv(GIT_WORK_TREE_ENVIRONMENT)) setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1); + for (i = 0; i < nr_cwd_callbacks; i++) + cwd_callbacks[i].fn(old_cwd.buf, work_tree, + cwd_callbacks[i].cb_data); + strbuf_release(&old_cwd); set_git_dir(remove_leading_path(git_dir, work_tree)); initialized = 1; } -- 2.17.0.rc1.439.gca064e2955