revision: set rev_input_given in handle_revision_arg()

Commit 7ba826290a (revision: add rev_input_given flag, 2017-08-02) added
a flag to rev_info to tell whether we got any revision arguments. As
explained there, this is necessary because some revision arguments may
not produce any pending traversal objects, but should still inhibit
default behaviors (e.g., a glob that matches nothing).

However, it only set the flag in the globbing code, but not for
revisions we get on the command-line or via stdin. This leads to two
problems:

  - the command-line code keeps its own separate got_rev_arg flag; this
    isn't wrong, but it's confusing and an extra maintenance burden

  - even specifically-named rev arguments might end up not adding any
    pending objects: if --ignore-missing is set, then specifying a
    missing object is a noop rather than an error.

And that leads to some user-visible bugs:

  - when deciding whether a default rev like "HEAD" should kick in, we
    check both got_rev_arg and rev_input_given. That means that
    "--ignore-missing $ZERO_OID" works on the command-line (where we set
    got_rev_arg) but not on --stdin (where we don't)

  - when rev-list decides whether it should complain that it wasn't
    given a starting point, it relies on rev_input_given. So it can't
    even get the command-line "--ignore-missing $ZERO_OID" right

Let's consistently set the flag if we got any revision argument. That
lets us clean up the redundant got_rev_arg, and fixes both of those bugs
(but note there are three new tests: we'll confirm the already working
git-log command-line case).

A few implementation notes:

  - conceptually we want to set the flag whenever handle_revision_arg()
    finds an actual revision arg ("handles" it, you might say). But it
    covers a ton of cases with early returns. Rather than annotating
    each one, we just wrap it and use its success exit-code to set the
    flag in one spot.

  - the new rev-list test is in t6018, which is titled to cover globs.
    This isn't exactly a glob, but it made sense to stick it with the
    other tests that handle the "even though we got a rev, we have no
    pending objects" case, which are globs.

  - the tests check for the oid of a missing object, which it's pretty
    clear --ignore-missing should ignore. You can see the same behavior
    with "--ignore-missing a-ref-that-does-not-exist", because
    --ignore-missing treats them both the same. That's perhaps less
    clearly correct, and we may want to change that in the future. But
    the way the code and tests here are written, we'd continue to do the
    right thing even if it does.

Reported-by: Bryan Turner <bturner@atlassian.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2020-08-26 16:13:05 -04:00 коммит произвёл Junio C Hamano
Родитель 47ae905ffb
Коммит 04a0e98515
3 изменённых файлов: 26 добавлений и 5 удалений

Просмотреть файл

@ -1997,7 +1997,7 @@ static int handle_dotdot(const char *arg,
return ret;
}
int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt)
static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt)
{
struct object_context oc;
char *mark;
@ -2072,6 +2072,14 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
return 0;
}
int handle_revision_arg(const char *arg, struct rev_info *revs, int flags, unsigned revarg_opt)
{
int ret = handle_revision_arg_1(arg, revs, flags, revarg_opt);
if (!ret)
revs->rev_input_given = 1;
return ret;
}
static void read_pathspec_from_stdin(struct strbuf *sb,
struct argv_array *prune)
{
@ -2674,7 +2682,7 @@ static void NORETURN diagnose_missing_default(const char *def)
*/
int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *opt)
{
int i, flags, left, seen_dashdash, got_rev_arg = 0, revarg_opt;
int i, flags, left, seen_dashdash, revarg_opt;
struct argv_array prune_data = ARGV_ARRAY_INIT;
const char *submodule = NULL;
int seen_end_of_options = 0;
@ -2763,8 +2771,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
argv_array_pushv(&prune_data, argv + i);
break;
}
else
got_rev_arg = 1;
}
if (prune_data.argc) {
@ -2793,7 +2799,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
opt->tweak(revs, opt);
if (revs->show_merge)
prepare_show_merge(revs);
if (revs->def && !revs->pending.nr && !revs->rev_input_given && !got_rev_arg) {
if (revs->def && !revs->pending.nr && !revs->rev_input_given) {
struct object_id oid;
struct object *object;
struct object_context oc;

Просмотреть файл

@ -1850,6 +1850,16 @@ test_expect_success 'log does not default to HEAD when rev input is given' '
test_must_be_empty actual
'
test_expect_success 'do not default to HEAD with ignored object on cmdline' '
git log --ignore-missing $ZERO_OID >actual &&
test_must_be_empty actual
'
test_expect_success 'do not default to HEAD with ignored object on stdin' '
echo $ZERO_OID | git log --ignore-missing --stdin >actual &&
test_must_be_empty actual
'
test_expect_success 'set up --source tests' '
git checkout --orphan source-a &&
test_commit one &&

Просмотреть файл

@ -345,6 +345,11 @@ test_expect_success 'rev-list should succeed with empty output with empty glob'
test_must_be_empty actual
'
test_expect_success 'rev-list should succeed with empty output when ignoring missing' '
git rev-list --ignore-missing $ZERO_OID >actual &&
test_must_be_empty actual
'
test_expect_success 'shortlog accepts --glob/--tags/--remotes' '
compare shortlog "subspace/one subspace/two" --branches=subspace &&