Merge branch 'tb/repack-cleanup'
The recent change to "git repack" made it react less nicely when a leftover .idx file that no longer has the corresponding .pack file in the repository, which has been corrected. * tb/repack-cleanup: builtin/repack.c: avoid dir traversal in `collect_pack_filenames()` builtin/repack.c: only repack `.pack`s that exist
This commit is contained in:
@ -105,46 +105,38 @@ static void collect_pack_filenames(struct string_list *fname_nonkept_list,
|
|||||||
struct string_list *fname_kept_list,
|
struct string_list *fname_kept_list,
|
||||||
const struct string_list *extra_keep)
|
const struct string_list *extra_keep)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
struct packed_git *p;
|
||||||
struct dirent *e;
|
|
||||||
char *fname;
|
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
if (!(dir = opendir(packdir)))
|
for (p = get_all_packs(the_repository); p; p = p->next) {
|
||||||
return;
|
|
||||||
|
|
||||||
while ((e = readdir(dir)) != NULL) {
|
|
||||||
size_t len;
|
|
||||||
int i;
|
int i;
|
||||||
|
const char *base;
|
||||||
|
|
||||||
if (!strip_suffix(e->d_name, ".idx", &len))
|
if (!p->pack_local)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
strbuf_reset(&buf);
|
base = pack_basename(p);
|
||||||
strbuf_add(&buf, e->d_name, len);
|
|
||||||
strbuf_addstr(&buf, ".pack");
|
|
||||||
|
|
||||||
for (i = 0; i < extra_keep->nr; i++)
|
for (i = 0; i < extra_keep->nr; i++)
|
||||||
if (!fspathcmp(buf.buf, extra_keep->items[i].string))
|
if (!fspathcmp(base, extra_keep->items[i].string))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
fname = xmemdupz(e->d_name, len);
|
strbuf_reset(&buf);
|
||||||
|
strbuf_addstr(&buf, base);
|
||||||
|
strbuf_strip_suffix(&buf, ".pack");
|
||||||
|
|
||||||
if ((extra_keep->nr > 0 && i < extra_keep->nr) ||
|
if ((extra_keep->nr > 0 && i < extra_keep->nr) || p->pack_keep)
|
||||||
(file_exists(mkpath("%s/%s.keep", packdir, fname)))) {
|
string_list_append(fname_kept_list, buf.buf);
|
||||||
string_list_append_nodup(fname_kept_list, fname);
|
else {
|
||||||
} else {
|
|
||||||
struct string_list_item *item;
|
struct string_list_item *item;
|
||||||
item = string_list_append_nodup(fname_nonkept_list,
|
item = string_list_append(fname_nonkept_list, buf.buf);
|
||||||
fname);
|
if (p->is_cruft)
|
||||||
if (file_exists(mkpath("%s/%s.mtimes", packdir, fname)))
|
|
||||||
item->util = (void*)(uintptr_t)CRUFT_PACK;
|
item->util = (void*)(uintptr_t)CRUFT_PACK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
|
||||||
strbuf_release(&buf);
|
|
||||||
|
|
||||||
string_list_sort(fname_kept_list);
|
string_list_sort(fname_kept_list);
|
||||||
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_redundant_pack(const char *dir_name, const char *base_name)
|
static void remove_redundant_pack(const char *dir_name, const char *base_name)
|
||||||
|
@ -213,7 +213,7 @@ test_expect_success 'repack --keep-pack' '
|
|||||||
test_create_repo keep-pack &&
|
test_create_repo keep-pack &&
|
||||||
(
|
(
|
||||||
cd keep-pack &&
|
cd keep-pack &&
|
||||||
# avoid producing difference packs to delta/base choices
|
# avoid producing different packs due to delta/base choices
|
||||||
git config pack.window 0 &&
|
git config pack.window 0 &&
|
||||||
P1=$(commit_and_pack 1) &&
|
P1=$(commit_and_pack 1) &&
|
||||||
P2=$(commit_and_pack 2) &&
|
P2=$(commit_and_pack 2) &&
|
||||||
@ -239,6 +239,10 @@ test_expect_success 'repack --keep-pack' '
|
|||||||
mv "$from" "$to" || return 1
|
mv "$from" "$to" || return 1
|
||||||
done &&
|
done &&
|
||||||
|
|
||||||
|
# A .idx file without a .pack should not stop us from
|
||||||
|
# repacking what we can.
|
||||||
|
touch .git/objects/pack/pack-does-not-exist.idx &&
|
||||||
|
|
||||||
git repack --cruft -d --keep-pack $P1 --keep-pack $P4 &&
|
git repack --cruft -d --keep-pack $P1 --keep-pack $P4 &&
|
||||||
|
|
||||||
ls .git/objects/pack/*.pack >newer-counts &&
|
ls .git/objects/pack/*.pack >newer-counts &&
|
||||||
@ -247,6 +251,36 @@ test_expect_success 'repack --keep-pack' '
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'repacking fails when missing .pack actually means missing objects' '
|
||||||
|
test_create_repo idx-without-pack &&
|
||||||
|
(
|
||||||
|
cd idx-without-pack &&
|
||||||
|
|
||||||
|
# Avoid producing different packs due to delta/base choices
|
||||||
|
git config pack.window 0 &&
|
||||||
|
P1=$(commit_and_pack 1) &&
|
||||||
|
P2=$(commit_and_pack 2) &&
|
||||||
|
P3=$(commit_and_pack 3) &&
|
||||||
|
P4=$(commit_and_pack 4) &&
|
||||||
|
ls .git/objects/pack/*.pack >old-counts &&
|
||||||
|
test_line_count = 4 old-counts &&
|
||||||
|
|
||||||
|
# Remove one .pack file
|
||||||
|
rm .git/objects/pack/$P2 &&
|
||||||
|
|
||||||
|
ls .git/objects/pack/*.pack >before-pack-dir &&
|
||||||
|
|
||||||
|
test_must_fail git fsck &&
|
||||||
|
test_must_fail git repack --cruft -d 2>err &&
|
||||||
|
grep "bad object" err &&
|
||||||
|
|
||||||
|
# Before failing, the repack did not modify the
|
||||||
|
# pack directory.
|
||||||
|
ls .git/objects/pack/*.pack >after-pack-dir &&
|
||||||
|
test_cmp before-pack-dir after-pack-dir
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'bitmaps are created by default in bare repos' '
|
test_expect_success 'bitmaps are created by default in bare repos' '
|
||||||
git clone --bare .git bare.git &&
|
git clone --bare .git bare.git &&
|
||||||
rm -f bare.git/objects/pack/*.bitmap &&
|
rm -f bare.git/objects/pack/*.bitmap &&
|
||||||
|
Reference in New Issue
Block a user