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