Skip to content

Commit c6a5e1a

Browse files
committed
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
2 parents 6016ee0 + def390d commit c6a5e1a

File tree

2 files changed

+50
-24
lines changed

2 files changed

+50
-24
lines changed

builtin/repack.c

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -105,46 +105,38 @@ static void collect_pack_filenames(struct string_list *fname_nonkept_list,
105105
struct string_list *fname_kept_list,
106106
const struct string_list *extra_keep)
107107
{
108-
DIR *dir;
109-
struct dirent *e;
110-
char *fname;
108+
struct packed_git *p;
111109
struct strbuf buf = STRBUF_INIT;
112110

113-
if (!(dir = opendir(packdir)))
114-
return;
115-
116-
while ((e = readdir(dir)) != NULL) {
117-
size_t len;
111+
for (p = get_all_packs(the_repository); p; p = p->next) {
118112
int i;
113+
const char *base;
119114

120-
if (!strip_suffix(e->d_name, ".idx", &len))
115+
if (!p->pack_local)
121116
continue;
122117

123-
strbuf_reset(&buf);
124-
strbuf_add(&buf, e->d_name, len);
125-
strbuf_addstr(&buf, ".pack");
118+
base = pack_basename(p);
126119

127120
for (i = 0; i < extra_keep->nr; i++)
128-
if (!fspathcmp(buf.buf, extra_keep->items[i].string))
121+
if (!fspathcmp(base, extra_keep->items[i].string))
129122
break;
130123

131-
fname = xmemdupz(e->d_name, len);
124+
strbuf_reset(&buf);
125+
strbuf_addstr(&buf, base);
126+
strbuf_strip_suffix(&buf, ".pack");
132127

133-
if ((extra_keep->nr > 0 && i < extra_keep->nr) ||
134-
(file_exists(mkpath("%s/%s.keep", packdir, fname)))) {
135-
string_list_append_nodup(fname_kept_list, fname);
136-
} else {
128+
if ((extra_keep->nr > 0 && i < extra_keep->nr) || p->pack_keep)
129+
string_list_append(fname_kept_list, buf.buf);
130+
else {
137131
struct string_list_item *item;
138-
item = string_list_append_nodup(fname_nonkept_list,
139-
fname);
140-
if (file_exists(mkpath("%s/%s.mtimes", packdir, fname)))
132+
item = string_list_append(fname_nonkept_list, buf.buf);
133+
if (p->is_cruft)
141134
item->util = (void*)(uintptr_t)CRUFT_PACK;
142135
}
143136
}
144-
closedir(dir);
145-
strbuf_release(&buf);
146137

147138
string_list_sort(fname_kept_list);
139+
strbuf_release(&buf);
148140
}
149141

150142
static void remove_redundant_pack(const char *dir_name, const char *base_name)

t/t7700-repack.sh

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ test_expect_success 'repack --keep-pack' '
213213
test_create_repo keep-pack &&
214214
(
215215
cd keep-pack &&
216-
# avoid producing difference packs to delta/base choices
216+
# avoid producing different packs due to delta/base choices
217217
git config pack.window 0 &&
218218
P1=$(commit_and_pack 1) &&
219219
P2=$(commit_and_pack 2) &&
@@ -239,6 +239,10 @@ test_expect_success 'repack --keep-pack' '
239239
mv "$from" "$to" || return 1
240240
done &&
241241
242+
# A .idx file without a .pack should not stop us from
243+
# repacking what we can.
244+
touch .git/objects/pack/pack-does-not-exist.idx &&
245+
242246
git repack --cruft -d --keep-pack $P1 --keep-pack $P4 &&
243247
244248
ls .git/objects/pack/*.pack >newer-counts &&
@@ -247,6 +251,36 @@ test_expect_success 'repack --keep-pack' '
247251
)
248252
'
249253

254+
test_expect_success 'repacking fails when missing .pack actually means missing objects' '
255+
test_create_repo idx-without-pack &&
256+
(
257+
cd idx-without-pack &&
258+
259+
# Avoid producing different packs due to delta/base choices
260+
git config pack.window 0 &&
261+
P1=$(commit_and_pack 1) &&
262+
P2=$(commit_and_pack 2) &&
263+
P3=$(commit_and_pack 3) &&
264+
P4=$(commit_and_pack 4) &&
265+
ls .git/objects/pack/*.pack >old-counts &&
266+
test_line_count = 4 old-counts &&
267+
268+
# Remove one .pack file
269+
rm .git/objects/pack/$P2 &&
270+
271+
ls .git/objects/pack/*.pack >before-pack-dir &&
272+
273+
test_must_fail git fsck &&
274+
test_must_fail git repack --cruft -d 2>err &&
275+
grep "bad object" err &&
276+
277+
# Before failing, the repack did not modify the
278+
# pack directory.
279+
ls .git/objects/pack/*.pack >after-pack-dir &&
280+
test_cmp before-pack-dir after-pack-dir
281+
)
282+
'
283+
250284
test_expect_success 'bitmaps are created by default in bare repos' '
251285
git clone --bare .git bare.git &&
252286
rm -f bare.git/objects/pack/*.bitmap &&

0 commit comments

Comments
 (0)