"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
show just one tag with got tag -l
To:
gameoftrees@openbsd.org
Date:
Wed, 29 Jun 2022 12:26:08 +0200

Download raw body.

Thread
Make it possible to show just one tag with 'got tag -l'.

This can be useful in situations where the desired tag name
is already known, so users do not have to wade through the
entire list of all tag messages.

Suggested by jrick on IRC.

ok?
 
diff f9d376997dd2e84bf84c3c9a4da842d1b5565e9d 10f634d85314c0a8cb06cd3dbd60c3a17dd43371
commit - f9d376997dd2e84bf84c3c9a4da842d1b5565e9d
commit + 10f634d85314c0a8cb06cd3dbd60c3a17dd43371
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,11 +6869,30 @@ 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);
 
@@ -6881,6 +6900,18 @@ list_tags(struct got_repository *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;
 		char *refstr, *tagmsg0, *tagmsg, *line, *id_str, *datestr;
@@ -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;
-		}
+	err = get_tag_refname(&refname, tag_name);
+	if (err)
+		goto done;
+	if (strncmp("refs/tags/", tag_name, 10) == 0)
 		tag_name += 10;
-	} else if (asprintf(&refname, "refs/tags/%s", tag_name) == -1) {
-		err = got_error_from_errno("asprintf");
-		goto done;
-	}
 
 	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"
 }