summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2016-09-26 11:59:41 (GMT)
committerJunio C Hamano <gitster@pobox.com>2016-09-26 18:46:30 (GMT)
commit8a10fea49b1f95daeea445072a60139590b216cf (patch)
tree6af8d5fb5afc4a9e0bda1e6f65de4663f6311b86
parent7243ffdd78d56738e568abb544eba00e8079f329 (diff)
downloadgit-8a10fea49b1f95daeea445072a60139590b216cf.zip
git-8a10fea49b1f95daeea445072a60139590b216cf.tar.gz
git-8a10fea49b1f95daeea445072a60139590b216cf.tar.bz2
get_sha1: propagate flags to child functions
The get_sha1() function is actually implementation by many sub-functions, but we do not always pass our flags around to all of those functions. As a result, we may forget that our caller asked us to resolve with GET_SHA1_QUIETLY and output messages. The two triggerable cases are: 1. Resolving treeish:path will resolve the "treeish" portion using GET_SHA1_TREEISH, dropping all other flags. 2. The peel_onion() function did not take flags at all but recurses to get_sha1_1(), which does. The solution for both is to bitwise-OR their new flags with the existing ones (after dropping any mutually exclusive disambiguation flags). This bug can trigger with "git rev-parse --quiet", which asks for quiet resolution. But it can also happen in a more vanilla code path when we do a follow-up ONLY_TO_DIE invocation of get_sha1(), and that's what the tests check. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--sha1_name.c18
-rwxr-xr-xt/t1512-rev-parse-disambiguation.sh14
2 files changed, 25 insertions, 7 deletions
diff --git a/sha1_name.c b/sha1_name.c
index e7e3a38..9356ac2 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -681,12 +681,12 @@ struct object *peel_to_type(const char *name, int namelen,
}
}
-static int peel_onion(const char *name, int len, unsigned char *sha1)
+static int peel_onion(const char *name, int len, unsigned char *sha1,
+ unsigned lookup_flags)
{
unsigned char outer[20];
const char *sp;
unsigned int expected_type = 0;
- unsigned lookup_flags = 0;
struct object *o;
/*
@@ -726,10 +726,11 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
else
return -1;
+ lookup_flags &= ~GET_SHA1_DISAMBIGUATORS;
if (expected_type == OBJ_COMMIT)
- lookup_flags = GET_SHA1_COMMITTISH;
+ lookup_flags |= GET_SHA1_COMMITTISH;
else if (expected_type == OBJ_TREE)
- lookup_flags = GET_SHA1_TREEISH;
+ lookup_flags |= GET_SHA1_TREEISH;
if (get_sha1_1(name, sp - name - 2, outer, lookup_flags))
return -1;
@@ -830,7 +831,7 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
return get_nth_ancestor(name, len1, sha1, num);
}
- ret = peel_onion(name, len, sha1);
+ ret = peel_onion(name, len, sha1, lookup_flags);
if (!ret)
return 0;
@@ -1465,7 +1466,12 @@ static int get_sha1_with_context_1(const char *name,
if (*cp == ':') {
unsigned char tree_sha1[20];
int len = cp - name;
- if (!get_sha1_1(name, len, tree_sha1, GET_SHA1_TREEISH)) {
+ unsigned sub_flags = flags;
+
+ sub_flags &= ~GET_SHA1_DISAMBIGUATORS;
+ sub_flags |= GET_SHA1_TREEISH;
+
+ if (!get_sha1_1(name, len, tree_sha1, sub_flags)) {
const char *filename = cp+1;
char *new_filename = NULL;
diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh
index 16f9709..30e0b80 100755
--- a/t/t1512-rev-parse-disambiguation.sh
+++ b/t/t1512-rev-parse-disambiguation.sh
@@ -291,10 +291,22 @@ test_expect_success 'ambiguous short sha1 ref' '
grep "refname.*${REF}.*ambiguous" err
'
-test_expect_success C_LOCALE_OUTPUT 'ambiguity errors are not repeated' '
+test_expect_success C_LOCALE_OUTPUT 'ambiguity errors are not repeated (raw)' '
test_must_fail git rev-parse 00000 2>stderr &&
grep "is ambiguous" stderr >errors &&
test_line_count = 1 errors
'
+test_expect_success C_LOCALE_OUTPUT 'ambiguity errors are not repeated (treeish)' '
+ test_must_fail git rev-parse 00000:foo 2>stderr &&
+ grep "is ambiguous" stderr >errors &&
+ test_line_count = 1 errors
+'
+
+test_expect_success C_LOCALE_OUTPUT 'ambiguity errors are not repeated (peel)' '
+ test_must_fail git rev-parse 00000^{commit} 2>stderr &&
+ grep "is ambiguous" stderr >errors &&
+ test_line_count = 1 errors
+'
+
test_done