rev-parse: handle --end-of-options
We taught rev-list a new way to separate options from revisions in
19e8789b23
(revision: allow --end-of-options to end option parsing,
2019-08-06), but rev-parse uses its own parser. It should know about
--end-of-options not only for consistency, but because it may be
presented with similarly ambiguous cases. E.g., if a caller does:
git rev-parse "$rev" -- "$path"
to parse an untrusted input, then it will get confused if $rev contains
an option-like string like "--local-env-vars". Or even "--not-real",
which we'd keep as an option to pass along to rev-list.
Or even more importantly:
git rev-parse --verify "$rev"
can be confused by options, even though its purpose is safely parsing
untrusted input. On the plus side, it will always fail the --verify
part, as it will not have parsed a revision, so the caller will
generally "fail closed" rather than continue to use the untrusted
string. But it will still trigger whatever option was in "$rev"; this
should be mostly harmless, since rev-parse options are all read-only,
but I didn't carefully audit all paths.
This patch lets callers write:
git rev-parse --end-of-options "$rev" -- "$path"
and:
git rev-parse --verify --end-of-options "$rev"
which will both treat "$rev" always as a revision parameter. The latter
is a bit clunky. It would be nicer if we had defined "--verify" to
require that its next argument be the revision. But we have not
historically done so, and:
git rev-parse --verify -q "$rev"
does currently work. I added a test here to confirm that we didn't break
that.
A few implementation notes:
- We don't document --end-of-options explicitly in commands, but rather
in gitcli(7). So I didn't give it its own section in git-rev-parse(1).
But I did call it out specifically in the --verify section, and
include it in the examples, which should show best practices.
- We don't have to re-indent the main option-parsing block, because we
can combine our "did we see end of options" check with "does it start
with a dash". The exception is the pre-setup options, which need
their own block.
- We do however have to pull the "--" parsing out of the "does it start
with dash" block, because we want to parse it even if we've seen
--end-of-options.
- We'll leave "--end-of-options" in the output. This is probably not
technically necessary, as a careful caller will do:
git rev-parse --end-of-options $revs -- $paths
and anything in $revs will be resolved to an object id. However, it
does help a slightly less careful caller like:
git rev-parse --end-of-options $revs_or_paths
where a path "--foo" will remain in the output as long as it also
exists on disk. In that case, it's helpful to retain --end-of-options
to get passed along to rev-list, s it would otherwise see just
"--foo".
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
9033addfa6
commit
3a1f91cfd9
@ -109,6 +109,10 @@ names an existing object that is a commit-ish (i.e. a commit, or an
|
||||
annotated tag that points at a commit). To make sure that `$VAR`
|
||||
names an existing object of any type, `git rev-parse "$VAR^{object}"`
|
||||
can be used.
|
||||
+
|
||||
Note that if you are verifying a name from an untrusted source, it is
|
||||
wise to use `--end-of-options` so that the name argument is not mistaken
|
||||
for another option.
|
||||
|
||||
-q::
|
||||
--quiet::
|
||||
@ -446,7 +450,7 @@ $ git rev-parse --verify HEAD
|
||||
* Print the commit object name from the revision in the $REV shell variable:
|
||||
+
|
||||
------------
|
||||
$ git rev-parse --verify $REV^{commit}
|
||||
$ git rev-parse --verify --end-of-options $REV^{commit}
|
||||
------------
|
||||
+
|
||||
This will error out if $REV is empty or not a valid revision.
|
||||
@ -454,7 +458,7 @@ This will error out if $REV is empty or not a valid revision.
|
||||
* Similar to above:
|
||||
+
|
||||
------------
|
||||
$ git rev-parse --default master --verify $REV
|
||||
$ git rev-parse --default master --verify --end-of-options $REV
|
||||
------------
|
||||
+
|
||||
but if $REV is empty, the commit object name from master will be printed.
|
||||
|
Reference in New Issue
Block a user