diff options
author | Greg Price <price@ksplice.com> | 2010-07-06 19:29:19 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2010-07-07 09:11:37 -0700 |
commit | be7c6d467e8cc4104e1a15e8ff2d7b207624c685 (patch) | |
tree | cb23a29c9a86b0017534892ed0db31e9fe821541 /pack-refs.c | |
parent | 78db709ae59da26de76264b79df3a7dc4d87e65c (diff) | |
download | git-be7c6d467e8cc4104e1a15e8ff2d7b207624c685.tar.gz git-be7c6d467e8cc4104e1a15e8ff2d7b207624c685.tar.xz |
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>
Diffstat (limited to 'pack-refs.c')
-rw-r--r-- | pack-refs.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/pack-refs.c b/pack-refs.c index 7f43f8ac3..129057026 100644 --- a/pack-refs.c +++ b/pack-refs.c @@ -60,6 +60,37 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, return 0; } +/* + * Remove empty parents, but spare refs/ and immediate subdirs. + * Note: munges *name. + */ +static void try_remove_empty_parents(char *name) +{ + char *p, *q; + int i; + p = name; + for (i = 0; i < 2; i++) { /* refs/{heads,tags,...}/ */ + while (*p && *p != '/') + p++; + /* tolerate duplicate slashes; see check_ref_format() */ + while (*p == '/') + p++; + } + for (q = p; *q; q++) + ; + while (1) { + while (q > p && *q != '/') + q--; + while (q > p && *(q-1) == '/') + q--; + if (q == p) + break; + *q = '\0'; + if (rmdir(git_path("%s", name))) + break; + } +} + /* make sure nobody touched the ref, and unlink */ static void prune_ref(struct ref_to_prune *r) { @@ -68,6 +99,7 @@ static void prune_ref(struct ref_to_prune *r) if (lock) { unlink_or_warn(git_path("%s", r->name)); unlock_ref(lock); + try_remove_empty_parents(r->name); } } |