git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Make builtin-tag.c use parse_options.

From
CRCarlos Rica <jasampler@gmail.com>
Date
Nov 9, 2007, 13:42 UTC
Message-ID
<473463E0.7000406@gmail.com>

Also, this removes those tests ensuring that repeated -m options don't allocate memory more than once, because now this is done after parsing options, using the last one when more are given. The same for -F.

Signed-off-by: Carlos Rica <jasampler@gmail.com>
---
    Applied to "next".
    Comments welcomed.
 builtin-tag.c  |  141 ++++++++++++++++++++++++--------------------------------
 t/t7004-tag.sh |    8 +---
 2 files changed, 61 insertions(+), 88 deletions(-)
diff --git a/builtin-tag.c b/builtin-tag.c
index 66e5a58..5af1950 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -11,9 +11,15 @@
 #include "refs.h"
 #include "tag.h"
 #include "run-command.h"
-
-static const char builtin_tag_usage[] =
-  "git-tag [-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg> | -F <file>] <tagname> [<head>]";
+#include "parse-options.h"
+
+static const char * const git_tag_usage[] = {
+	"git-tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
+	"git-tag -d <tagname>...",
+	"git-tag [-n [<num>]] -l [<pattern>]",
+	"git-tag -v <tagname>...",
+	NULL
+};

 static char signingkey[1000];

@@ -308,101 +314,74 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf;
 	unsigned char object[20], prev[20];
-	int annotate = 0, sign = 0, force = 0, lines = 0, message = 0;
 	char ref[PATH_MAX];
 	const char *object_ref, *tag;
-	int i;
 	struct ref_lock *lock;

+	int annotate = 0, sign = 0, force = 0, lines = 0,
+					delete = 0, verify = 0;
+	char *list = NULL, *msg = NULL, *msgfile = NULL, *keyid = NULL;
+	const char *no_pattern = "NO_PATTERN";
+	struct option options[] = {
+		{ OPTION_STRING, 'l', NULL, &list, "pattern", "list tag names",
+			PARSE_OPT_OPTARG, NULL, (intptr_t) no_pattern },
+		{ OPTION_INTEGER, 'n', NULL, &lines, NULL,
+				"print n lines of each tag message",
+				PARSE_OPT_OPTARG, NULL, 1 },
+		OPT_BOOLEAN('d', NULL, &delete, "delete tags"),
+		OPT_BOOLEAN('v', NULL, &verify, "verify tags"),
+
+		OPT_GROUP("Tag creation options"),
+		OPT_BOOLEAN('a', NULL, &annotate,
+					"annotated tag, needs a message"),
+		OPT_STRING('m', NULL, &msg, "msg", "message for the tag"),
+		OPT_STRING('F', NULL, &msgfile, "file", "message in a file"),
+		OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
+		OPT_STRING('u', NULL, &keyid, "key-id",
+					"use another key to sign the tag"),
+		OPT_BOOLEAN('f', NULL, &force, "replace the tag if exists"),
+		OPT_END()
+	};
+
 	git_config(git_tag_config);
-	strbuf_init(&buf, 0);

-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
+	argc = parse_options(argc, argv, options, git_tag_usage, 0);

-		if (arg[0] != '-')
-			break;
-		if (!strcmp(arg, "-a")) {
-			annotate = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-s")) {
-			annotate = 1;
-			sign = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-f")) {
-			force = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-n")) {
-			if (i + 1 == argc || *argv[i + 1] == '-')
-				/* no argument */
-				lines = 1;
-			else
-				lines = isdigit(*argv[++i]) ?
-					atoi(argv[i]) : 1;
-			continue;
-		}
-		if (!strcmp(arg, "-m")) {
-			annotate = 1;
-			i++;
-			if (i == argc)
-				die("option -m needs an argument.");
-			if (message)
-				die("only one -F or -m option is allowed.");
-			strbuf_addstr(&buf, argv[i]);
-			message = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-F")) {
-			annotate = 1;
-			i++;
-			if (i == argc)
-				die("option -F needs an argument.");
-			if (message)
-				die("only one -F or -m option is allowed.");
-
-			if (!strcmp(argv[i], "-")) {
+	if (list)
+		return list_tags(list == no_pattern ? NULL : list, lines);
+	if (delete)
+		return for_each_tag_name(argv, delete_tag);
+	if (verify)
+		return for_each_tag_name(argv, verify_tag);
+
+	strbuf_init(&buf, 0);
+	if (msg || msgfile) {
+		if (msg && msgfile)
+			die("only one -F or -m option is allowed.");
+		annotate = 1;
+		if (msg)
+			strbuf_addstr(&buf, msg);
+		else {
+			if (!strcmp(msgfile, "-")) {
 				if (strbuf_read(&buf, 0, 1024) < 0)
-					die("cannot read %s", argv[i]);
+					die("cannot read %s", msgfile);
 			} else {
-				if (strbuf_read_file(&buf, argv[i], 1024) < 0)
+				if (strbuf_read_file(&buf, msgfile, 1024) < 0)
 					die("could not open or read '%s': %s",
-						argv[i], strerror(errno));
+						msgfile, strerror(errno));
 			}
-			message = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-u")) {
-			annotate = 1;
-			sign = 1;
-			i++;
-			if (i == argc)
-				die("option -u needs an argument.");
-			if (strlcpy(signingkey, argv[i], sizeof(signingkey))
-							>= sizeof(signingkey))
-				die("argument to option -u too long");
-			continue;
 		}
-		if (!strcmp(arg, "-l"))
-			return list_tags(argv[i + 1], lines);
-		if (!strcmp(arg, "-d"))
-			return for_each_tag_name(argv + i + 1, delete_tag);
-		if (!strcmp(arg, "-v"))
-			return for_each_tag_name(argv + i + 1, verify_tag);
-		usage(builtin_tag_usage);
 	}

-	if (i == argc) {
+	if (argc == 0) {
 		if (annotate)
-			usage(builtin_tag_usage);
+			usage_with_options(git_tag_usage, options);
 		return list_tags(NULL, lines);
 	}
-	tag = argv[i++];
+	tag = argv[0];

-	object_ref = i < argc ? argv[i] : "HEAD";
-	if (i + 1 < argc)
+	object_ref = argc == 2 ? argv[1] : "HEAD";
+	if (argc > 2)
 		die("too many params");

 	if (get_sha1(object_ref, object))
@@ -419,7 +398,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		die("tag '%s' already exists", tag);

 	if (annotate)
-		create_tag(object, tag, &buf, message, sign, object);
+		create_tag(object, tag, &buf, msg || msgfile, sign, object);

 	lock = lock_any_ref_for_update(ref, prev, 0);
 	if (!lock)
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 0d07bc3..4b09d28 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -339,20 +339,14 @@ test_expect_success \
 '

 test_expect_success \
-	'trying to create tags giving many -m or -F options should fail' '
+	'trying to create tags giving both -m or -F options should fail' '
 	echo "message file 1" >msgfile1 &&
 	echo "message file 2" >msgfile2 &&
 	! tag_exists msgtag &&
-	! git-tag -m "message 1" -m "message 2" msgtag &&
-	! tag_exists msgtag &&
-	! git-tag -F msgfile1 -F msgfile2 msgtag &&
-	! tag_exists msgtag &&
 	! git-tag -m "message 1" -F msgfile1 msgtag &&
 	! tag_exists msgtag &&
 	! git-tag -F msgfile1 -m "message 1" msgtag &&
 	! tag_exists msgtag &&
-	! git-tag -F msgfile1 -m "message 1" -F msgfile2 msgtag &&
-	! tag_exists msgtag &&
 	! git-tag -m "message 1" -F msgfile1 -m "message 2" msgtag &&
 	! tag_exists msgtag
 '
-- 
1.5.3.4
Next: Jakub Narebski
Message 1 of 11 in “Make builtin-tag.c use parse_options.”
  1. Make builtin-tag.c use parse_options.Carlos Rica, Nov 9, 2007
  2. Jakub NarebskiNov 9, 2007
  3. Johannes SchindelinNov 9, 2007
  4. Junio C HamanoNov 10, 2007
  5. Junio C HamanoNov 10, 2007
  6. Junio C HamanoNov 10, 2007
  7. Carlos RicaNov 10, 2007
  8. Pierre HabouzitNov 10, 2007
  9. Carlos RicaNov 12, 2007
  10. Pierre HabouzitNov 12, 2007
  11. Kristian HøgsbergNov 12, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.