summaryrefslogtreecommitdiff
path: root/revision.c
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2023-06-15 14:39:59 (GMT)
committerJunio C Hamano <gitster@pobox.com>2023-06-15 19:09:31 (GMT)
commitc40f0b78771ecc8696014e2e0aa37e78417b4723 (patch)
tree6507c00163a5237029b13ad8d04c93f5a8c61524 /revision.c
parentaf37a209ad76ce760becc0d2c2fac63c2022e730 (diff)
downloadgit-c40f0b78771ecc8696014e2e0aa37e78417b4723.zip
git-c40f0b78771ecc8696014e2e0aa37e78417b4723.tar.gz
git-c40f0b78771ecc8696014e2e0aa37e78417b4723.tar.bz2
revision: handle pseudo-opts in `--stdin` mode
While both git-rev-list(1) and git-log(1) support `--stdin`, it only accepts commits and files. Most notably, it is impossible to pass any of the pseudo-opts like `--all`, `--glob=` or others via stdin. This makes it hard to use this function in certain scripted scenarios, like when one wants to support queries against specific revisions, but also against reference patterns. While this is theoretically possible by using arguments, this may run into issues once we hit platform limits with sufficiently large queries. And because `--stdin` cannot handle pseudo-opts, the only alternative would be to use a mixture of arguments and standard input, which is cumbersome. Implement support for handling pseudo-opts in both commands to support this usecase better. One notable restriction here is that `--stdin` only supports "stuck" arguments in the form of `--glob=foo`. This is because "unstuck" arguments would also require us to read the next line, which would add quite some complexity to the code. This restriction should be fine for scripted usage though. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'revision.c')
-rw-r--r--revision.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/revision.c b/revision.c
index 3a39f41..a0b1479 100644
--- a/revision.c
+++ b/revision.c
@@ -2784,10 +2784,12 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
}
static void read_revisions_from_stdin(struct rev_info *revs,
- struct strvec *prune)
+ 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;
@@ -2803,8 +2805,19 @@ static void read_revisions_from_stdin(struct rev_info *revs,
break;
}
- if (sb.buf[0] == '-')
- die("options not supported in --stdin mode");
+ 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))
@@ -2889,7 +2902,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;
}