Download raw body.
tog: make ref view selection of non-commit tags non-fatal
Git allows tags to point to commits, trees, blobs, and even other tags.
Currently, selecting a tag that points to anything but a commit causes a
fatal error in tog's ref view. This change instead draws a message to
the status line, and also enables selecting nested tags that resolve to
a commit.
I've run out of time tonight to write a test case--I'll do this after
zzz--but to test the nested tag to commit case:
# make tag to base commit
$ got tag -m "test tag" testtag
# make tag to previous tag
$ git tag -a nestedtag -m "nested tag" testtag
then invoke `tog ref` without this diff and select refs/tags/nestedtag:
tog: wrong type of object
With this diff, the log view will instead open starting traversal from
the tagged commit in the first tag (i.e., testtag).
To test a tag to a blob or tree object, you need to use git to create
the tag as this is not allowed by design in got:
$ git tag tag2blob $blobid
Selecting the refs/tags/tag2blob entry in tog's ref view without this
diff causes tog to exit with a fatal error. With this diff, a message is
drawn to the status line: "commit reference required". This is also a
good test case for why the wtimeout(3) fix is needed: without that fix,
the message is not visible when selecting tag2blob after entering a
compound key (e.g., 2j).
commit 754667b95534144f355facd02c994a66baca0aa1 (main)
from: Mark Jamsek <mark@jamsek.dev>
date: Wed Dec 25 13:57:30 2024 UTC
tog: make ref view selection of non-commit tags non-fatal
Tags can point to all git objects: commits, trees, blobs, and tags.
Selecting a tag that points to any object other than a commit causes a
fatal error. Instead, report a message to the status line. Similarly,
nested tags may resolve to a commit, which currently errors. Instead,
keep peeling till we reach the bottom and if it's a commit, use it for
the requested view.
M tog/tog.c | 32+ 16-
1 file changed, 32 insertions(+), 16 deletions(-)
commit - cfe9343a9f6a872cd65b1086e6dab68010b19d98
commit + 754667b95534144f355facd02c994a66baca0aa1
blob - 7dd3a24c5a2515f0073943bd56830d25bf86f45a
blob + 17f68383e6756d777cb62720ac994c2ed1f81c0b
--- tog/tog.c
+++ tog/tog.c
@@ -1320,8 +1320,16 @@ view_request_new(struct tog_view **requested, struct t
view_get_split(view, &y, &x);
err = view_dispatch_request(&new_view, view, request, y, x);
- if (err)
- return err;
+ if (err) {
+ /*
+ * The ref view expects its selected entry to resolve to
+ * a commit object id to open either a log or tree view.
+ */
+ if (err->code != GOT_ERR_OBJ_TYPE)
+ return err;
+ view->action = "commit reference required";
+ return NULL;
+ }
if (view_is_parent_view(view) && view->mode == TOG_VIEW_SPLIT_HRZN &&
request != TOG_VIEW_HELP) {
@@ -10026,24 +10034,32 @@ resolve_reflist_entry(struct got_object_id **commit_id
*commit_id = obj_id;
break;
case GOT_OBJ_TYPE_TAG:
- err = got_object_open_as_tag(&tag, repo, obj_id);
- if (err)
- goto done;
- free(obj_id);
- err = got_object_get_type(&obj_type, repo,
- got_object_tag_get_object_id(tag));
- if (err)
- goto done;
+ /*
+ * Git allows nested tags that point to tags; keep peeling
+ * till we reach the bottom, which is always a non-tag ref.
+ */
+ while (obj_type == GOT_OBJ_TYPE_TAG) {
+ if (tag != NULL)
+ got_object_tag_close(tag);
+ err = got_object_open_as_tag(&tag, repo, obj_id);
+ free(obj_id);
+ if (err)
+ goto done;
+ obj_id = got_object_id_dup(
+ got_object_tag_get_object_id(tag));
+ if (obj_id == NULL) {
+ err = got_error_from_errno("got_object_id_dup");
+ goto done;
+ }
+ err = got_object_get_type(&obj_type, repo, obj_id);
+ if (err)
+ goto done;
+ }
+ *commit_id = obj_id;
if (obj_type != GOT_OBJ_TYPE_COMMIT) {
err = got_error(GOT_ERR_OBJ_TYPE);
goto done;
}
- *commit_id = got_object_id_dup(
- got_object_tag_get_object_id(tag));
- if (*commit_id == NULL) {
- err = got_error_from_errno("got_object_id_dup");
- goto done;
- }
break;
default:
err = got_error(GOT_ERR_OBJ_TYPE);
--
Mark Jamsek <https://bsdbox.org>
GPG: F2FF 13DE 6A06 C471 CA80 E6E2 2930 DC66 86EE CF68
tog: make ref view selection of non-commit tags non-fatal