commit 8c4a6db8547e314f29117f820ab5f99722b980fb from: Stefan Sperling date: Wed Jun 29 14:58:58 2022 UTC make it possible to show just one tag with 'got tag -l' suggested by jrick ok jrick jamsek commit - f9d376997dd2e84bf84c3c9a4da842d1b5565e9d commit + 8c4a6db8547e314f29117f820ab5f99722b980fb blob - 6e54669dd487e962e60aabbc77043a09b250bd99 blob + d2db3f11b55b0dcd7008e9f4662210887aa2742b --- got/got.1 +++ got/got.1 @@ -1232,7 +1232,10 @@ If this directory is a work tree, use the repository path associated with this work tree. .It Fl l List all existing tags in the repository instead of creating a new tag. -If this option is used, no other command-line arguments are allowed. +If a +.Ar name +argument is passed, show only the tag with the given +.Ar name . .El .Pp By design, the blob - 6332563c1a68c343f8f860c77299ff6dbe5f18f3 blob + 2dceeed3a7a54bee61a491f92527df8295059f95 --- got/got.c +++ got/got.c @@ -6869,17 +6869,48 @@ done: #endif static const struct got_error * -list_tags(struct got_repository *repo) +get_tag_refname(char **refname, const char *tag_name) { + const struct got_error *err; + + if (strncmp("refs/tags/", tag_name, 10) == 0) { + *refname = strdup(tag_name); + if (*refname == NULL) + return got_error_from_errno("strdup"); + } else if (asprintf(refname, "refs/tags/%s", tag_name) == -1) { + err = got_error_from_errno("asprintf"); + *refname = NULL; + return err; + } + + return NULL; +} + +static const struct got_error * +list_tags(struct got_repository *repo, const char *tag_name) +{ static const struct got_error *err = NULL; struct got_reflist_head refs; struct got_reflist_entry *re; + char *wanted_refname = NULL; TAILQ_INIT(&refs); err = got_ref_list(&refs, repo, "refs/tags", got_ref_cmp_tags, repo); if (err) return err; + + if (tag_name) { + struct got_reference *ref; + err = get_tag_refname(&wanted_refname, tag_name); + if (err) + goto done; + /* Wanted tag reference should exist. */ + err = got_ref_open(&ref, repo, wanted_refname, 0); + if (err) + goto done; + got_ref_close(ref); + } TAILQ_FOREACH(re, &refs, entry) { const char *refname; @@ -6892,7 +6923,8 @@ list_tags(struct got_repository *repo) struct got_commit_object *commit = NULL; refname = got_ref_get_name(re->ref); - if (strncmp(refname, "refs/tags/", 10) != 0) + if (strncmp(refname, "refs/tags/", 10) != 0 || + (wanted_refname && strcmp(refname, wanted_refname) != 0)) continue; refname += 10; refstr = got_ref_to_str(re->ref); @@ -6985,9 +7017,10 @@ list_tags(struct got_repository *repo) } while (line); free(tagmsg0); } - +done: got_ref_list_free(&refs); - return NULL; + free(wanted_refname); + return err; } static const struct got_error * @@ -7081,17 +7114,11 @@ add_tag(struct got_repository *repo, const char *tagge if (err) goto done; - if (strncmp("refs/tags/", tag_name, 10) == 0) { - refname = strdup(tag_name); - if (refname == NULL) { - err = got_error_from_errno("strdup"); - goto done; - } - tag_name += 10; - } else if (asprintf(&refname, "refs/tags/%s", tag_name) == -1) { - err = got_error_from_errno("asprintf"); + err = get_tag_refname(&refname, tag_name); + if (err) goto done; - } + if (strncmp("refs/tags/", tag_name, 10) == 0) + tag_name += 10; err = got_ref_open(&ref, repo, refname, 0); if (err == NULL) { @@ -7166,7 +7193,7 @@ cmd_tag(int argc, char *argv[]) struct got_worktree *worktree = NULL; char *cwd = NULL, *repo_path = NULL, *commit_id_str = NULL; char *gitconfig_path = NULL, *tagger = NULL; - const char *tag_name, *commit_id_arg = NULL, *tagmsg = NULL; + const char *tag_name = NULL, *commit_id_arg = NULL, *tagmsg = NULL; int ch, do_list = 0; int *pack_fds = NULL; @@ -7203,12 +7230,13 @@ cmd_tag(int argc, char *argv[]) "-c option can only be used when creating a tag"); if (tagmsg) option_conflict('l', 'm'); - if (argc > 0) + if (argc > 1) usage_tag(); } else if (argc != 1) usage_tag(); - tag_name = argv[0]; + if (argc == 1) + tag_name = argv[0]; #ifndef PROFILE if (pledge("stdio rpath wpath cpath fattr flock proc exec " @@ -7266,7 +7294,7 @@ cmd_tag(int argc, char *argv[]) error = apply_unveil(got_repo_get_path(repo), 1, NULL); if (error) goto done; - error = list_tags(repo); + error = list_tags(repo, tag_name); } else { error = get_gitconfig_path(&gitconfig_path); if (error) blob - ab908a49f4d848281c7d725df6742a474700a0e1 blob + 53325e40ea937187e8814d7b18dd3a6a2f5c40f5 --- regress/cmdline/tag.sh +++ regress/cmdline/tag.sh @@ -168,7 +168,45 @@ test_tag_list() { ret=$? if [ $ret -ne 0 ]; then diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 fi + + got tag -r $testroot/repo -l $tag > $testroot/stdout + + echo "-----------------------------------------------" \ + > $testroot/stdout.expected + echo "tag $tag $tag_id" >> $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 " test" >> $testroot/stdout.expected + echo " " >> $testroot/stdout.expected + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + got tag -r $testroot/repo -l $tag2 > $testroot/stdout + + echo "-----------------------------------------------" \ + > $testroot/stdout.expected + echo "tag $tag2 $tag_id2" >> $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 " test" >> $testroot/stdout.expected + echo " " >> $testroot/stdout.expected + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi test_done "$testroot" "$ret" }