Skip to content

Commit

Permalink
bundle: framework for options before bundle file
Browse files Browse the repository at this point in the history
Make it possible for any of the git-bundle subcommands to include
options:
- before the sub-command
- after the sub-command, before the bundle filename

There is an immediate gain in support for help with all of the
sub-commands, where 'git bundle list-heads -h' previously returned an
error.

Downside here is an increase in code duplication that cannot be
trivially avoided short of shared global static options.

Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
robbat2 authored and gitster committed Nov 11, 2019
1 parent d9f6f3b commit 73c3253
Showing 1 changed file with 145 additions and 45 deletions.
190 changes: 145 additions & 45 deletions builtin/bundle.c
@@ -1,4 +1,5 @@
#include "builtin.h"
#include "parse-options.h"
#include "cache.h"
#include "bundle.h"

Expand All @@ -9,59 +10,158 @@
* 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 * const builtin_bundle_usage[] = {
N_("git bundle create <file> <git-rev-list args>"),
N_("git bundle verify <file>"),
N_("git bundle list-heads <file> [<refname>...]"),
N_("git bundle unbundle <file> [<refname>...]"),
NULL
};

int cmd_bundle(int argc, const char **argv, const char *prefix)
{
static const char * const builtin_bundle_create_usage[] = {
N_("git bundle create <file> <git-rev-list args>"),
NULL
};

static const char * const builtin_bundle_verify_usage[] = {
N_("git bundle verify <file>"),
NULL
};

static const char * const builtin_bundle_list_heads_usage[] = {
N_("git bundle list-heads <file> [<refname>...]"),
NULL
};

static const char * const builtin_bundle_unbundle_usage[] = {
N_("git bundle unbundle <file> [<refname>...]"),
NULL
};

static int verbose;

static int parse_options_cmd_bundle(int argc,
const char **argv,
const char* prefix,
const char * const usagestr[],
const struct option options[],
const char **bundle_file) {
int newargc;
newargc = parse_options(argc, argv, NULL, options, usagestr,
PARSE_OPT_STOP_AT_NON_OPTION);
if (argc < 1)
usage_with_options(usagestr, options);
*bundle_file = prefix_filename(prefix, argv[0]);
return newargc;
}

static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
struct option options[] = {
OPT_END()
};
const char* bundle_file;

argc = parse_options_cmd_bundle(argc, argv, prefix,
builtin_bundle_create_usage, options, &bundle_file);
/* bundle internals use argv[1] as further parameters */

if (!startup_info->have_repository)
die(_("Need a repository to create a bundle."));
return !!create_bundle(the_repository, bundle_file, argc, argv);
}

static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
struct bundle_header header;
const char *cmd, *bundle_file;
int bundle_fd = -1;

if (argc < 3)
usage(builtin_bundle_usage);
struct option options[] = {
OPT_END()
};
const char* bundle_file;

cmd = argv[1];
bundle_file = prefix_filename(prefix, argv[2]);
argc -= 2;
argv += 2;
argc = parse_options_cmd_bundle(argc, argv, prefix,
builtin_bundle_verify_usage, options, &bundle_file);
/* bundle internals use argv[1] as further parameters */

memset(&header, 0, sizeof(header));
if (strcmp(cmd, "create") && (bundle_fd =
read_bundle_header(bundle_file, &header)) < 0)
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
return 1;
close(bundle_fd);
if (verify_bundle(the_repository, &header, 1))
return 1;
fprintf(stderr, _("%s is okay\n"), bundle_file);
return 0;
}

if (!strcmp(cmd, "verify")) {
close(bundle_fd);
if (argc != 1) {
usage(builtin_bundle_usage);
return 1;
}
if (verify_bundle(the_repository, &header, 1))
return 1;
fprintf(stderr, _("%s is okay\n"), bundle_file);
return 0;
}
if (!strcmp(cmd, "list-heads")) {
close(bundle_fd);
return !!list_bundle_refs(&header, argc, argv);
static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix) {
struct bundle_header header;
int bundle_fd = -1;

struct option options[] = {
OPT_END()
};
const char* bundle_file;

argc = parse_options_cmd_bundle(argc, argv, prefix,
builtin_bundle_list_heads_usage, options, &bundle_file);
/* bundle internals use argv[1] as further parameters */

memset(&header, 0, sizeof(header));
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
return 1;
close(bundle_fd);
return !!list_bundle_refs(&header, argc, argv);
}

static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) {
struct bundle_header header;
int bundle_fd = -1;

struct option options[] = {
OPT_END()
};
const char* bundle_file;

argc = parse_options_cmd_bundle(argc, argv, prefix,
builtin_bundle_unbundle_usage, options, &bundle_file);
/* bundle internals use argv[1] as further parameters */

memset(&header, 0, sizeof(header));
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
return 1;
if (!startup_info->have_repository)
die(_("Need a repository to unbundle."));
return !!unbundle(the_repository, &header, bundle_fd, 0) ||
list_bundle_refs(&header, argc, argv);
}

int cmd_bundle(int argc, const char **argv, const char *prefix)
{
struct option options[] = {
OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")),
OPT_END()
};
int result;

argc = parse_options(argc, argv, prefix, options, builtin_bundle_usage,
PARSE_OPT_STOP_AT_NON_OPTION);

packet_trace_identity("bundle");

if (argc < 2)
usage_with_options(builtin_bundle_usage, options);

else if (!strcmp(argv[0], "create"))
result = cmd_bundle_create(argc, argv, prefix);
else if (!strcmp(argv[0], "verify"))
result = cmd_bundle_verify(argc, argv, prefix);
else if (!strcmp(argv[0], "list-heads"))
result = cmd_bundle_list_heads(argc, argv, prefix);
else if (!strcmp(argv[0], "unbundle"))
result = cmd_bundle_unbundle(argc, argv, prefix);
else {
error(_("Unknown subcommand: %s"), argv[0]);
usage_with_options(builtin_bundle_usage, options);
}
if (!strcmp(cmd, "create")) {
if (argc < 2) {
usage(builtin_bundle_usage);
return 1;
}
if (!startup_info->have_repository)
die(_("Need a repository to create a bundle."));
return !!create_bundle(the_repository, bundle_file, argc, argv);
} else if (!strcmp(cmd, "unbundle")) {
if (!startup_info->have_repository)
die(_("Need a repository to unbundle."));
return !!unbundle(the_repository, &header, bundle_fd, 0) ||
list_bundle_refs(&header, argc, argv);
} else
usage(builtin_bundle_usage);
return result ? 1 : 0;
}

0 comments on commit 73c3253

Please sign in to comment.