Skip to content

Commit

Permalink
Merge branch 'rj/bundle-ui-updates' into jch
Browse files Browse the repository at this point in the history
"git bundle" has been taught to use the parse options API.  "git
bundle verify" learned "--quiet" and "git bundle create" learned
options to control the progress output.

* rj/bundle-ui-updates:
  bundle-verify: add --quiet
  bundle-create: progress output control
  bundle: framework for options before bundle file
  • Loading branch information
gitster committed Nov 20, 2019
2 parents b2e9b1f + e0eba64 commit 4fd5707
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 53 deletions.
35 changes: 32 additions & 3 deletions Documentation/git-bundle.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ git-bundle - Move objects and refs by archive
SYNOPSIS
--------
[verse]
'git bundle' create <file> <git-rev-list-args>
'git bundle' verify <file>
'git bundle' create [-q | --quiet | --progress | --all-progress] [--all-progress-implied] <file> <git-rev-list-args>
'git bundle' verify [-q | --quiet] <file>
'git bundle' list-heads <file> [<refname>...]
'git bundle' unbundle <file> [<refname>...]

Expand All @@ -33,9 +33,11 @@ destination repository.
OPTIONS
-------

create <file>::
create [options] <file> <git-rev-list-args>::
Used to create a bundle named 'file'. This requires the
'git-rev-list-args' arguments to define the bundle contents.
'options' contains the options specific to the 'git bundle create'
subcommand.

verify <file>::
Used to check that a bundle file is valid and will apply
Expand Down Expand Up @@ -75,6 +77,33 @@ unbundle <file>::
necessarily everything in the pack (in this case, 'git bundle' acts
like 'git fetch-pack').

--progress::
Progress status is reported on the standard error stream
by default when it is attached to a terminal, unless -q
is specified. This flag forces progress status even if
the standard error stream is not directed to a terminal.

--all-progress::
When --stdout is specified then progress report is
displayed during the object count and compression phases
but inhibited during the write-out phase. The reason is
that in some cases the output stream is directly linked
to another command which may wish to display progress
status of its own as it processes incoming pack data.
This flag is like --progress except that it forces progress
report for the write-out phase as well even if --stdout is
used.

--all-progress-implied::
This is used to imply --all-progress whenever progress display
is activated. Unlike --all-progress this flag doesn't actually
force any progress display by itself.

-q::
--quiet::
This flag makes the command not to report its progress
on the standard error stream.

SPECIFYING REFERENCES
---------------------

Expand Down
217 changes: 172 additions & 45 deletions builtin/bundle.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "builtin.h"
#include "argv-array.h"
#include "parse-options.h"
#include "cache.h"
#include "bundle.h"

Expand All @@ -9,59 +11,184 @@
* 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 [<options>] <file> <git-rev-list args>"),
N_("git bundle verify [<options>] <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 [<options>] <file> <git-rev-list args>"),
NULL
};

static const char * const builtin_bundle_verify_usage[] = {
N_("git bundle verify [<options>] <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) {
int all_progress_implied = 0;
int progress = isatty(STDERR_FILENO);
struct argv_array pack_opts;

struct option options[] = {
OPT_SET_INT('q', "quiet", &progress,
N_("do not show progress meter"), 0),
OPT_SET_INT(0, "progress", &progress,
N_("show progress meter"), 1),
OPT_SET_INT(0, "all-progress", &progress,
N_("show progress meter during object writing phase"), 2),
OPT_BOOL(0, "all-progress-implied",
&all_progress_implied,
N_("similar to --all-progress when progress meter is shown")),
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 */

argv_array_init(&pack_opts);
if (progress == 0)
argv_array_push(&pack_opts, "--quiet");
else if (progress == 1)
argv_array_push(&pack_opts, "--progress");
else if (progress == 2)
argv_array_push(&pack_opts, "--all-progress");
if (progress && all_progress_implied)
argv_array_push(&pack_opts, "--all-progress-implied");

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

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;
int quiet = 0;

if (argc < 3)
usage(builtin_bundle_usage);
struct option options[] = {
OPT_BOOL('q', "quiet", &quiet,
N_("do not show bundle details")),
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, !quiet))
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;
}
9 changes: 5 additions & 4 deletions bundle.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,16 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)


/* Write the pack data to bundle_fd */
static int write_pack_data(int bundle_fd, struct rev_info *revs)
static int write_pack_data(int bundle_fd, struct rev_info *revs, struct argv_array *pack_options)
{
struct child_process pack_objects = CHILD_PROCESS_INIT;
int i;

argv_array_pushl(&pack_objects.args,
"pack-objects", "--all-progress-implied",
"pack-objects",
"--stdout", "--thin", "--delta-base-offset",
NULL);
argv_array_pushv(&pack_objects.args, pack_options->argv);
pack_objects.in = -1;
pack_objects.out = bundle_fd;
pack_objects.git_cmd = 1;
Expand Down Expand Up @@ -428,7 +429,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
}

int create_bundle(struct repository *r, const char *path,
int argc, const char **argv)
int argc, const char **argv, struct argv_array *pack_options)
{
struct lock_file lock = LOCK_INIT;
int bundle_fd = -1;
Expand Down Expand Up @@ -470,7 +471,7 @@ int create_bundle(struct repository *r, const char *path,
goto err;

/* write pack */
if (write_pack_data(bundle_fd, &revs))
if (write_pack_data(bundle_fd, &revs, pack_options))
goto err;

if (!bundle_to_stdout) {
Expand Down
3 changes: 2 additions & 1 deletion bundle.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef BUNDLE_H
#define BUNDLE_H

#include "argv-array.h"
#include "cache.h"

struct ref_list {
Expand All @@ -19,7 +20,7 @@ struct bundle_header {
int is_bundle(const char *path, int quiet);
int read_bundle_header(const char *path, struct bundle_header *header);
int create_bundle(struct repository *r, const char *path,
int argc, const char **argv);
int argc, const char **argv, struct argv_array *pack_options);
int verify_bundle(struct repository *r, struct bundle_header *header, int verbose);
#define BUNDLE_VERBOSE 1
int unbundle(struct repository *r, struct bundle_header *header,
Expand Down

0 comments on commit 4fd5707

Please sign in to comment.