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>
Nguyễn Thái Ngọc Duy committed
Aug 23, 2017 at 19:37 UTC
acd9544a8fdcf8095c82c91365c45dcb93112be3
2 files changed
+43
-1
revision.c
+27
-1
@@ -1132,6 +1132,7 @@ struct all_refs_cb {
1132
int warned_bad_reflog;
1133
struct rev_info *all_revs;
1134
const char *name_for_errormsg;
1135
+ struct ref_store *refs;
1136
};
1137
1138
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,
1169
cb->all_revs = revs;
1170
cb->all_flags = flags;
1171
revs->rev_input_given = 1;
1172
+ cb->refs = NULL;
1173
}
1174
1175
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,
1238
struct all_refs_cb *cb = cb_data;
1239
cb->warned_bad_reflog = 0;
1240
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);
1243
return 0;
1244
}
1245
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
+
1265
void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
1266
{
1267
struct all_refs_cb cb;
1268
1269
cb.all_revs = revs;
1270
cb.all_flags = flags;
1271
+ cb.refs = get_main_ref_store();
1272
for_each_reflog(handle_one_reflog, &cb);
1273
+
1274
+ if (!revs->single_worktree)
1275
+ add_other_reflogs_to_pending(&cb);
1276
}
1277
1278
static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
t/t5304-prune.sh
+16
@@ -304,4 +304,20 @@ test_expect_success 'prune: handle HEAD in multiple worktrees' '
304
test_cmp third-worktree/blob actual
305
'
306
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
+
323
test_done