revision.c: better error reporting on ref from different worktrees
Make use of the new ref aliases to pass refs from another worktree around and access them from the current ref store instead. This does not change any functionality, but when a problem arises, we would like the reported messages to mention full ref aliases, like this: fatal: bad object worktrees/ztemp/HEAD warning: reflog of 'main-worktree/HEAD' references pruned commits instead of fatal: bad object HEAD warning: reflog of 'HEAD' references pruned commits which does not really tell where the refs are from. 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
Oct 21, 2018 at 10:08 UTC
ab3e1f78ae8ecb3371cf85a36d73fd341fad3884
3 files changed
+74
-11
revision.c
+13
-8
@@ -1177,7 +1177,7 @@ struct all_refs_cb {
1177
int warned_bad_reflog;
1178
struct rev_info *all_revs;
1179
const char *name_for_errormsg;
1180
- struct ref_store *refs;
1180
+ struct worktree *wt;
1181
};
1182
1183
int ref_excluded(struct string_list *ref_excludes, const char *path)
@@ -1214,7 +1214,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
1214
cb->all_revs = revs;
1215
cb->all_flags = flags;
1216
revs->rev_input_given = 1;
1217
- cb->refs = NULL;
1217
+ cb->wt = NULL;
1218
}
1219
1220
void clear_ref_exclusion(struct string_list **ref_excludes_p)
@@ -1277,15 +1277,20 @@ static int handle_one_reflog_ent(struct object_id *ooid, struct object_id *noid,
1277
return 0;
1278
}
1279
1280
-static int handle_one_reflog(const char *refname,
1280
+static int handle_one_reflog(const char *refname_in_wt,
1281
const struct object_id *oid,
1282
int flag, void *cb_data)
1283
{
1284
struct all_refs_cb *cb = cb_data;
1285
+ struct strbuf refname = STRBUF_INIT;
1286
+
1287
cb->warned_bad_reflog = 0;
1286
- cb->name_for_errormsg = refname;
1287
- refs_for_each_reflog_ent(cb->refs, refname,
1288
+ strbuf_worktree_ref(cb->wt, &refname, refname_in_wt);
1289
+ cb->name_for_errormsg = refname.buf;
1290
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
1291
+ refname.buf,
1292
handle_one_reflog_ent, cb_data);
1293
+ strbuf_release(&refname);
1294
return 0;
1295
}
1296
@@ -1300,8 +1305,8 @@ static void add_other_reflogs_to_pending(struct all_refs_cb *cb)
1305
if (wt->is_current)
1306
continue;
1307
1303
- cb->refs = get_worktree_ref_store(wt);
1304
- refs_for_each_reflog(cb->refs,
1308
+ cb->wt = wt;
1309
+ refs_for_each_reflog(get_worktree_ref_store(wt),
1310
handle_one_reflog,
1311
cb);
1312
}
@@ -1314,7 +1319,7 @@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
1319
1320
cb.all_revs = revs;
1321
cb.all_flags = flags;
1317
- cb.refs = get_main_ref_store(the_repository);
1322
+ cb.wt = NULL;
1323
for_each_reflog(handle_one_reflog, &cb);
1324
1325
if (!revs->single_worktree)
worktree.c
+46
-3
@@ -517,6 +517,45 @@ int parse_worktree_ref(const char *worktree_ref, const char **name,
517
return -1;
518
}
519
520
+void strbuf_worktree_ref(const struct worktree *wt,
521
+ struct strbuf *sb,
522
+ const char *refname)
523
+{
524
+ switch (ref_type(refname)) {
525
+ case REF_TYPE_PSEUDOREF:
526
+ case REF_TYPE_PER_WORKTREE:
527
+ if (wt && !wt->is_current) {
528
+ if (is_main_worktree(wt))
529
+ strbuf_addstr(sb, "main-worktree/");
530
+ else
531
+ strbuf_addf(sb, "worktrees/%s/", wt->id);
532
+ }
533
+ break;
534
+
535
+ case REF_TYPE_MAIN_PSEUDOREF:
536
+ case REF_TYPE_OTHER_PSEUDOREF:
537
+ break;
538
+
539
+ case REF_TYPE_NORMAL:
540
+ /*
541
+ * For shared refs, don't prefix worktrees/ or
542
+ * main-worktree/. It's not necessary and
543
+ * files-backend.c can't handle it anyway.
544
+ */
545
+ break;
546
+ }
547
+ strbuf_addstr(sb, refname);
548
+}
549
+
550
+const char *worktree_ref(const struct worktree *wt, const char *refname)
551
+{
552
+ static struct strbuf sb = STRBUF_INIT;
553
+
554
+ strbuf_reset(&sb);
555
+ strbuf_worktree_ref(wt, &sb, refname);
556
+ return sb.buf;
557
+}
558
+
559
int other_head_refs(each_ref_fn fn, void *cb_data)
560
{
561
struct worktree **worktrees, **p;
@@ -525,13 +564,17 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
564
worktrees = get_worktrees(0);
565
for (p = worktrees; *p; p++) {
566
struct worktree *wt = *p;
528
- struct ref_store *refs;
567
+ struct object_id oid;
568
+ int flag;
569
570
if (wt->is_current)
571
continue;
572
533
- refs = get_worktree_ref_store(wt);
534
- ret = refs_head_ref(refs, fn, cb_data);
573
+ if (!refs_read_ref_full(get_main_ref_store(the_repository),
574
+ worktree_ref(wt, "HEAD"),
575
+ RESOLVE_REF_READING,
576
+ &oid, &flag))
577
+ ret = fn(worktree_ref(wt, "HEAD"), &oid, flag, cb_data);
578
if (ret)
579
break;
580
}
worktree.h
+15
@@ -117,4 +117,19 @@ extern const char *worktree_git_path(const struct worktree *wt,
117
*/
118
int parse_worktree_ref(const char *worktree_ref, const char **name,
119
int *name_length, const char **ref);
120
+
121
+/*
122
+ * Return a refname suitable for access from the current ref store.
123
+ */
124
+void strbuf_worktree_ref(const struct worktree *wt,
125
+ struct strbuf *sb,
126
+ const char *refname);
127
+
128
+/*
129
+ * Return a refname suitable for access from the current ref
130
+ * store. The result will be destroyed at the next call.
131
+ */
132
+const char *worktree_ref(const struct worktree *wt,
133
+ const char *refname);
134
+
135
#endif