On 2023.11.17 21:32, Adam Majer wrote: > In a garbage collected bare git repository, the refs/ subdirectory is > empty. In use-cases when such a repository is directly added into > another repository, it no longer is detected as valid. Git doesn't > preserve empty paths so refs/ subdirectory is not present. Simply > creating an empty refs/ subdirectory fixes this problem. > > Looking more carefully, there are two backends to handle various refs in > git -- the files backend that uses refs/ subdirectory and the > packed-refs backend that uses packed-refs file. If references are not > found in refs/ subdirectory (or directory doesn't exist), the > packed-refs directory will be consulted. Garbage collected repository > will have all its references in packed-refs file. > > To allow the use-case when packed-refs is the only source of refs and > refs/ subdirectory is simply not present, augment 'is_git_directory()' > setup function to look for packed-refs file as an alternative to refs/ > subdirectory. > > Signed-off-by: Adam Majer <adamm@xxxxxxxxxxx> > --- > setup.c | 10 +++++++--- > t/t6500-gc.sh | 8 ++++++++ > 2 files changed, 15 insertions(+), 3 deletions(-) > > diff --git a/setup.c b/setup.c > index fc592dc6dd..2a6dda6ae9 100644 > --- a/setup.c > +++ b/setup.c > @@ -348,7 +348,7 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir) > * > * - either an objects/ directory _or_ the proper > * GIT_OBJECT_DIRECTORY environment variable > - * - a refs/ directory > + * - a refs/ directory or packed-refs file > * - either a HEAD symlink or a HEAD file that is formatted as > * a proper "ref:", or a regular file HEAD that has a properly > * formatted sha1 object name. > @@ -384,8 +384,12 @@ int is_git_directory(const char *suspect) > > strbuf_setlen(&path, len); > strbuf_addstr(&path, "/refs"); > - if (access(path.buf, X_OK)) > - goto done; > + if (access(path.buf, X_OK)) { > + strbuf_setlen(&path, len); > + strbuf_addstr(&path, "/packed-refs"); > + if (access(path.buf, R_OK)) > + goto done; > + } > > ret = 1; > done: > diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh > index 18fe1c25e6..e81eb7d2ab 100755 > --- a/t/t6500-gc.sh > +++ b/t/t6500-gc.sh > @@ -214,6 +214,14 @@ test_expect_success 'gc.repackFilter launches repack with a filter' ' > grep -E "^trace: (built-in|exec|run_command): git repack .* --filter=blob:none ?.*" trace.out > ' > > +test_expect_success 'remove empty refs/ subdirectory' ' > + git -C bare.git cat-file -e 60dd8ad7d8ed49005c18b7ce9f5b7a45c28df814 && > + test_dir_is_empty bare.git/refs/heads && > + test_dir_is_empty bare.git/refs/tags && > + rm -r bare.git/refs && > + GIT_DIR="$PWD"/bare.git git -C bare.git cat-file -e 60dd8ad7d8ed49005c18b7ce9f5b7a45c28df814 > +' > + Two suggestions for the test here: 1) Can you give the test a more descriptive name, such as "GCed bare repos still recognized"? 2) Can you add a check that bare.git/packed-refs exists? Other than that, looks good to me. Reviewed-by: Josh Steadmon <steadmon@xxxxxxxxxx>