Merge branch 'jk/bundle-use-dash-for-stdfiles'
"git bundle" learned that "-" is a common way to say that the input comes from the standard input and/or the output goes to the standard output. It used to work only for output and only from the root level of the working tree. * jk/bundle-use-dash-for-stdfiles: parse-options: use prefix_filename_except_for_dash() helper parse-options: consistently allocate memory in fix_filename() bundle: don't blindly apply prefix_filename() to "-" bundle: document handling of "-" as stdin bundle: let "-" mean stdin for reading operations
This commit is contained in:
commit
95de376349
@ -66,7 +66,7 @@ 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.
|
||||
subcommand. If 'file' is `-`, the bundle is written to stdout.
|
||||
|
||||
verify <file>::
|
||||
Used to check that a bundle file is valid and will apply
|
||||
@ -77,12 +77,13 @@ verify <file>::
|
||||
Finally, information about additional capabilities, such as "object
|
||||
filter", is printed. See "Capabilities" in linkgit:gitformat-bundle[5]
|
||||
for more information. The exit code is zero for success, but will
|
||||
be nonzero if the bundle file is invalid.
|
||||
be nonzero if the bundle file is invalid. If 'file' is `-`, the
|
||||
bundle is read from stdin.
|
||||
|
||||
list-heads <file>::
|
||||
Lists the references defined in the bundle. If followed by a
|
||||
list of references, only references matching those given are
|
||||
printed out.
|
||||
printed out. If 'file' is `-`, the bundle is read from stdin.
|
||||
|
||||
unbundle <file>::
|
||||
Passes the objects in the bundle to 'git index-pack'
|
||||
@ -90,6 +91,7 @@ unbundle <file>::
|
||||
defined references. If a list of references is given, only
|
||||
references matching those in the list are printed. This command is
|
||||
really plumbing, intended to be called only by 'git fetch'.
|
||||
If 'file' is `-`, the bundle is read from stdin.
|
||||
|
||||
<git-rev-list-args>::
|
||||
A list of arguments, acceptable to 'git rev-parse' and
|
||||
|
@ -280,3 +280,10 @@ char *prefix_filename(const char *pfx, const char *arg)
|
||||
#endif
|
||||
return strbuf_detach(&path, NULL);
|
||||
}
|
||||
|
||||
char *prefix_filename_except_for_dash(const char *pfx, const char *arg)
|
||||
{
|
||||
if (!strcmp(arg, "-"))
|
||||
return xstrdup(arg);
|
||||
return prefix_filename(pfx, arg);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ static int run_remote_archiver(int argc, const char **argv,
|
||||
int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char *exec = "git-upload-archive";
|
||||
const char *output = NULL;
|
||||
char *output = NULL;
|
||||
const char *remote = NULL;
|
||||
struct option local_opts[] = {
|
||||
OPT_FILENAME('o', "output", &output,
|
||||
@ -106,5 +106,6 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
|
||||
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
|
||||
|
||||
UNLEAK(output);
|
||||
return write_archive(argc, argv, prefix, the_repository, output, 0);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ static int parse_options_cmd_bundle(int argc,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
if (!argc)
|
||||
usage_msg_opt(_("need a <file> argument"), usagestr, options);
|
||||
*bundle_file = prefix_filename(prefix, argv[0]);
|
||||
*bundle_file = prefix_filename_except_for_dash(prefix, argv[0]);
|
||||
return argc;
|
||||
}
|
||||
|
||||
@ -108,6 +108,23 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to read_bundle_header(), but handle "-" as stdin.
|
||||
*/
|
||||
static int open_bundle(const char *path, struct bundle_header *header,
|
||||
const char **name)
|
||||
{
|
||||
if (!strcmp(path, "-")) {
|
||||
if (name)
|
||||
*name = "<stdin>";
|
||||
return read_bundle_header_fd(0, header, "<stdin>");
|
||||
}
|
||||
|
||||
if (name)
|
||||
*name = path;
|
||||
return read_bundle_header(path, header);
|
||||
}
|
||||
|
||||
static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
|
||||
struct bundle_header header = BUNDLE_HEADER_INIT;
|
||||
int bundle_fd = -1;
|
||||
@ -119,12 +136,13 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
|
||||
OPT_END()
|
||||
};
|
||||
char *bundle_file;
|
||||
const char *name;
|
||||
|
||||
argc = parse_options_cmd_bundle(argc, argv, prefix,
|
||||
builtin_bundle_verify_usage, options, &bundle_file);
|
||||
/* bundle internals use argv[1] as further parameters */
|
||||
|
||||
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
|
||||
if ((bundle_fd = open_bundle(bundle_file, &header, &name)) < 0) {
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -135,7 +153,7 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
fprintf(stderr, _("%s is okay\n"), bundle_file);
|
||||
fprintf(stderr, _("%s is okay\n"), name);
|
||||
ret = 0;
|
||||
cleanup:
|
||||
free(bundle_file);
|
||||
@ -156,7 +174,7 @@ static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix
|
||||
builtin_bundle_list_heads_usage, options, &bundle_file);
|
||||
/* bundle internals use argv[1] as further parameters */
|
||||
|
||||
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
|
||||
if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) {
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -186,7 +204,7 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
|
||||
builtin_bundle_unbundle_usage, options, &bundle_file);
|
||||
/* bundle internals use argv[1] as further parameters */
|
||||
|
||||
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
|
||||
if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) {
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ struct checkout_opts {
|
||||
const char *ignore_unmerged_opt;
|
||||
int ignore_unmerged;
|
||||
int pathspec_file_nul;
|
||||
const char *pathspec_from_file;
|
||||
char *pathspec_from_file;
|
||||
|
||||
const char *new_branch;
|
||||
const char *new_branch_force;
|
||||
@ -1890,6 +1890,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
||||
options, checkout_usage, &new_branch_info);
|
||||
branch_info_release(&new_branch_info);
|
||||
clear_pathspec(&opts.pathspec);
|
||||
free(opts.pathspec_from_file);
|
||||
FREE_AND_NULL(options);
|
||||
return ret;
|
||||
}
|
||||
|
@ -318,7 +318,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
int reset_type = NONE, update_ref_status = 0, quiet = 0;
|
||||
int no_refresh = 0;
|
||||
int patch_mode = 0, pathspec_file_nul = 0, unborn;
|
||||
const char *rev, *pathspec_from_file = NULL;
|
||||
const char *rev;
|
||||
char *pathspec_from_file = NULL;
|
||||
struct object_id oid;
|
||||
struct pathspec pathspec;
|
||||
int intent_to_add = 0;
|
||||
@ -496,5 +497,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
|
||||
cleanup:
|
||||
clear_pathspec(&pathspec);
|
||||
free(pathspec_from_file);
|
||||
return update_ref_status;
|
||||
}
|
||||
|
@ -429,7 +429,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
int create_reflog = 0;
|
||||
int annotate = 0, force = 0;
|
||||
int cmdmode = 0, create_tag_object = 0;
|
||||
const char *msgfile = NULL, *keyid = NULL;
|
||||
char *msgfile = NULL;
|
||||
const char *keyid = NULL;
|
||||
struct msg_arg msg = { .buf = STRBUF_INIT };
|
||||
struct ref_transaction *transaction;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
@ -639,5 +640,6 @@ cleanup:
|
||||
strbuf_release(&reflog_msg);
|
||||
strbuf_release(&msg.buf);
|
||||
strbuf_release(&err);
|
||||
free(msgfile);
|
||||
return ret;
|
||||
}
|
||||
|
3
cache.h
3
cache.h
@ -610,6 +610,9 @@ char *prefix_path_gently(const char *prefix, int len, int *remaining, const char
|
||||
*/
|
||||
char *prefix_filename(const char *prefix, const char *path);
|
||||
|
||||
/* Likewise, but path=="-" always yields "-" */
|
||||
char *prefix_filename_except_for_dash(const char *prefix, const char *path);
|
||||
|
||||
int check_filename(const char *prefix, const char *name);
|
||||
void verify_filename(const char *prefix,
|
||||
const char *name,
|
||||
|
@ -59,12 +59,12 @@ static enum parse_opt_result get_arg(struct parse_opt_ctx_t *p,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fix_filename(const char *prefix, const char **file)
|
||||
static void fix_filename(const char *prefix, char **file)
|
||||
{
|
||||
if (!file || !*file || !prefix || is_absolute_path(*file)
|
||||
|| !strcmp("-", *file))
|
||||
return;
|
||||
*file = prefix_filename(prefix, *file);
|
||||
if (!file || !*file)
|
||||
; /* leave as NULL */
|
||||
else
|
||||
*file = prefix_filename_except_for_dash(prefix, *file);
|
||||
}
|
||||
|
||||
static enum parse_opt_result opt_command_mode_error(
|
||||
@ -177,7 +177,7 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
|
||||
err = get_arg(p, opt, flags, (const char **)opt->value);
|
||||
|
||||
if (!err)
|
||||
fix_filename(p->prefix, (const char **)opt->value);
|
||||
fix_filename(p->prefix, (char **)opt->value);
|
||||
return err;
|
||||
|
||||
case OPTION_CALLBACK:
|
||||
|
@ -6,7 +6,7 @@
|
||||
int cmd__parse_pathspec_file(int argc, const char **argv)
|
||||
{
|
||||
struct pathspec pathspec;
|
||||
const char *pathspec_from_file = NULL;
|
||||
char *pathspec_from_file = NULL;
|
||||
int pathspec_file_nul = 0, i;
|
||||
|
||||
static const char *const usage[] = {
|
||||
@ -29,5 +29,6 @@ int cmd__parse_pathspec_file(int argc, const char **argv)
|
||||
printf("%s\n", pathspec.items[i].original);
|
||||
|
||||
clear_pathspec(&pathspec);
|
||||
free(pathspec_from_file);
|
||||
return 0;
|
||||
}
|
||||
|
@ -619,4 +619,30 @@ test_expect_success TTY 'create --quiet disables all bundle progress' '
|
||||
test_must_be_empty err
|
||||
'
|
||||
|
||||
test_expect_success 'read bundle over stdin' '
|
||||
git bundle create some.bundle HEAD &&
|
||||
|
||||
git bundle verify - <some.bundle 2>err &&
|
||||
grep "<stdin> is okay" err &&
|
||||
|
||||
git bundle list-heads some.bundle >expect &&
|
||||
git bundle list-heads - <some.bundle >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
git bundle unbundle some.bundle >expect &&
|
||||
git bundle unbundle - <some.bundle >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'send a bundle to standard output' '
|
||||
git bundle create - --all HEAD >bundle-one &&
|
||||
mkdir -p down &&
|
||||
git -C down bundle create - --all HEAD >bundle-two &&
|
||||
git bundle verify bundle-one &&
|
||||
git bundle verify bundle-two &&
|
||||
git ls-remote bundle-one >expect &&
|
||||
git ls-remote bundle-two >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user