The git-bundle builtin currently parses command-line options by hand; this is both fragile and cryptic on failure. Since we now have an OPT_SUBCOMMAND, make use of it to parse the correct subcommand, while forbidding the use of more than one subcommand in the same invocation. Signed-off-by: Ramkumar Ramachandra <artagnon@xxxxxxxxx> --- builtin/bundle.c | 111 +++++++++++++++++++++++++++++++++++------------------ 1 files changed, 73 insertions(+), 38 deletions(-) diff --git a/builtin/bundle.c b/builtin/bundle.c index 92a8a60..c977d9f 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,91 @@ * 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 +}; + +enum bundle_subcommand { + BUNDLE_NONE = 0, + BUNDLE_CREATE = 1, + BUNDLE_VERIFY = 2, + BUNDLE_LIST_HEADS = 4, + BUNDLE_UNBUNDLE = 8 +}; 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 *bundle_file; + struct bundle_header header; + enum bundle_subcommand subcommand = BUNDLE_NONE; - if (argc < 3) - usage(builtin_bundle_usage); + struct option options[] = { + OPT_SUBCOMMAND("create", &subcommand, + "create a new bundle", + BUNDLE_CREATE), + OPT_SUBCOMMAND("verify", &subcommand, + "verify clean application of the bundle", + BUNDLE_VERIFY), + OPT_SUBCOMMAND("list-heads", &subcommand, + "list references defined in the bundle", + BUNDLE_LIST_HEADS), + OPT_SUBCOMMAND("unbundle", &subcommand, + "pass objects in the bundle to 'git index-pack'", + BUNDLE_UNBUNDLE), + OPT_END(), + }; - cmd = argv[1]; - bundle_file = argv[2]; - argc -= 2; - argv += 2; + argc = parse_options(argc, argv, NULL, + options, builtin_bundle_usage, + PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN); - if (prefix && bundle_file[0] != '/') { - snprintf(buffer, sizeof(buffer), "%s/%s", prefix, bundle_file); - bundle_file = buffer; - } + if (argc < 2) + 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; + /* The next parameter on the command line is bundle_file */ + prefix_length = prefix ? strlen(prefix) : 0; + bundle_file = prefix_filename(prefix, prefix_length, argv[1]); + argc -= 1; + argv += 1; - if (!strcmp(cmd, "verify")) { + /* Read out bundle header, except in BUNDLE_CREATE case */ + if (subcommand == BUNDLE_VERIFY || subcommand == BUNDLE_LIST_HEADS || + subcommand == BUNDLE_UNBUNDLE) { + 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); + } + + switch (subcommand) { + case BUNDLE_CREATE: + if (!startup_info->have_repository) + die(_("Need a repository to create a bundle.")); + return create_bundle(&header, bundle_file, argc, argv); + case BUNDLE_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")) { + break; + case BUNDLE_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); + case BUNDLE_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); + default: + usage_with_options(builtin_bundle_usage, options); + } + return 0; } -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html