Skip to content

Commit e61f25f

Browse files
committed
Merge branch 'jc/log-stdin'
* jc/log-stdin: Add trivial tests for --stdin option to log family Make --stdin option to "log" family read also pathspecs setup_revisions(): do not call get_pathspec() too early Teach --stdin option to "log" family read_revision_from_stdin(): use strbuf Conflicts: revision.c
2 parents 2a97101 + d21fc93 commit e61f25f

File tree

8 files changed

+164
-34
lines changed

8 files changed

+164
-34
lines changed

Documentation/rev-list-options.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,14 @@ endif::git-rev-list[]
243243
Pretend as if all the refs in `$GIT_DIR/refs/remotes` are listed
244244
on the command line as '<commit>'.
245245

246-
ifdef::git-rev-list[]
247246
--stdin::
248247

249248
In addition to the '<commit>' listed on the command
250-
line, read them from the standard input.
249+
line, read them from the standard input. If a '--' separator is
250+
seen, stop reading commits and start reading paths to limit the
251+
result.
251252

253+
ifdef::git-rev-list[]
252254
--quiet::
253255

254256
Don't print anything to standard output. This form

builtin-blame.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
23582358
die_errno("cannot stat path '%s'", path);
23592359
}
23602360

2361+
revs.disable_stdin = 1;
23612362
setup_revisions(argc, argv, &revs, NULL);
23622363
memset(&sb, 0, sizeof(sb));
23632364

builtin-diff-tree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
104104
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
105105
opt->abbrev = 0;
106106
opt->diff = 1;
107+
opt->disable_stdin = 1;
107108
argc = setup_revisions(argc, argv, opt, NULL);
108109

109110
while (--argc > 0) {

builtin-rev-list.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
306306
struct rev_info revs;
307307
struct rev_list_info info;
308308
int i;
309-
int read_from_stdin = 0;
310309
int bisect_list = 0;
311310
int bisect_show_vars = 0;
312311
int bisect_find_all = 0;
@@ -351,12 +350,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
351350
bisect_show_vars = 1;
352351
continue;
353352
}
354-
if (!strcmp(arg, "--stdin")) {
355-
if (read_from_stdin++)
356-
die("--stdin given twice?");
357-
read_revisions_from_stdin(&revs);
358-
continue;
359-
}
360353
usage(rev_list_usage);
361354

362355
}

bundle.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ int create_bundle(struct bundle_header *header, const char *path,
204204
int i, ref_count = 0;
205205
char buffer[1024];
206206
struct rev_info revs;
207-
int read_from_stdin = 0;
208207
struct child_process rls;
209208
FILE *rls_fout;
210209

@@ -256,15 +255,8 @@ int create_bundle(struct bundle_header *header, const char *path,
256255
/* write references */
257256
argc = setup_revisions(argc, argv, &revs, NULL);
258257

259-
for (i = 1; i < argc; i++) {
260-
if (!strcmp(argv[i], "--stdin")) {
261-
if (read_from_stdin++)
262-
die("--stdin given twice?");
263-
read_revisions_from_stdin(&revs);
264-
continue;
265-
}
266-
return error("unrecognized argument: %s'", argv[i]);
267-
}
258+
if (argc > 1)
259+
return error("unrecognized argument: %s'", argv[1]);
268260

269261
object_array_remove_duplicates(&revs.pending);
270262

revision.c

Lines changed: 93 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -953,21 +953,59 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
953953
return 0;
954954
}
955955

956-
void read_revisions_from_stdin(struct rev_info *revs)
956+
static void read_pathspec_from_stdin(struct rev_info *revs, struct strbuf *sb, const char ***prune_data)
957957
{
958-
char line[1000];
958+
const char **prune = *prune_data;
959+
int prune_nr;
960+
int prune_alloc;
959961

960-
while (fgets(line, sizeof(line), stdin) != NULL) {
961-
int len = strlen(line);
962-
if (len && line[len - 1] == '\n')
963-
line[--len] = '\0';
962+
/* count existing ones */
963+
if (!prune)
964+
prune_nr = 0;
965+
else
966+
for (prune_nr = 0; prune[prune_nr]; prune_nr++)
967+
;
968+
prune_alloc = prune_nr; /* not really, but we do not know */
969+
970+
while (strbuf_getwholeline(sb, stdin, '\n') != EOF) {
971+
int len = sb->len;
972+
if (len && sb->buf[len - 1] == '\n')
973+
sb->buf[--len] = '\0';
974+
ALLOC_GROW(prune, prune_nr+1, prune_alloc);
975+
prune[prune_nr++] = xstrdup(sb->buf);
976+
}
977+
if (prune) {
978+
ALLOC_GROW(prune, prune_nr+1, prune_alloc);
979+
prune[prune_nr] = NULL;
980+
}
981+
*prune_data = prune;
982+
}
983+
984+
static void read_revisions_from_stdin(struct rev_info *revs, const char ***prune)
985+
{
986+
struct strbuf sb;
987+
int seen_dashdash = 0;
988+
989+
strbuf_init(&sb, 1000);
990+
while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
991+
int len = sb.len;
992+
if (len && sb.buf[len - 1] == '\n')
993+
sb.buf[--len] = '\0';
964994
if (!len)
965995
break;
966-
if (line[0] == '-')
996+
if (sb.buf[0] == '-') {
997+
if (len == 2 && sb.buf[1] == '-') {
998+
seen_dashdash = 1;
999+
break;
1000+
}
9671001
die("options not supported in --stdin mode");
968-
if (handle_revision_arg(line, revs, 0, 1))
969-
die("bad revision '%s'", line);
1002+
}
1003+
if (handle_revision_arg(sb.buf, revs, 0, 1))
1004+
die("bad revision '%s'", sb.buf);
9701005
}
1006+
if (seen_dashdash)
1007+
read_pathspec_from_stdin(revs, &sb, prune);
1008+
strbuf_release(&sb);
9711009
}
9721010

9731011
static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
@@ -1229,6 +1267,34 @@ static int for_each_good_bisect_ref(each_ref_fn fn, void *cb_data)
12291267
return for_each_ref_in("refs/bisect/good", fn, cb_data);
12301268
}
12311269

1270+
static void append_prune_data(const char ***prune_data, const char **av)
1271+
{
1272+
const char **prune = *prune_data;
1273+
int prune_nr;
1274+
int prune_alloc;
1275+
1276+
if (!prune) {
1277+
*prune_data = av;
1278+
return;
1279+
}
1280+
1281+
/* count existing ones */
1282+
for (prune_nr = 0; prune[prune_nr]; prune_nr++)
1283+
;
1284+
prune_alloc = prune_nr; /* not really, but we do not know */
1285+
1286+
while (*av) {
1287+
ALLOC_GROW(prune, prune_nr+1, prune_alloc);
1288+
prune[prune_nr++] = *av;
1289+
av++;
1290+
}
1291+
if (prune) {
1292+
ALLOC_GROW(prune, prune_nr+1, prune_alloc);
1293+
prune[prune_nr] = NULL;
1294+
}
1295+
*prune_data = prune;
1296+
}
1297+
12321298
/*
12331299
* Parse revision information, filling in the "rev_info" structure,
12341300
* and removing the used arguments from the argument list.
@@ -1238,7 +1304,8 @@ static int for_each_good_bisect_ref(each_ref_fn fn, void *cb_data)
12381304
*/
12391305
int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def)
12401306
{
1241-
int i, flags, left, seen_dashdash;
1307+
int i, flags, left, seen_dashdash, read_from_stdin;
1308+
const char **prune_data = NULL;
12421309

12431310
/* First, search for "--" */
12441311
seen_dashdash = 0;
@@ -1249,13 +1316,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
12491316
argv[i] = NULL;
12501317
argc = i;
12511318
if (argv[i + 1])
1252-
revs->prune_data = get_pathspec(revs->prefix, argv + i + 1);
1319+
prune_data = argv + i + 1;
12531320
seen_dashdash = 1;
12541321
break;
12551322
}
12561323

12571324
/* Second, deal with arguments and options */
12581325
flags = 0;
1326+
read_from_stdin = 0;
12591327
for (left = i = 1; i < argc; i++) {
12601328
const char *arg = argv[i];
12611329
if (*arg == '-') {
@@ -1300,6 +1368,16 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
13001368
revs->no_walk = 0;
13011369
continue;
13021370
}
1371+
if (!strcmp(arg, "--stdin")) {
1372+
if (revs->disable_stdin) {
1373+
argv[left++] = arg;
1374+
continue;
1375+
}
1376+
if (read_from_stdin++)
1377+
die("--stdin given twice?");
1378+
read_revisions_from_stdin(revs, &prune_data);
1379+
continue;
1380+
}
13031381

13041382
opts = handle_revision_opt(revs, argc - i, argv + i, &left, argv);
13051383
if (opts > 0) {
@@ -1325,12 +1403,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
13251403
for (j = i; j < argc; j++)
13261404
verify_filename(revs->prefix, argv[j]);
13271405

1328-
revs->prune_data = get_pathspec(revs->prefix,
1329-
argv + i);
1406+
append_prune_data(&prune_data, argv + i);
13301407
break;
13311408
}
13321409
}
13331410

1411+
if (prune_data)
1412+
revs->prune_data = get_pathspec(revs->prefix, prune_data);
1413+
13341414
if (revs->def == NULL)
13351415
revs->def = def;
13361416
if (revs->show_merge)

revision.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ struct rev_info {
8484
use_terminator:1,
8585
missing_newline:1,
8686
date_mode_explicit:1;
87+
unsigned int disable_stdin:1;
88+
8789
enum date_mode date_mode;
8890

8991
unsigned int abbrev;
@@ -129,8 +131,6 @@ struct rev_info {
129131
#define REV_TREE_DIFFERENT 3 /* Mixed changes */
130132

131133
/* revision.c */
132-
void read_revisions_from_stdin(struct rev_info *revs);
133-
134134
typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *);
135135
extern volatile show_early_output_fn_t show_early_output;
136136

t/t6017-rev-list-stdin.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2009, Junio C Hamano
4+
#
5+
6+
test_description='log family learns --stdin'
7+
8+
. ./test-lib.sh
9+
10+
check () {
11+
for cmd in rev-list "log --stat"
12+
do
13+
for i in "$@"
14+
do
15+
printf "%s\n" $i
16+
done >input &&
17+
test_expect_success "check $cmd $*" '
18+
git $cmd $(cat input) >expect &&
19+
git $cmd --stdin <input >actual &&
20+
sed -e "s/^/input /" input &&
21+
sed -e "s/^/output /" expect &&
22+
test_cmp expect actual
23+
'
24+
done
25+
}
26+
27+
them='1 2 3 4 5 6 7'
28+
29+
test_expect_success setup '
30+
(
31+
for i in 0 $them
32+
do
33+
for j in $them
34+
do
35+
echo $i.$j >file-$j &&
36+
git add file-$j || exit
37+
done &&
38+
test_tick &&
39+
git commit -m $i || exit
40+
done &&
41+
for i in $them
42+
do
43+
git checkout -b side-$i master~$i &&
44+
echo updated $i >file-$i &&
45+
git add file-$i &&
46+
test_tick &&
47+
git commit -m side-$i || exit
48+
done
49+
)
50+
'
51+
52+
check master
53+
check side-1 ^side-4
54+
check side-1 ^side-7 --
55+
check side-1 ^side-7 -- file-1
56+
check side-1 ^side-7 -- file-2
57+
check side-3 ^side-4 -- file-3
58+
check side-3 ^side-2
59+
check side-3 ^side-2 -- file-1
60+
61+
test_done

0 commit comments

Comments
 (0)