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

[PATCH 2/2] bundle: rewrite builtin to use parse-options

From
Ramkumar Ramachandra <artagnon@gmail.com>
Date
Dec 15, 2011, 16:45 UTC
Message-ID
<1323967528-10537-3-git-send-email-artagnon@gmail.com>
In-Reply-To
<1323967528-10537-1-git-send-email-artagnon@gmail.com>

The git-bundle builtin currently parses command-line options by hand; this is fragile, and reports cryptic errors on failure. Use the parse-options library to do the parsing instead.

Encouraged-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 builtin/bundle.c  |   91 +++++++++++++++++++++++++++++++----------------------
 t/t5704-bundle.sh |    2 +-
 2 files changed, 54 insertions(+), 39 deletions(-)
diff --git a/builtin/bundle.c b/builtin/bundle.c
index 92a8a60..13ed770 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "parse-options.h"
 #include "bundle.h"
 
 /*
@@ -9,57 +10,71 @@
  * bundle supporting "fetch", "pull", and "ls-remote".
  */
 
-static const char builtin_bundle_usage[] =
-  "git bundle create <file> <git-rev-list args>\n"
-  "   or: git bundle verify <file>\n"
-  "   or: git bundle list-heads <file> [<refname>...]\n"
-  "   or: git bundle unbundle <file> [<refname>...]";
+static const char * builtin_bundle_usage[] = {
+	"git bundle create <file> <git-rev-list args>",
+	"git bundle verify <file>",
+	"git bundle list-heads <file> [<refname>...]",
+	"git bundle unbundle <file> [<refname>...]",
+	NULL
+};
 
 int cmd_bundle(int argc, const char **argv, const char *prefix)
 {
-	struct bundle_header header;
-	const char *cmd, *bundle_file;
+	int prefix_length;
 	int bundle_fd = -1;
-	char buffer[PATH_MAX];
+	const char *subcommand, *bundle_file;
+	struct bundle_header header;
+	struct option options[] = { OPT_END() };
 
-	if (argc < 3)
-		usage(builtin_bundle_usage);
+	argc = parse_options(argc, argv, prefix, options,
+			builtin_bundle_usage, PARSE_OPT_STOP_AT_NON_OPTION);
 
-	cmd = argv[1];
-	bundle_file = argv[2];
-	argc -= 2;
-	argv += 2;
+	if (argc < 2)
+		usage_with_options(builtin_bundle_usage, options);
+	subcommand = argv[0];
 
-	if (prefix && bundle_file[0] != '/') {
-		snprintf(buffer, sizeof(buffer), "%s/%s", prefix, bundle_file);
-		bundle_file = buffer;
-	}
+	argc = parse_options(argc, argv, prefix, options,
+			builtin_bundle_usage, PARSE_OPT_STOP_AT_NON_OPTION);
+
+	/* Disallow stray arguments */
+	if ((strcmp(subcommand, "create") && argc > 2) ||
+		(!strcmp(subcommand, "verify") && argc > 1))
+		usage_with_options(builtin_bundle_usage, options);
 
-	memset(&header, 0, sizeof(header));
-	if (strcmp(cmd, "create") && (bundle_fd =
-				read_bundle_header(bundle_file, &header)) < 0)
-		return 1;
+	prefix_length = prefix ? strlen(prefix) : 0;
+	bundle_file = prefix_filename(prefix, prefix_length, argv[0]);
 
-	if (!strcmp(cmd, "verify")) {
+	/* Read out bundle header, except in the "create" case */
+	if (strcmp(subcommand, "create")) {
+		memset(&header, 0, sizeof(header));
+		bundle_fd = read_bundle_header(bundle_file, &header);
+		if (bundle_fd < 0)
+			die_errno(_("Failed to open bundle file '%s'"), bundle_file);
+	}
+
+	if (!strcmp(subcommand, "create")) {
+		if (!startup_info->have_repository)
+			die(_("Need a repository to create a bundle."));
+		return create_bundle(&header, bundle_file, argc, argv);
+	} else if (!strcmp(subcommand, "verify")) {
 		close(bundle_fd);
 		if (verify_bundle(&header, 1))
-			return 1;
+			return -1; /* Error already reported */
 		fprintf(stderr, _("%s is okay\n"), bundle_file);
-		return 0;
-	}
-	if (!strcmp(cmd, "list-heads")) {
+	} else if (!strcmp(subcommand, "list-heads")) {
 		close(bundle_fd);
-		return !!list_bundle_refs(&header, argc, argv);
-	}
-	if (!strcmp(cmd, "create")) {
-		if (!startup_info->have_repository)
-			die(_("Need a repository to create a bundle."));
-		return !!create_bundle(&header, bundle_file, argc, argv);
-	} else if (!strcmp(cmd, "unbundle")) {
-		if (!startup_info->have_repository)
+		return list_bundle_refs(&header, argc, argv);
+	} else if (!strcmp(subcommand, "unbundle")) {
+		if (!startup_info->have_repository) {
+			close(bundle_fd);
 			die(_("Need a repository to unbundle."));
-		return !!unbundle(&header, bundle_fd, 0) ||
+		}
+		return unbundle(&header, bundle_fd, 0) ||
 			list_bundle_refs(&header, argc, argv);
-	} else
-		usage(builtin_bundle_usage);
+	} else {
+		close(bundle_fd);
+		usage_with_options(builtin_bundle_usage, options);
+	}
+
+	return 0;
 }
diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh
index 09ff4f1..8e3f677 100755
--- a/t/t5704-bundle.sh
+++ b/t/t5704-bundle.sh
@@ -53,7 +53,7 @@ test_expect_success 'disallow stray command-line options' '
 	test_must_fail git bundle create --junk bundle second third
 '
 
-test_expect_failure 'disallow stray command-line arguments' '
+test_expect_success 'disallow stray command-line arguments' '
 	git bundle create bundle second third &&
 	test_must_fail git bundle verify bundle junk
 '
-- 
1.7.4.1
Previous: Jonathan NiederNext: Jonathan Nieder
Message 23 of 50 in “Fix '&&' chaining in tests”
  1. 0/6 Fix '&&' chaining in testsRamkumar Ramachandra, Dec 8, 2011
  2. 1/2 parse-options: introduce OPT_SUBCOMMANDRamkumar Ramachandra, Dec 8, 2011
  3. Jonathan NiederDec 8, 2011
  4. Ramkumar RamachandraDec 8, 2011
  5. 1/6 t3040 (subprojects-basic): modernize styleRamkumar Ramachandra, Dec 8, 2011
  6. Jonathan NiederDec 8, 2011
  7. Ramkumar RamachandraDec 9, 2011
  8. Junio C HamanoDec 9, 2011
  9. Ramkumar RamachandraDec 9, 2011
  10. 2/2 bundle: rewrite builtin to use parse-optionsRamkumar Ramachandra, Dec 8, 2011
  11. Jonathan NiederDec 8, 2011
  12. Ramkumar RamachandraDec 8, 2011
  13. Jonathan NiederDec 8, 2011
  14. Ramkumar RamachandraDec 8, 2011
  15. Jonathan NiederDec 8, 2011
  16. Ramkumar RamachandraDec 8, 2011
  17. Junio C HamanoDec 8, 2011
  18. Jakub NarebskiDec 9, 2011
  19. Junio C HamanoDec 9, 2011
  20. 0/2 Improve git-bundle builtinRamkumar Ramachandra, Dec 15, 2011
  21. 1/2 t5704 (bundle): rewrite for larger coverageRamkumar Ramachandra, Dec 15, 2011
  22. Jonathan NiederDec 15, 2011
  23. 2/2 bundle: rewrite builtin to use parse-optionsRamkumar Ramachandra, Dec 15, 2011
  24. Jonathan NiederDec 15, 2011
  25. Jonathan NiederDec 15, 2011
  26. Junio C HamanoDec 15, 2011
  27. 2/6 t3030 (merge-recursive): use test_expect_codeRamkumar Ramachandra, Dec 8, 2011
  28. 3/6 t1006 (cat-file): use test_cmpRamkumar Ramachandra, Dec 8, 2011
  29. Matthieu MoyDec 8, 2011
  30. Ramkumar RamachandraDec 8, 2011
  31. Matthieu MoyDec 8, 2011
  32. Jonathan NiederDec 8, 2011
  33. 4/6 t3200 (branch): fix '&&' chainingRamkumar Ramachandra, Dec 8, 2011
  34. Jonathan NiederDec 8, 2011
  35. 5/6 t1510 (worktree): fix '&&' chainingRamkumar Ramachandra, Dec 8, 2011
  36. Jonathan NiederDec 8, 2011
  37. Junio C HamanoDec 9, 2011
  38. 6/6 test: fix '&&' chainingRamkumar Ramachandra, Dec 8, 2011
  39. Jonathan NiederDec 8, 2011
  40. Junio C HamanoDec 8, 2011
  41. Ramkumar RamachandraDec 9, 2011
  42. 0/6 Fix '&&' chaining in testsRamkumar Ramachandra, Dec 9, 2011
  43. 1/6 t3040 (subprojects-basic): fix '&&' chaining, modernize styleRamkumar Ramachandra, Dec 9, 2011
  44. 2/6 t3030 (merge-recursive): use test_expect_codeRamkumar Ramachandra, Dec 9, 2011
  45. 3/6 t1006 (cat-file): use test_cmpRamkumar Ramachandra, Dec 9, 2011
  46. Junio C HamanoDec 9, 2011
  47. Ramkumar RamachandraDec 9, 2011
  48. 4/6 t3200 (branch): fix '&&' chainingRamkumar Ramachandra, Dec 9, 2011
  49. 5/6 t1510 (worktree): fix '&&' chainingRamkumar Ramachandra, Dec 9, 2011
  50. 6/6 tests: fix '&&' chainingRamkumar Ramachandra, Dec 9, 2011

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.