commit d4efa91b5a0b6d8d90ff1f847518ff59c17682e3 from: Stefan Sperling date: Tue Jan 14 13:25:55 2020 UTC handle Git-style "lightweight" tags in got tag -l commit - 6586ea880db352b50506623a050aa8690c46d804 commit + d4efa91b5a0b6d8d90ff1f847518ff59c17682e3 blob - 8dafea8ba4c83120ee4dc4873ed2292d55c988cb blob + 4b74c056672711e1ebae75fd3d7c79da18c35d82 --- got/got.c +++ got/got.c @@ -3764,6 +3764,7 @@ cmp_tags(void *arg, int *cmp, struct got_reference *re struct got_repository *repo = arg; struct got_object_id *id1, *id2 = NULL; struct got_tag_object *tag1 = NULL, *tag2 = NULL; + struct got_commit_object *commit1 = NULL, *commit2 = NULL; time_t time1, time2; *cmp = 0; @@ -3772,18 +3773,31 @@ cmp_tags(void *arg, int *cmp, struct got_reference *re if (err) return err; err = got_object_open_as_tag(&tag1, repo, id1); - if (err) - goto done; + if (err) { + if (err->code != GOT_ERR_OBJ_TYPE) + goto done; + /* "lightweight" tag */ + err = got_object_open_as_commit(&commit1, repo, id1); + if (err) + goto done; + time1 = got_object_commit_get_committer_time(commit1); + } else + time1 = got_object_tag_get_tagger_time(tag1); err = got_ref_resolve(&id2, repo, ref2); if (err) goto done; err = got_object_open_as_tag(&tag2, repo, id2); - if (err) - goto done; - - time1 = got_object_tag_get_tagger_time(tag1); - time2 = got_object_tag_get_tagger_time(tag2); + if (err) { + if (err->code != GOT_ERR_OBJ_TYPE) + goto done; + /* "lightweight" tag */ + err = got_object_open_as_commit(&commit2, repo, id2); + if (err) + goto done; + time2 = got_object_commit_get_committer_time(commit2); + } else + time2 = got_object_tag_get_tagger_time(tag2); /* Put latest tags first. */ if (time1 < time2) @@ -3799,6 +3813,10 @@ done: got_object_tag_close(tag1); if (tag2) got_object_tag_close(tag2); + if (commit1) + got_object_commit_close(commit1); + if (commit2) + got_object_commit_close(commit2); return err; } @@ -3819,9 +3837,11 @@ list_tags(struct got_repository *repo, struct got_work const char *refname; char *refstr, *tagmsg0, *tagmsg, *line, *id_str, *datestr; char datebuf[26]; + const char *tagger; time_t tagger_time; struct got_object_id *id; struct got_tag_object *tag; + struct got_commit_object *commit = NULL; refname = got_ref_get_name(re->ref); if (strncmp(refname, "refs/tags/", 10) != 0) @@ -3839,40 +3859,74 @@ list_tags(struct got_repository *repo, struct got_work if (err) break; err = got_object_open_as_tag(&tag, repo, id); - free(id); - if (err) - break; - printf("from: %s\n", got_object_tag_get_tagger(tag)); - tagger_time = got_object_tag_get_tagger_time(tag); + if (err) { + if (err->code != GOT_ERR_OBJ_TYPE) { + free(id); + break; + } + /* "lightweight" tag */ + err = got_object_open_as_commit(&commit, repo, id); + if (err) { + free(id); + break; + } + tagger = got_object_commit_get_committer(commit); + tagger_time = + got_object_commit_get_committer_time(commit); + err = got_object_id_str(&id_str, id); + free(id); + if (err) + break; + } else { + free(id); + tagger = got_object_tag_get_tagger(tag); + tagger_time = got_object_tag_get_tagger_time(tag); + err = got_object_id_str(&id_str, + got_object_tag_get_object_id(tag)); + if (err) + break; + } + printf("from: %s\n", tagger); datestr = get_datestr(&tagger_time, datebuf); if (datestr) printf("date: %s UTC\n", datestr); - err = got_object_id_str(&id_str, - got_object_tag_get_object_id(tag)); - if (err) - break; - switch (got_object_tag_get_object_type(tag)) { - case GOT_OBJ_TYPE_BLOB: - printf("object: %s %s\n", GOT_OBJ_LABEL_BLOB, id_str); - break; - case GOT_OBJ_TYPE_TREE: - printf("object: %s %s\n", GOT_OBJ_LABEL_TREE, id_str); - break; - case GOT_OBJ_TYPE_COMMIT: + if (commit) printf("object: %s %s\n", GOT_OBJ_LABEL_COMMIT, id_str); - break; - case GOT_OBJ_TYPE_TAG: - printf("object: %s %s\n", GOT_OBJ_LABEL_TAG, id_str); - break; - default: - break; + else { + switch (got_object_tag_get_object_type(tag)) { + case GOT_OBJ_TYPE_BLOB: + printf("object: %s %s\n", GOT_OBJ_LABEL_BLOB, + id_str); + break; + case GOT_OBJ_TYPE_TREE: + printf("object: %s %s\n", GOT_OBJ_LABEL_TREE, + id_str); + break; + case GOT_OBJ_TYPE_COMMIT: + printf("object: %s %s\n", GOT_OBJ_LABEL_COMMIT, + id_str); + break; + case GOT_OBJ_TYPE_TAG: + printf("object: %s %s\n", GOT_OBJ_LABEL_TAG, + id_str); + break; + default: + break; + } } free(id_str); - tagmsg0 = strdup(got_object_tag_get_message(tag)); - got_object_tag_close(tag); - if (tagmsg0 == NULL) { - err = got_error_from_errno("strdup"); - break; + if (commit) { + err = got_object_commit_get_logmsg(&tagmsg0, commit); + if (err) + break; + got_object_commit_close(commit); + } else { + tagmsg0 = strdup(got_object_tag_get_message(tag)); + got_object_tag_close(tag); + if (tagmsg0 == NULL) { + err = got_error_from_errno("strdup"); + break; + } } tagmsg = tagmsg0; blob - ff9e9e50a0904b80d516f90d64a8b838feb7aa37 blob + 070aa6e7367bb0b19a095cfa71e058341486bd99 --- regress/cmdline/tag.sh +++ regress/cmdline/tag.sh @@ -170,5 +170,53 @@ function test_tag_list { test_done "$testroot" "$ret" } +function test_tag_list_lightweight { + local testroot=`test_init tag_list_lightweight` + local commit_id=`git_show_head $testroot/repo` + local tag=1.0.0 + local tag2=2.0.0 + + # create "lightweight" tag with Git + (cd $testroot/repo && git tag $tag) + (cd $testroot/repo && git tag $tag2) + + tag_id=`got ref -r $testroot/repo -l \ + | grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2` + local tagger_time=`git_show_author_time $testroot/repo $tag` + d1=`env TZ=UTC date -r $tagger_time +"%a %b %e %X %Y UTC"` + tag_id2=`got ref -r $testroot/repo -l \ + | grep "^refs/tags/$tag2" | tr -d ' ' | cut -d: -f2` + local tagger_time2=`git_show_author_time $testroot/repo $tag2` + d2=`env TZ=UTC date -r $tagger_time2 +"%a %b %e %X %Y UTC"` + + got tag -r $testroot/repo -l > $testroot/stdout + + echo "-----------------------------------------------" \ + > $testroot/stdout.expected + echo "tag $tag2 $tag_id2" >> $testroot/stdout.expected + echo "from: $GOT_AUTHOR" >> $testroot/stdout.expected + echo "date: $d1" >> $testroot/stdout.expected + echo "object: commit $commit_id" >> $testroot/stdout.expected + echo " " >> $testroot/stdout.expected + echo " adding the test tree" >> $testroot/stdout.expected + echo " " >> $testroot/stdout.expected + echo "-----------------------------------------------" \ + >> $testroot/stdout.expected + echo "tag $tag $tag_id" >> $testroot/stdout.expected + echo "from: $GOT_AUTHOR" >> $testroot/stdout.expected + echo "date: $d2" >> $testroot/stdout.expected + echo "object: commit $commit_id" >> $testroot/stdout.expected + echo " " >> $testroot/stdout.expected + echo " adding the test tree" >> $testroot/stdout.expected + echo " " >> $testroot/stdout.expected + cmp -s $testroot/stdout $testroot/stdout.expected + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" +} + run_test test_tag_create run_test test_tag_list +run_test test_tag_list_lightweight