Skip to content

Commit c334b87

Browse files
peffgitster
authored andcommitted
cat-file: split --batch input lines on whitespace
If we get an input line to --batch or --batch-check that looks like "HEAD foo bar", we will currently feed the whole thing to get_sha1(). This means that to use --batch-check with `rev-list --objects`, one must pre-process the input, like: git rev-list --objects HEAD | cut -d' ' -f1 | git cat-file --batch-check Besides being more typing and slightly less efficient to invoke `cut`, the result loses information: we no longer know which path each object was found at. This patch teaches cat-file to split input lines at the first whitespace. Everything to the left of the whitespace is considered an object name, and everything to the right is made available as the %(reset) atom. So you can now do: git rev-list --objects HEAD | git cat-file --batch-check='%(objectsize) %(rest)' to collect object sizes at particular paths. Even if %(rest) is not used, we always do the whitespace split (which means you can simply eliminate the `cut` command from the first example above). This whitespace split is backwards compatible for any reasonable input. Object names cannot contain spaces, so any input with spaces would have resulted in a "missing" line. The only input hurt is if somebody really expected input of the form "HEAD is a fine-looking ref!" to fail; it will now parse HEAD, and make "is a fine-looking ref!" available as %(rest). Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a4ac106 commit c334b87

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

Documentation/git-cat-file.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ BATCH OUTPUT
8888
If `--batch` or `--batch-check` is given, `cat-file` will read objects
8989
from stdin, one per line, and print information about them.
9090

91-
Each line is considered as a whole object name, and is parsed as if
92-
given to linkgit:git-rev-parse[1].
91+
Each line is split at the first whitespace boundary. All characters
92+
before that whitespace are considered as a whole object name, and are
93+
parsed as if given to linkgit:git-rev-parse[1]. Characters after that
94+
whitespace can be accessed using the `%(rest)` atom (see below).
9395

9496
You can specify the information shown for each object by using a custom
9597
`<format>`. The `<format>` is copied literally to stdout for each
@@ -110,6 +112,10 @@ newline. The available atoms are:
110112
The size, in bytes, that the object takes up on disk. See the
111113
note about on-disk sizes in the `CAVEATS` section below.
112114

115+
`rest`::
116+
The text (if any) found after the first run of whitespace on the
117+
input line (i.e., the "rest" of the line).
118+
113119
If no format is specified, the default format is `%(objectname)
114120
%(objecttype) %(objectsize)`.
115121

builtin/cat-file.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ struct expand_data {
119119
enum object_type type;
120120
unsigned long size;
121121
unsigned long disk_size;
122+
const char *rest;
122123

123124
/*
124125
* If mark_query is true, we do not expand anything, but rather
@@ -161,6 +162,9 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,
161162
data->info.disk_sizep = &data->disk_size;
162163
else
163164
strbuf_addf(sb, "%lu", data->disk_size);
165+
} else if (is_atom("rest", atom, len)) {
166+
if (!data->mark_query && data->rest)
167+
strbuf_addstr(sb, data->rest);
164168
} else
165169
die("unknown format element: %.*s", len, atom);
166170
}
@@ -263,7 +267,21 @@ static int batch_objects(struct batch_options *opt)
263267
data.mark_query = 0;
264268

265269
while (strbuf_getline(&buf, stdin, '\n') != EOF) {
266-
int error = batch_one_object(buf.buf, opt, &data);
270+
char *p;
271+
int error;
272+
273+
/*
274+
* Split at first whitespace, tying off the beginning of the
275+
* string and saving the remainder (or NULL) in data.rest.
276+
*/
277+
p = strpbrk(buf.buf, " \t");
278+
if (p) {
279+
while (*p && strchr(" \t", *p))
280+
*p++ = '\0';
281+
}
282+
data.rest = p;
283+
284+
error = batch_one_object(buf.buf, opt, &data);
267285
if (error)
268286
return error;
269287
}

t/t1006-cat-file.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ $content"
7878
echo $sha1 | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&
7979
test_cmp expect actual
8080
'
81+
82+
test_expect_success '--batch-check with %(rest)' '
83+
echo "$type this is some extra content" >expect &&
84+
echo "$sha1 this is some extra content" |
85+
git cat-file --batch-check="%(objecttype) %(rest)" >actual &&
86+
test_cmp expect actual
87+
'
8188
}
8289

8390
hello_content="Hello World"

0 commit comments

Comments
 (0)