Merge branch 'ps/revision-stdin-with-options'

The set-up code for the get_revision() API now allows feeding
options like --all and --not in the --stdin mode.

* ps/revision-stdin-with-options:
  revision: handle pseudo-opts in `--stdin` mode
  revision: small readability improvement for reading from stdin
  revision: reorder `read_revisions_from_stdin()`
This commit is contained in:
Junio C Hamano 2023-07-04 16:08:18 -07:00
commit 812907d16f
3 changed files with 103 additions and 39 deletions

View file

@ -236,10 +236,11 @@ ifndef::git-rev-list[]
endif::git-rev-list[]
--stdin::
In addition to the '<commit>' listed on the command
line, read them from the standard input. If a `--` separator is
seen, stop reading commits and start reading paths to limit the
result.
In addition to getting arguments from the command line, read
them for standard input as well. This accepts commits and
pseudo-options like `--all` and `--glob=`. When a `--` separator
is seen, the following input is treated as paths and used to
limit the result.
ifdef::git-rev-list[]
--quiet::

View file

@ -2198,39 +2198,6 @@ static void read_pathspec_from_stdin(struct strbuf *sb,
strvec_push(prune, sb->buf);
}
static void read_revisions_from_stdin(struct rev_info *revs,
struct strvec *prune)
{
struct strbuf sb;
int seen_dashdash = 0;
int save_warning;
save_warning = warn_on_object_refname_ambiguity;
warn_on_object_refname_ambiguity = 0;
strbuf_init(&sb, 1000);
while (strbuf_getline(&sb, stdin) != EOF) {
int len = sb.len;
if (!len)
break;
if (sb.buf[0] == '-') {
if (len == 2 && sb.buf[1] == '-') {
seen_dashdash = 1;
break;
}
die("options not supported in --stdin mode");
}
if (handle_revision_arg(sb.buf, revs, 0,
REVARG_CANNOT_BE_FILENAME))
die("bad revision '%s'", sb.buf);
}
if (seen_dashdash)
read_pathspec_from_stdin(&sb, prune);
strbuf_release(&sb);
warn_on_object_refname_ambiguity = save_warning;
}
static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
{
append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
@ -2819,6 +2786,53 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
return 1;
}
static void read_revisions_from_stdin(struct rev_info *revs,
struct strvec *prune,
int *flags)
{
struct strbuf sb;
int seen_dashdash = 0;
int seen_end_of_options = 0;
int save_warning;
save_warning = warn_on_object_refname_ambiguity;
warn_on_object_refname_ambiguity = 0;
strbuf_init(&sb, 1000);
while (strbuf_getline(&sb, stdin) != EOF) {
if (!sb.len)
break;
if (!strcmp(sb.buf, "--")) {
seen_dashdash = 1;
break;
}
if (!seen_end_of_options && sb.buf[0] == '-') {
const char *argv[] = { sb.buf, NULL };
if (!strcmp(sb.buf, "--end-of-options")) {
seen_end_of_options = 1;
continue;
}
if (handle_revision_pseudo_opt(revs, argv, flags) > 0)
continue;
die(_("invalid option '%s' in --stdin mode"), sb.buf);
}
if (handle_revision_arg(sb.buf, revs, 0,
REVARG_CANNOT_BE_FILENAME))
die("bad revision '%s'", sb.buf);
}
if (seen_dashdash)
read_pathspec_from_stdin(&sb, prune);
strbuf_release(&sb);
warn_on_object_refname_ambiguity = save_warning;
}
static void NORETURN diagnose_missing_default(const char *def)
{
int flags;
@ -2891,7 +2905,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
}
if (revs->read_from_stdin++)
die("--stdin given twice?");
read_revisions_from_stdin(revs, &prune_data);
read_revisions_from_stdin(revs, &prune_data, &flags);
continue;
}

View file

@ -48,7 +48,9 @@ test_expect_success setup '
git add file-$i &&
test_tick &&
git commit -m side-$i || exit
done
done &&
git update-ref refs/heads/-dashed-branch HEAD
)
'
@ -60,6 +62,12 @@ check side-1 ^side-7 -- file-2
check side-3 ^side-4 -- file-3
check side-3 ^side-2
check side-3 ^side-2 -- file-1
check --all
check --all --not --branches
check --glob=refs/heads
check --glob=refs/heads --
check --glob=refs/heads -- file-1
check --end-of-options -dashed-branch
test_expect_success 'not only --stdin' '
cat >expect <<-EOF &&
@ -78,4 +86,45 @@ test_expect_success 'not only --stdin' '
test_cmp expect actual
'
test_expect_success 'pseudo-opt with missing value' '
cat >input <<-EOF &&
--glob
refs/heads
EOF
cat >expect <<-EOF &&
fatal: Option ${SQ}--glob${SQ} requires a value
EOF
test_must_fail git rev-list --stdin <input 2>error &&
test_cmp expect error
'
test_expect_success 'pseudo-opt with invalid value' '
cat >input <<-EOF &&
--no-walk=garbage
EOF
cat >expect <<-EOF &&
error: invalid argument to --no-walk
fatal: invalid option ${SQ}--no-walk=garbage${SQ} in --stdin mode
EOF
test_must_fail git rev-list --stdin <input 2>error &&
test_cmp expect error
'
test_expect_success 'unknown option without --end-of-options' '
cat >input <<-EOF &&
-dashed-branch
EOF
cat >expect <<-EOF &&
fatal: invalid option ${SQ}-dashed-branch${SQ} in --stdin mode
EOF
test_must_fail git rev-list --stdin <input 2>error &&
test_cmp expect error
'
test_done