revision.c: better error reporting on ref from different worktrees
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Sun, 21 Oct 2018 08:08:56 +0000 (10:08 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 22 Oct 2018 04:32:29 +0000 (13:32 +0900)
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>
revision.c
worktree.c
worktree.h
index 63aae722c1ecb51987c2a4d76ff98ab79918029d..8ce660e3b1c4165e97def27265e2e8560499b50e 100644 (file)
@@ -1177,7 +1177,7 @@ struct all_refs_cb {
        int warned_bad_reflog;
        struct rev_info *all_revs;
        const char *name_for_errormsg;
-       struct ref_store *refs;
+       struct worktree *wt;
 };
 
 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,
        cb->all_revs = revs;
        cb->all_flags = flags;
        revs->rev_input_given = 1;
-       cb->refs = NULL;
+       cb->wt = NULL;
 }
 
 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,
        return 0;
 }
 
-static int handle_one_reflog(const char *refname,
+static int handle_one_reflog(const char *refname_in_wt,
                             const struct object_id *oid,
                             int flag, void *cb_data)
 {
        struct all_refs_cb *cb = cb_data;
+       struct strbuf refname = STRBUF_INIT;
+
        cb->warned_bad_reflog = 0;
-       cb->name_for_errormsg = refname;
-       refs_for_each_reflog_ent(cb->refs, refname,
+       strbuf_worktree_ref(cb->wt, &refname, refname_in_wt);
+       cb->name_for_errormsg = refname.buf;
+       refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+                                refname.buf,
                                 handle_one_reflog_ent, cb_data);
+       strbuf_release(&refname);
        return 0;
 }
 
@@ -1300,8 +1305,8 @@ static void add_other_reflogs_to_pending(struct all_refs_cb *cb)
                if (wt->is_current)
                        continue;
 
-               cb->refs = get_worktree_ref_store(wt);
-               refs_for_each_reflog(cb->refs,
+               cb->wt = wt;
+               refs_for_each_reflog(get_worktree_ref_store(wt),
                                     handle_one_reflog,
                                     cb);
        }
@@ -1314,7 +1319,7 @@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
 
        cb.all_revs = revs;
        cb.all_flags = flags;
-       cb.refs = get_main_ref_store(the_repository);
+       cb.wt = NULL;
        for_each_reflog(handle_one_reflog, &cb);
 
        if (!revs->single_worktree)
index 4193496f2a01b0d5dcfd7c48448a1a27644f7068..e6a65ec6842d1a18a0463d774be0ab920cbee5a9 100644 (file)
@@ -517,6 +517,45 @@ int parse_worktree_ref(const char *worktree_ref, const char **name,
        return -1;
 }
 
+void strbuf_worktree_ref(const struct worktree *wt,
+                        struct strbuf *sb,
+                        const char *refname)
+{
+       switch (ref_type(refname)) {
+       case REF_TYPE_PSEUDOREF:
+       case REF_TYPE_PER_WORKTREE:
+               if (wt && !wt->is_current) {
+                       if (is_main_worktree(wt))
+                               strbuf_addstr(sb, "main-worktree/");
+                       else
+                               strbuf_addf(sb, "worktrees/%s/", wt->id);
+               }
+               break;
+
+       case REF_TYPE_MAIN_PSEUDOREF:
+       case REF_TYPE_OTHER_PSEUDOREF:
+               break;
+
+       case REF_TYPE_NORMAL:
+               /*
+                * For shared refs, don't prefix worktrees/ or
+                * main-worktree/. It's not necessary and
+                * files-backend.c can't handle it anyway.
+                */
+               break;
+       }
+       strbuf_addstr(sb, refname);
+}
+
+const char *worktree_ref(const struct worktree *wt, const char *refname)
+{
+       static struct strbuf sb = STRBUF_INIT;
+
+       strbuf_reset(&sb);
+       strbuf_worktree_ref(wt, &sb, refname);
+       return sb.buf;
+}
+
 int other_head_refs(each_ref_fn fn, void *cb_data)
 {
        struct worktree **worktrees, **p;
@@ -525,13 +564,17 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
        worktrees = get_worktrees(0);
        for (p = worktrees; *p; p++) {
                struct worktree *wt = *p;
-               struct ref_store *refs;
+               struct object_id oid;
+               int flag;
 
                if (wt->is_current)
                        continue;
 
-               refs = get_worktree_ref_store(wt);
-               ret = refs_head_ref(refs, fn, cb_data);
+               if (!refs_read_ref_full(get_main_ref_store(the_repository),
+                                       worktree_ref(wt, "HEAD"),
+                                       RESOLVE_REF_READING,
+                                       &oid, &flag))
+                       ret = fn(worktree_ref(wt, "HEAD"), &oid, flag, cb_data);
                if (ret)
                        break;
        }
index 440bb219ddc585979f9f6a4c9d994f0d5057244d..1164ca396ff628412793d62ff8a1b3d7e84ea058 100644 (file)
@@ -117,4 +117,19 @@ extern const char *worktree_git_path(const struct worktree *wt,
  */
 int parse_worktree_ref(const char *worktree_ref, const char **name,
                       int *name_length, const char **ref);
+
+/*
+ * Return a refname suitable for access from the current ref store.
+ */
+void strbuf_worktree_ref(const struct worktree *wt,
+                        struct strbuf *sb,
+                        const char *refname);
+
+/*
+ * Return a refname suitable for access from the current ref
+ * store. The result will be destroyed at the next call.
+ */
+const char *worktree_ref(const struct worktree *wt,
+                        const char *refname);
+
 #endif