Skip to content

Commit acd9544

Browse files
pcloudsgitster
authored andcommitted
revision.c: --reflog add HEAD reflog from all worktrees
Note that add_other_reflogs_to_pending() is a bit inefficient, since it scans reflog for all refs of each worktree, including shared refs, so the shared ref's reflog is scanned over and over again. We could update refs API to pass "per-worktree only" flag to avoid that. But long term we should be able to obtain a "per-worktree only" ref store and would need to revert the changes in reflog iteration API. So let's just wait until then. add_reflogs_to_pending() is called by reachable.c so by default "git prune" will examine reflog from all worktrees. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 944b4e3 commit acd9544

2 files changed

Lines changed: 43 additions & 1 deletion

File tree

revision.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,7 @@ struct all_refs_cb {
11321132
int warned_bad_reflog;
11331133
struct rev_info *all_revs;
11341134
const char *name_for_errormsg;
1135+
struct ref_store *refs;
11351136
};
11361137

11371138
int ref_excluded(struct string_list *ref_excludes, const char *path)
@@ -1168,6 +1169,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
11681169
cb->all_revs = revs;
11691170
cb->all_flags = flags;
11701171
revs->rev_input_given = 1;
1172+
cb->refs = NULL;
11711173
}
11721174

11731175
void clear_ref_exclusion(struct string_list **ref_excludes_p)
@@ -1236,17 +1238,41 @@ static int handle_one_reflog(const char *path, const struct object_id *oid,
12361238
struct all_refs_cb *cb = cb_data;
12371239
cb->warned_bad_reflog = 0;
12381240
cb->name_for_errormsg = path;
1239-
for_each_reflog_ent(path, handle_one_reflog_ent, cb_data);
1241+
refs_for_each_reflog_ent(cb->refs, path,
1242+
handle_one_reflog_ent, cb_data);
12401243
return 0;
12411244
}
12421245

1246+
static void add_other_reflogs_to_pending(struct all_refs_cb *cb)
1247+
{
1248+
struct worktree **worktrees, **p;
1249+
1250+
worktrees = get_worktrees(0);
1251+
for (p = worktrees; *p; p++) {
1252+
struct worktree *wt = *p;
1253+
1254+
if (wt->is_current)
1255+
continue;
1256+
1257+
cb->refs = get_worktree_ref_store(wt);
1258+
refs_for_each_reflog(cb->refs,
1259+
handle_one_reflog,
1260+
cb);
1261+
}
1262+
free_worktrees(worktrees);
1263+
}
1264+
12431265
void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
12441266
{
12451267
struct all_refs_cb cb;
12461268

12471269
cb.all_revs = revs;
12481270
cb.all_flags = flags;
1271+
cb.refs = get_main_ref_store();
12491272
for_each_reflog(handle_one_reflog, &cb);
1273+
1274+
if (!revs->single_worktree)
1275+
add_other_reflogs_to_pending(&cb);
12501276
}
12511277

12521278
static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,

t/t5304-prune.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,4 +304,20 @@ test_expect_success 'prune: handle HEAD in multiple worktrees' '
304304
test_cmp third-worktree/blob actual
305305
'
306306

307+
test_expect_success 'prune: handle HEAD reflog in multiple worktrees' '
308+
git config core.logAllRefUpdates true &&
309+
echo "lost blob for third-worktree" >expected &&
310+
(
311+
cd third-worktree &&
312+
cat ../expected >blob &&
313+
git add blob &&
314+
git commit -m "second commit in third" &&
315+
git reset --hard HEAD^
316+
) &&
317+
git prune --expire=now &&
318+
SHA1=`git hash-object expected` &&
319+
git -C third-worktree show "$SHA1" >actual &&
320+
test_cmp expected actual
321+
'
322+
307323
test_done

0 commit comments

Comments
 (0)