commit 85fd8f07c38f9da35257c66dde7ce2357271c7b7 from: Mark Jamsek via: Thomas Adam date: Fri Jan 3 10:46:48 2025 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. ok stsp@ commit - 696b1a9d2a13d33de9e3d182e3ec8fd3818f8b58 commit + 85fd8f07c38f9da35257c66dde7ce2357271c7b7 blob - 79ff1430b9c3aafc77b7601269f359c9499e543b blob + 40d9d440f0ca6f4c9a2f302aebab7ffa7ffa680a --- tog/tog.c +++ tog/tog.c @@ -1325,8 +1325,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) { @@ -10058,23 +10066,29 @@ resolve_reflist_entry(struct got_object_id **commit_id case GOT_OBJ_TYPE_COMMIT: break; case GOT_OBJ_TYPE_TAG: - err = got_object_open_as_tag(&tag, repo, obj_id); - if (err) - goto done; - err = got_object_get_type(&obj_type, repo, - got_object_tag_get_object_id(tag)); - if (err) - goto done; - if (obj_type != GOT_OBJ_TYPE_COMMIT) { + /* + * Git allows nested tags that point to tags; keep peeling + * till we reach the bottom, which is always a non-tag ref. + */ + do { + if (tag != NULL) + got_object_tag_close(tag); + err = got_object_open_as_tag(&tag, repo, obj_id); + if (err) + goto done; + free(obj_id); + 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; + } while (obj_type == GOT_OBJ_TYPE_TAG); + if (obj_type != GOT_OBJ_TYPE_COMMIT) err = got_error(GOT_ERR_OBJ_TYPE); - goto done; - } - free(obj_id); - 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; - } break; default: err = got_error(GOT_ERR_OBJ_TYPE);