[PATCH v2] revision: allow missing promisor objects on CLI
From: Jonathan Tan <hidden>
Date: 2019-12-30 23:45:14
Subsystem:
the rest · Maintainer:
Linus Torvalds
Commit 4cf67869b2 ("list-objects.c: don't segfault for missing cmdline
objects", 2018-12-06) prevented some segmentation faults from occurring
by tightening handling of missing objects provided through the CLI: if
--ignore-missing is set, then it is OK (and the missing object ignored,
just like one would if encountered in traversal).
However, in the case that --ignore-missing is not set but
--exclude-promisor-objects is set, there is still no distinction between
the case wherein the missing object is a promisor object and the case
wherein it is not. This is unnecessarily restrictive, since if a missing
promisor object is encountered in traversal, it is ignored; likewise it
should be ignored if provided through the CLI. Therefore, distinguish
between these 2 cases. (As a bonus, the code is now simpler.)
(Note that this only affects handling of missing promisor objects.
Handling of non-missing promisor objects is already done by setting all
of them to UNINTERESTING in prepare_revision_walk().)
Additionally, clarify in get_reference() that error messages are already
being printed by the functions called (parse_object(),
repo_parse_commit(), and parse_commit_buffer() - invoked by the latter).
Signed-off-by: Jonathan Tan <redacted>
---
Changes from v1: Improved code comments and commit message
This is the case where oid must be COMMIT from oid_object_info()'s point of view, but repo_parse_commit() finds it as a non-commit, and object becomes NULL. This is quite different from the normal lazy clone case where exclude-promisor-objects etc. wants to cover, that the object whose name is oid is truly missing because it can be fetched later from elsewhere. Instead, we have found that there is an inconsistency in the data we have about the object, iow, a possible corruption.
Thanks! I should have looked at the first half of get_reference() more carefully. If there is corruption in the form of hash mismatch, parse_object() will print a message and then return NULL, leaving get_reference() to handle it - and treat it as missing in this case. It seems reasonable to me to handle the repo_parse_commit() failure in a similar way. I've added comments to clarify that error messages are being printed. --- revision.c | 23 ++++++++++++++++++++++- t/t0410-partial-clone.sh | 10 ++-------- 2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/revision.c b/revision.c
index 8136929e23..af1e31b4fc 100644
--- a/revision.c
+++ b/revision.c@@ -370,8 +370,18 @@ static struct object *get_reference(struct rev_info *revs, const char *name, if (!repo_parse_commit(revs->repo, c)) object = (struct object *) c; else + /* + * There is something wrong with the commit. + * repo_parse_commit() will have already printed an + * error message. For our purposes, treat as missing. + */ object = NULL; } else { + /* + * There is something wrong with the object. parse_object() + * will have already printed an error message. For our + * purposes, treat as missing. + */ object = parse_object(revs->repo, oid); }
@@ -1907,7 +1917,18 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi verify_non_filename(revs->prefix, arg); object = get_reference(revs, arg, &oid, flags ^ local_flags); if (!object) - return revs->ignore_missing ? 0 : -1; + /* + * If this object is corrupt, get_reference() prints an error + * message and treats it as missing. + * + * get_reference() returns NULL only if this object is missing + * and ignore_missing is true, or this object is a (missing) + * promisor object and exclude_promisor_objects is true. In + * both these cases, we can safely ignore this object because + * this object will not appear in output and cannot be used as + * a source of UNINTERESTING ancestors (since it is missing). + */ + return 0; add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags); add_pending_object_with_path(revs, object, arg, oc.mode, oc.path); free(oc.path);
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index a3988bd4b8..fd28f5402a 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh@@ -416,15 +416,9 @@ test_expect_success 'rev-list dies for missing objects on cmd line' ' git -C repo config extensions.partialclone "arbitrary string" && for OBJ in "$COMMIT" "$TREE" "$BLOB"; do - test_must_fail git -C repo rev-list --objects \ + git -C repo rev-list --objects \ --exclude-promisor-objects "$OBJ" && - test_must_fail git -C repo rev-list --objects-edge-aggressive \ - --exclude-promisor-objects "$OBJ" && - - # Do not die or crash when --ignore-missing is passed. - git -C repo rev-list --ignore-missing --objects \ - --exclude-promisor-objects "$OBJ" && - git -C repo rev-list --ignore-missing --objects-edge-aggressive \ + git -C repo rev-list --objects-edge-aggressive \ --exclude-promisor-objects "$OBJ" done '
--
2.24.1.735.g03f4e72817-goog