Skip to content

Commit d0bcc2e

Browse files
committed
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 <[email protected]>
1 parent bd71ffe commit d0bcc2e

File tree

3 files changed

+67
-10
lines changed

3 files changed

+67
-10
lines changed

Documentation/git-cat-file.txt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ SYNOPSIS
1010
--------
1111
[verse]
1212
'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | <type> | --textconv | --filters ) [--path=<path>] <object>
13-
'git cat-file' (--batch | --batch-check) [--follow-symlinks]
13+
'git cat-file' (--batch | --batch-check) [ --textconv | --filters ] [--follow-symlinks]
1414

1515
DESCRIPTION
1616
-----------
@@ -20,7 +20,11 @@ object type, or `-s` is used to find the object size, or `--textconv` or
2020
`--filters` is used (which imply type "blob").
2121

2222
In the second form, a list of objects (separated by linefeeds) is provided on
23-
stdin, and the SHA-1, type, and size of each object is printed on stdout.
23+
stdin, and the SHA-1, type, and size of each object is printed on stdout. The
24+
output format can be overridden using the optional `<format>` argument. If
25+
either `--textconv` or `--filters` was specified, the input is expected to
26+
list the object names followed by the path name, separated by a single white
27+
space, so that the appropriate drivers can be determined.
2428

2529
OPTIONS
2630
-------
@@ -72,13 +76,17 @@ OPTIONS
7276
--batch::
7377
--batch=<format>::
7478
Print object information and contents for each object provided
75-
on stdin. May not be combined with any other options or arguments.
76-
See the section `BATCH OUTPUT` below for details.
79+
on stdin. May not be combined with any other options or arguments
80+
except `--textconv` or `--filters`, in which case the input lines
81+
also need to specify the path, separated by white space. See the
82+
section `BATCH OUTPUT` below for details.
7783

7884
--batch-check::
7985
--batch-check=<format>::
8086
Print object information for each object provided on stdin. May
81-
not be combined with any other options or arguments. See the
87+
not be combined with any other options or arguments except
88+
`--textconv` or `--filters`, in which case the input lines also
89+
need to specify the path, separated by white space. See the
8290
section `BATCH OUTPUT` below for details.
8391

8492
--batch-all-objects::

builtin/cat-file.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct batch_options {
1717
int print_contents;
1818
int buffer_output;
1919
int all_objects;
20+
int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
2021
const char *format;
2122
};
2223

@@ -285,7 +286,32 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
285286
if (data->type == OBJ_BLOB) {
286287
if (opt->buffer_output)
287288
fflush(stdout);
288-
if (stream_blob_to_fd(1, sha1, NULL, 0) < 0)
289+
if (opt->cmdmode) {
290+
char *contents;
291+
unsigned long size;
292+
293+
if (!data->rest)
294+
die("missing path for '%s'", sha1_to_hex(sha1));
295+
296+
if (opt->cmdmode == 'w') {
297+
if (filter_object(data->rest, 0100644, sha1,
298+
&contents, &size))
299+
die("could not convert '%s' %s",
300+
sha1_to_hex(sha1), data->rest);
301+
} else if (opt->cmdmode == 'c') {
302+
enum object_type type;
303+
if (!textconv_object(data->rest, 0100644, sha1,
304+
1, &contents, &size))
305+
contents = read_sha1_file(sha1, &type,
306+
&size);
307+
if (!contents)
308+
die("could not convert '%s' %s",
309+
sha1_to_hex(sha1), data->rest);
310+
} else
311+
die("BUG: invalid cmdmode: %c", opt->cmdmode);
312+
batch_write(opt, contents, size);
313+
free(contents);
314+
} else if (stream_blob_to_fd(1, sha1, NULL, 0) < 0)
289315
die("unable to stream %s to stdout", sha1_to_hex(sha1));
290316
}
291317
else {
@@ -422,6 +448,8 @@ static int batch_objects(struct batch_options *opt)
422448
data.mark_query = 1;
423449
strbuf_expand(&buf, opt->format, expand_format, &data);
424450
data.mark_query = 0;
451+
if (opt->cmdmode)
452+
data.split_on_whitespace = 1;
425453

426454
if (opt->all_objects) {
427455
struct object_info empty;
@@ -487,7 +515,7 @@ static int batch_objects(struct batch_options *opt)
487515

488516
static const char * const cat_file_usage[] = {
489517
N_("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|<type>|--textconv|--filters) [--path=<path>] <object>"),
490-
N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"),
518+
N_("git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv|--filters]"),
491519
NULL
492520
};
493521

@@ -558,7 +586,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
558586
argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
559587

560588
if (opt) {
561-
if (argc == 1)
589+
if (batch.enabled && (opt == 'c' || opt == 'w'))
590+
batch.cmdmode = opt;
591+
else if (argc == 1)
562592
obj_name = argv[0];
563593
else
564594
usage_with_options(cat_file_usage, options);
@@ -570,8 +600,12 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
570600
} else
571601
usage_with_options(cat_file_usage, options);
572602
}
573-
if (batch.enabled && (opt || argc)) {
574-
usage_with_options(cat_file_usage, options);
603+
if (batch.enabled) {
604+
if (batch.cmdmode != opt || argc)
605+
usage_with_options(cat_file_usage, options);
606+
if (batch.cmdmode && batch.all_objects)
607+
die("--batch-all-objects cannot be combined with "
608+
"--textconv nor with --filters");
575609
}
576610

577611
if ((batch.follow_symlinks || batch.all_objects) && !batch.enabled) {
@@ -583,6 +617,11 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
583617
usage_with_options(cat_file_usage, options);
584618
}
585619

620+
if (force_path && batch.enabled) {
621+
error("--path=<path> incompatible with --batch");
622+
usage_with_options(cat_file_usage, options);
623+
}
624+
586625
if (batch.buffer_output < 0)
587626
batch.buffer_output = batch.all_objects;
588627

t/t8010-cat-file-filters.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,14 @@ test_expect_success '----path=<path> complains without --textconv/--filters' '
5151
grep "path.*needs.*filters" err
5252
'
5353

54+
test_expect_success 'cat-file --textconv --batch works' '
55+
sha1=$(git rev-parse -q --verify HEAD:world.txt) &&
56+
test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" &&
57+
printf "%s hello.txt\n%s hello\n" $sha1 $sha1 |
58+
git cat-file --textconv --batch >actual &&
59+
printf "%s blob 6\nuryyb\r\n\n%s blob 6\nhello\n\n" \
60+
$sha1 $sha1 >expect &&
61+
test_cmp expect actual
62+
'
63+
5464
test_done

0 commit comments

Comments
 (0)