@matheusbsbs / matheus-bagliano / commits / be7c6d467e
Fork 0

pack-refs: remove newly empty directories

In a large repository which uses directories to organize many refs, "git pack-refs --all --prune" does not improve performance so much as it should, unless we remove all the now-empty directories as well. Signed-off-by: Greg Price <price@ksplice.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Greg Price committed Jul 6, 2010 at 19:29 UTC be7c6d467e8cc4104e1a15e8ff2d7b207624c685
2 files changed +38
pack-refs.c
+32
@@ -60,6 +60,37 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
60 return 0;
61 }
62
63 +/*
64 + * Remove empty parents, but spare refs/ and immediate subdirs.
65 + * Note: munges *name.
66 + */
67 +static void try_remove_empty_parents(char *name)
68 +{
69 + char *p, *q;
70 + int i;
71 + p = name;
72 + for (i = 0; i < 2; i++) { /* refs/{heads,tags,...}/ */
73 + while (*p && *p != '/')
74 + p++;
75 + /* tolerate duplicate slashes; see check_ref_format() */
76 + while (*p == '/')
77 + p++;
78 + }
79 + for (q = p; *q; q++)
80 + ;
81 + while (1) {
82 + while (q > p && *q != '/')
83 + q--;
84 + while (q > p && *(q-1) == '/')
85 + q--;
86 + if (q == p)
87 + break;
88 + *q = '\0';
89 + if (rmdir(git_path("%s", name)))
90 + break;
91 + }
92 +}
93 +
94 /* make sure nobody touched the ref, and unlink */
95 static void prune_ref(struct ref_to_prune *r)
96 {
@@ -68,6 +99,7 @@ static void prune_ref(struct ref_to_prune *r)
99 if (lock) {
100 unlink_or_warn(git_path("%s", r->name));
101 unlock_ref(lock);
102 + try_remove_empty_parents(r->name);
103 }
104 }
105
t/t3210-pack-refs.sh
+6
@@ -60,6 +60,12 @@ test_expect_success 'see if git pack-refs --prune remove ref files' '
60 ! test -f .git/refs/heads/f
61 '
62
63 +test_expect_success 'see if git pack-refs --prune removes empty dirs' '
64 + git branch r/s/t &&
65 + git pack-refs --all --prune &&
66 + ! test -e .git/refs/heads/r
67 +'
68 +
69 test_expect_success \
70 'git branch g should work when git branch g/h has been deleted' \
71 'git branch g/h &&