refs: use chdir_notify to update cached relative paths

Commit f57f37e2e1 (files-backend: remove the use of git_path(), 2017-03-26) introduced a regression when a relative $GIT_DIR is used in a working tree: - when we initialize the ref backend, we make a copy of get_git_dir(), which may be relative - later, we may call setup_work_tree() and chdir to the root of the working tree - further calls to the ref code will use the stored git directory, but relative paths will now point to the wrong place The new test in t1501 demonstrates one such instance (the bug causes us to write the ref update to the nonsense "relative/relative/.git"). Since setup_work_tree() now uses chdir_notify, we can just ask it update our relative paths when necessary. Reported-by: Rafael Ascensao <rafa.almas@gmail.com> Helped-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Mar 30, 2018 at 14:35 UTC fb9c2d27039a23457cb9710d86e00c51dfb910dc
3 files changed +21
refs/files-backend.c
+6
@@ -9,6 +9,7 @@
9 #include "../lockfile.h"
10 #include "../object.h"
11 #include "../dir.h"
12 +#include "../chdir-notify.h"
13
14 /*
15 * This backend uses the following flags in `ref_update::flags` for
@@ -106,6 +107,11 @@ static struct ref_store *files_ref_store_create(const char *gitdir,
107 refs->packed_ref_store = packed_ref_store_create(sb.buf, flags);
108 strbuf_release(&sb);
109
110 + chdir_notify_reparent("files-backend $GIT_DIR",
111 + &refs->gitdir);
112 + chdir_notify_reparent("files-backend $GIT_COMMONDIR",
113 + &refs->gitcommondir);
114 +
115 return ref_store;
116 }
117
refs/packed-backend.c
+3
@@ -5,6 +5,7 @@
5 #include "packed-backend.h"
6 #include "../iterator.h"
7 #include "../lockfile.h"
8 +#include "../chdir-notify.h"
9
10 enum mmap_strategy {
11 /*
@@ -202,6 +203,8 @@ struct ref_store *packed_ref_store_create(const char *path,
203 refs->store_flags = store_flags;
204
205 refs->path = xstrdup(path);
206 + chdir_notify_reparent("packed-refs", &refs->path);
207 +
208 return ref_store;
209 }
210
t/t1501-work-tree.sh
+12
@@ -431,4 +431,16 @@ test_expect_success 'error out gracefully on invalid $GIT_WORK_TREE' '
431 )
432 '
433
434 +test_expect_success 'refs work with relative gitdir and work tree' '
435 + git init relative &&
436 + git -C relative commit --allow-empty -m one &&
437 + git -C relative commit --allow-empty -m two &&
438 +
439 + GIT_DIR=relative/.git GIT_WORK_TREE=relative git reset HEAD^ &&
440 +
441 + git -C relative log -1 --format=%s >actual &&
442 + echo one >expect &&
443 + test_cmp expect actual
444 +'
445 +
446 test_done