Skip to content

Commit 561cb76

Browse files
committed
Merge branch 'jc/resolve-undo' into seen
* jc/resolve-undo: revision: mark blobs needed for resolve-undo as reachable
2 parents 94c9167 + 5a5ea14 commit 561cb76

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

builtin/fsck.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "decorate.h"
2020
#include "packfile.h"
2121
#include "object-store.h"
22+
#include "resolve-undo.h"
2223
#include "run-command.h"
2324
#include "worktree.h"
2425

@@ -757,6 +758,42 @@ static int fsck_cache_tree(struct cache_tree *it)
757758
return err;
758759
}
759760

761+
static int fsck_resolve_undo(struct index_state *istate)
762+
{
763+
struct string_list_item *item;
764+
struct string_list *resolve_undo = istate->resolve_undo;
765+
766+
if (!resolve_undo)
767+
return 0;
768+
769+
for_each_string_list_item(item, resolve_undo) {
770+
const char *path = item->string;
771+
struct resolve_undo_info *ru = item->util;
772+
int i;
773+
774+
if (!ru)
775+
continue;
776+
for (i = 0; i < 3; i++) {
777+
struct object *obj;
778+
779+
if (!ru->mode[i] || !S_ISREG(ru->mode[i]))
780+
continue;
781+
782+
obj = parse_object(the_repository, &ru->oid[i]);
783+
if (!obj) {
784+
error(_("%s: invalid sha1 pointer in resolve-undo"),
785+
oid_to_hex(&ru->oid[i]));
786+
errors_found |= ERROR_REFS;
787+
}
788+
obj->flags |= USED;
789+
fsck_put_object_name(&fsck_walk_options, &ru->oid[i],
790+
":(%d):%s", i, path);
791+
mark_object_reachable(obj);
792+
}
793+
}
794+
return 0;
795+
}
796+
760797
static void mark_object_for_connectivity(const struct object_id *oid)
761798
{
762799
struct object *obj = lookup_unknown_object(the_repository, oid);
@@ -938,6 +975,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
938975
}
939976
if (active_cache_tree)
940977
fsck_cache_tree(active_cache_tree);
978+
fsck_resolve_undo(&the_index);
941979
}
942980

943981
check_connectivity();

revision.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "bloom.h"
3434
#include "json-writer.h"
3535
#include "list-objects-filter-options.h"
36+
#include "resolve-undo.h"
3637

3738
volatile show_early_output_fn_t show_early_output;
3839

@@ -1696,6 +1697,39 @@ static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
16961697

16971698
}
16981699

1700+
static void add_resolve_undo_to_pending(struct index_state *istate, struct rev_info *revs)
1701+
{
1702+
struct string_list_item *item;
1703+
struct string_list *resolve_undo = istate->resolve_undo;
1704+
1705+
if (!resolve_undo)
1706+
return;
1707+
1708+
for_each_string_list_item(item, resolve_undo) {
1709+
const char *path = item->string;
1710+
struct resolve_undo_info *ru = item->util;
1711+
int i;
1712+
1713+
if (!ru)
1714+
continue;
1715+
for (i = 0; i < 3; i++) {
1716+
struct blob *blob;
1717+
1718+
if (!ru->mode[i] || !S_ISREG(ru->mode[i]))
1719+
continue;
1720+
1721+
blob = lookup_blob(revs->repo, &ru->oid[i]);
1722+
if (!blob) {
1723+
warning(_("resolve-undo records `%s` which is missing"),
1724+
oid_to_hex(&ru->oid[i]));
1725+
continue;
1726+
}
1727+
add_pending_object_with_path(revs, &blob->object, "",
1728+
ru->mode[i], path);
1729+
}
1730+
}
1731+
}
1732+
16991733
static void do_add_index_objects_to_pending(struct rev_info *revs,
17001734
struct index_state *istate,
17011735
unsigned int flags)
@@ -1724,6 +1758,8 @@ static void do_add_index_objects_to_pending(struct rev_info *revs,
17241758
add_cache_tree(istate->cache_tree, revs, &path, flags);
17251759
strbuf_release(&path);
17261760
}
1761+
1762+
add_resolve_undo_to_pending(istate, revs);
17271763
}
17281764

17291765
void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)

t/t2030-unresolve-info.sh

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,75 @@ test_expect_success 'rerere forget (add-add conflict)' '
194194
test_i18ngrep "no remembered" actual
195195
'
196196

197+
test_expect_success 'resolve-undo keeps blobs from gc' '
198+
git checkout -f main &&
199+
200+
# First make sure we do not have any cruft left in the object store
201+
git repack -a -d &&
202+
git prune --expire=now &&
203+
git prune-packed &&
204+
git gc --prune=now &&
205+
git fsck --unreachable >cruft &&
206+
test_must_be_empty cruft &&
207+
208+
# Now add three otherwise unreferenced blob objects to the index
209+
git reset --hard &&
210+
B1=$(echo "resolve undo test data 1" | git hash-object -w --stdin) &&
211+
B2=$(echo "resolve undo test data 2" | git hash-object -w --stdin) &&
212+
B3=$(echo "resolve undo test data 3" | git hash-object -w --stdin) &&
213+
git update-index --add --index-info <<-EOF &&
214+
100644 $B1 1 frotz
215+
100644 $B2 2 frotz
216+
100644 $B3 3 frotz
217+
EOF
218+
219+
# These three blob objects are reachable (only) from the index
220+
git fsck --unreachable >cruft &&
221+
test_must_be_empty cruft &&
222+
# and they should be protected from GC
223+
git gc --prune=now &&
224+
git cat-file -e $B1 &&
225+
git cat-file -e $B2 &&
226+
git cat-file -e $B3 &&
227+
228+
# Now resolve the conflicted path
229+
B0=$(echo "resolve undo test data 0" | git hash-object -w --stdin) &&
230+
git update-index --add --cacheinfo 100644,$B0,frotz &&
231+
232+
# These three blob objects are now reachable only from the resolve-undo
233+
git fsck --unreachable >cruft &&
234+
test_must_be_empty cruft &&
235+
236+
# and they should survive GC
237+
git gc --prune=now &&
238+
git cat-file -e $B0 &&
239+
git cat-file -e $B1 &&
240+
git cat-file -e $B2 &&
241+
git cat-file -e $B3 &&
242+
243+
# Now we switch away, which nukes resolve-undo, and
244+
# blobs B0..B3 would become dangling. fsck should
245+
# notice that they are now unreachable.
246+
git checkout -f side &&
247+
git fsck --unreachable >cruft &&
248+
sort cruft >actual &&
249+
sort <<-EOF >expect &&
250+
unreachable blob $B0
251+
unreachable blob $B1
252+
unreachable blob $B2
253+
unreachable blob $B3
254+
EOF
255+
test_cmp expect actual &&
256+
257+
# And they should go away when gc runs.
258+
git gc --prune=now &&
259+
git fsck --unreachable >cruft &&
260+
test_must_be_empty cruft &&
261+
262+
test_must_fail git cat-file -e $B0 &&
263+
test_must_fail git cat-file -e $B1 &&
264+
test_must_fail git cat-file -e $B2 &&
265+
test_must_fail git cat-file -e $B3
266+
'
267+
197268
test_done

0 commit comments

Comments
 (0)