diff options
-rw-r--r-- | Documentation/git-bundle.txt | 8 | ||||
-rw-r--r-- | abspath.c | 7 | ||||
-rw-r--r-- | builtin/archive.c | 3 | ||||
-rw-r--r-- | builtin/bundle.c | 28 | ||||
-rw-r--r-- | builtin/checkout.c | 3 | ||||
-rw-r--r-- | builtin/reset.c | 4 | ||||
-rw-r--r-- | builtin/tag.c | 4 | ||||
-rw-r--r-- | cache.h | 3 | ||||
-rw-r--r-- | parse-options.c | 12 | ||||
-rw-r--r-- | t/helper/test-parse-pathspec-file.c | 3 | ||||
-rwxr-xr-x | t/t6020-bundle-misc.sh | 26 |
11 files changed, 82 insertions, 19 deletions
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt index a4227b6561..3ab42a19ca 100644 --- a/Documentation/git-bundle.txt +++ b/Documentation/git-bundle.txt @@ -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); +} diff --git a/builtin/archive.c b/builtin/archive.c index f094390ee0..d0a583ea95 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -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); } diff --git a/builtin/bundle.c b/builtin/bundle.c index c2b916e027..666f01bccd 100644 --- a/builtin/bundle.c +++ b/builtin/bundle.c @@ -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; } diff --git a/builtin/checkout.c b/builtin/checkout.c index 2b3ae6032d..734d730980 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -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; } diff --git a/builtin/reset.c b/builtin/reset.c index 58f567afd3..24b04aeecb 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -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; } diff --git a/builtin/tag.c b/builtin/tag.c index 7cdcd4293d..adcaa547b0 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -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; } @@ -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, diff --git a/parse-options.c b/parse-options.c index fd4743293f..6dd4c090e0 100644 --- a/parse-options.c +++ b/parse-options.c @@ -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: diff --git a/t/helper/test-parse-pathspec-file.c b/t/helper/test-parse-pathspec-file.c index b3e08cef4b..71d2131fba 100644 --- a/t/helper/test-parse-pathspec-file.c +++ b/t/helper/test-parse-pathspec-file.c @@ -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; } diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh index 8c7b25a281..dface8bcfe 100755 --- a/t/t6020-bundle-misc.sh +++ b/t/t6020-bundle-misc.sh @@ -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 |