Empty directories in $GIT_DIR/refs increases overhead at startup. Removing a ref does not remove its parent directories even if it's the only file left so empty directories will be hanging around. pack-refs was taught of cleaning up empty directories in be7c6d4 (pack-refs: remove newly empty directories - 2010-07-06), but it only checks parent directories of packed refs only. Already empty dirs are left untouched. This patch removes empty directories as we see while traversing $GIT_DIR/refs and reverts be7c6d4 because it's no longer needed. Some directories, even if empty, are not removed: - refs: this one is needed to recognize a git repository - refs/heads and refs/tags: these are created by init-db, people may expect them to always be there Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- I don't think the a few extra rmdir()s from time to time at startup are going to cause any problems. Making delete_ref() delete empty directories takes more effort and probably not worth it. Of course this only works if people do not expect empty directories to stay in $GIT_DIR/refs permanently. They now may need to put .keep file in to keep parent directories from being removed. Would anyone do that? pack-refs.c | 32 -------------------------------- refs.c | 14 +++++++++++++- t/t3210-pack-refs.sh | 6 ------ 3 files changed, 13 insertions(+), 39 deletions(-) diff --git a/pack-refs.c b/pack-refs.c index f09a054..ec9e476 100644 --- a/pack-refs.c +++ b/pack-refs.c @@ -60,37 +60,6 @@ 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_refname_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) { @@ -99,7 +68,6 @@ 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); } } diff --git a/refs.c b/refs.c index b8843bb..80ebba3 100644 --- a/refs.c +++ b/refs.c @@ -343,6 +343,12 @@ static void get_ref_dir(struct ref_cache *refs, const char *base, struct dirent *de; int baselen = strlen(base); char *refname = xmalloc(baselen + 257); + int empty_dir = 1; + + if (!strcmp(base, "refs") || + !strcmp(base, "refs/heads") || + !strcmp(base, "refs/tags")) + empty_dir = 0; memcpy(refname, base, baselen); if (baselen && base[baselen-1] != '/') @@ -355,8 +361,12 @@ static void get_ref_dir(struct ref_cache *refs, const char *base, int namelen; const char *refdir; - if (de->d_name[0] == '.') + if (de->d_name[0] == '.') { + if (de->d_name[1] != '.' || de->d_name[2]) + empty_dir = 0; continue; + } + empty_dir = 0; namelen = strlen(de->d_name); if (namelen > 255) continue; @@ -387,6 +397,8 @@ static void get_ref_dir(struct ref_cache *refs, const char *base, } free(refname); closedir(dir); + if (empty_dir) + rmdir(path); } } diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index cd04361..5251740 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -60,12 +60,6 @@ test_expect_success 'see if git pack-refs --prune remove ref files' ' ! test -f .git/refs/heads/f ' -test_expect_success 'see if git pack-refs --prune removes empty dirs' ' - git branch r/s/t && - git pack-refs --all --prune && - ! test -e .git/refs/heads/r -' - test_expect_success \ 'git branch g should work when git branch g/h has been deleted' \ 'git branch g/h && -- 1.7.8.36.g69ee2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html