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>
This commit is contained in:
parent
78db709ae5
commit
be7c6d467e
32
pack-refs.c
32
pack-refs.c
@ -60,6 +60,37 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
|
|||||||
return 0;
|
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 */
|
/* make sure nobody touched the ref, and unlink */
|
||||||
static void prune_ref(struct ref_to_prune *r)
|
static void prune_ref(struct ref_to_prune *r)
|
||||||
{
|
{
|
||||||
@ -68,6 +99,7 @@ static void prune_ref(struct ref_to_prune *r)
|
|||||||
if (lock) {
|
if (lock) {
|
||||||
unlink_or_warn(git_path("%s", r->name));
|
unlink_or_warn(git_path("%s", r->name));
|
||||||
unlock_ref(lock);
|
unlock_ref(lock);
|
||||||
|
try_remove_empty_parents(r->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,12 @@ test_expect_success 'see if git pack-refs --prune remove ref files' '
|
|||||||
! test -f .git/refs/heads/f
|
! 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 \
|
test_expect_success \
|
||||||
'git branch g should work when git branch g/h has been deleted' \
|
'git branch g should work when git branch g/h has been deleted' \
|
||||||
'git branch g/h &&
|
'git branch g/h &&
|
||||||
|
Loading…
Reference in New Issue
Block a user