[PATCH] setup: recognize bare repositories with packed-refs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When a garbage collected bare git repository is added to another git
repository, the refs/ subdirectory is empty.  In case-cases when such a
repository is added into another repository directly, it no longer is
detected as a valid. Git doesn't preserve empty paths so refs/
subdirectory is not present in parent git.  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
+'
+
 test_expect_success 'gc.repackFilterTo store filtered out objects' '
 	test_when_finished "rm -rf bare.git filtered.git" &&
 
-- 
2.42.0





[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux