From 321459439e19517c412cab1cfbb64a2749f272c9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 9 Sep 2016 12:10:54 +0200 Subject: cat-file: support --textconv/--filters in batch mode With this patch, --batch can be combined with --textconv or --filters. For this to work, the input needs to have the form so that the filters can be chosen appropriately. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 4fa9041..204541c 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | | --textconv | --filters ) [--path=] -'git cat-file' (--batch | --batch-check) [--follow-symlinks] +'git cat-file' (--batch | --batch-check) [ --textconv | --filters ] [--follow-symlinks] DESCRIPTION ----------- @@ -20,7 +20,11 @@ object type, or `-s` is used to find the object size, or `--textconv` or `--filters` is used (which imply type "blob"). In the second form, a list of objects (separated by linefeeds) is provided on -stdin, and the SHA-1, type, and size of each object is printed on stdout. +stdin, and the SHA-1, type, and size of each object is printed on stdout. The +output format can be overridden using the optional `` argument. If +either `--textconv` or `--filters` was specified, the input is expected to +list the object names followed by the path name, separated by a single white +space, so that the appropriate drivers can be determined. OPTIONS ------- @@ -72,13 +76,17 @@ OPTIONS --batch:: --batch=:: Print object information and contents for each object provided - on stdin. May not be combined with any other options or arguments. - See the section `BATCH OUTPUT` below for details. + on stdin. May not be combined with any other options or arguments + except `--textconv` or `--filters`, in which case the input lines + also need to specify the path, separated by white space. See the + section `BATCH OUTPUT` below for details. --batch-check:: --batch-check=:: Print object information for each object provided on stdin. May - not be combined with any other options or arguments. See the + not be combined with any other options or arguments except + `--textconv` or `--filters`, in which case the input lines also + need to specify the path, separated by white space. See the section `BATCH OUTPUT` below for details. --batch-all-objects:: diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 51f4c54..59dea48 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -17,6 +17,7 @@ struct batch_options { int print_contents; int buffer_output; int all_objects; + int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */ const char *format; }; @@ -280,7 +281,32 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d if (data->type == OBJ_BLOB) { if (opt->buffer_output) fflush(stdout); - if (stream_blob_to_fd(1, sha1, NULL, 0) < 0) + if (opt->cmdmode) { + char *contents; + unsigned long size; + + if (!data->rest) + die("missing path for '%s'", sha1_to_hex(sha1)); + + if (opt->cmdmode == 'w') { + if (filter_object(data->rest, 0100644, sha1, + &contents, &size)) + die("could not convert '%s' %s", + sha1_to_hex(sha1), data->rest); + } else if (opt->cmdmode == 'c') { + enum object_type type; + if (!textconv_object(data->rest, 0100644, sha1, + 1, &contents, &size)) + contents = read_sha1_file(sha1, &type, + &size); + if (!contents) + die("could not convert '%s' %s", + sha1_to_hex(sha1), data->rest); + } else + die("BUG: invalid cmdmode: %c", opt->cmdmode); + batch_write(opt, contents, size); + free(contents); + } else if (stream_blob_to_fd(1, sha1, NULL, 0) < 0) die("unable to stream %s to stdout", sha1_to_hex(sha1)); } else { @@ -417,6 +443,8 @@ static int batch_objects(struct batch_options *opt) data.mark_query = 1; strbuf_expand(&buf, opt->format, expand_format, &data); data.mark_query = 0; + if (opt->cmdmode) + data.split_on_whitespace = 1; if (opt->all_objects) { struct object_info empty; @@ -482,7 +510,7 @@ static int batch_objects(struct batch_options *opt) static const char * const cat_file_usage[] = { N_("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p||--textconv|--filters) [--path=] "), - N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"), + N_("git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv|--filters]"), NULL }; @@ -553,7 +581,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0); if (opt) { - if (argc == 1) + if (batch.enabled && (opt == 'c' || opt == 'w')) + batch.cmdmode = opt; + else if (argc == 1) obj_name = argv[0]; else usage_with_options(cat_file_usage, options); @@ -565,8 +595,12 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) } else usage_with_options(cat_file_usage, options); } - if (batch.enabled && (opt || argc)) { - usage_with_options(cat_file_usage, options); + if (batch.enabled) { + if (batch.cmdmode != opt || argc) + usage_with_options(cat_file_usage, options); + if (batch.cmdmode && batch.all_objects) + die("--batch-all-objects cannot be combined with " + "--textconv nor with --filters"); } if ((batch.follow_symlinks || batch.all_objects) && !batch.enabled) { @@ -578,6 +612,11 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) usage_with_options(cat_file_usage, options); } + if (force_path && batch.enabled) { + error("--path= incompatible with --batch"); + usage_with_options(cat_file_usage, options); + } + if (batch.buffer_output < 0) batch.buffer_output = batch.all_objects; diff --git a/t/t8010-cat-file-filters.sh b/t/t8010-cat-file-filters.sh index 3d5ad7d..d8242e4 100755 --- a/t/t8010-cat-file-filters.sh +++ b/t/t8010-cat-file-filters.sh @@ -51,4 +51,14 @@ test_expect_success '--path= complains without --textconv/--filters' ' grep "path.*needs.*filters" err ' +test_expect_success 'cat-file --textconv --batch works' ' + sha1=$(git rev-parse -q --verify HEAD:world.txt) && + test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" && + printf "%s hello.txt\n%s hello\n" $sha1 $sha1 | + git cat-file --textconv --batch >actual && + printf "%s blob 6\nuryyb\r\n\n%s blob 6\nhello\n\n" \ + $sha1 $sha1 >expect && + test_cmp expect actual +' + test_done -- cgit v0.10.2-6-g49f6