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

	<object name><single white space><path>

so that the filters can be chosen appropriately.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin 2016-09-09 12:10:54 +02:00 committed by Junio C Hamano
parent 7bcf341453
commit 321459439e
3 changed files with 67 additions and 10 deletions

View File

@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | <type> | --textconv | --filters ) [--path=<path>] <object>
'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 `<format>` 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=<format>::
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=<format>::
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::

View File

@ -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|<type>|--textconv|--filters) [--path=<path>] <object>"),
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=<path> incompatible with --batch");
usage_with_options(cat_file_usage, options);
}
if (batch.buffer_output < 0)
batch.buffer_output = batch.all_objects;

View File

@ -51,4 +51,14 @@ test_expect_success '--path=<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