Git fork

Merge branch 'en/object-name-with-funny-refname-fix'

Extended SHA-1 expression parser did not work well when a branch
with an unusual name (e.g. "foo{bar") is involved.

* en/object-name-with-funny-refname-fix:
object-name: be more strict in parsing describe-like output
object-name: fix resolution of object names containing curly braces

+113 -5
+59 -4
object-name.c
··· 1272 1272 return 0; 1273 1273 } 1274 1274 1275 + /* 1276 + * Documentation/revisions.txt says: 1277 + * '<describeOutput>', e.g. 'v1.7.4.2-679-g3bee7fb':: 1278 + * Output from `git describe`; i.e. a closest tag, optionally 1279 + * followed by a dash and a number of commits, followed by a dash, a 1280 + * 'g', and an abbreviated object name. 1281 + * 1282 + * which means that the stuff before '-g${HASH}' needs to be a valid 1283 + * refname, a dash, and a non-negative integer. This function verifies 1284 + * that. 1285 + * 1286 + * In particular, we do not want to treat 1287 + * branchname:path/to/file/named/i-gaffed 1288 + * as a request for commit affed. 1289 + * 1290 + * More generally, we should probably not treat 1291 + * 'refs/heads/./../.../ ~^:/?*[////\\\&}/busted.lock-g050e0ef6ead' 1292 + * as a request for object 050e0ef6ead either. 1293 + * 1294 + * We are called with name[len] == '-' and name[len+1] == 'g', i.e. 1295 + * we are verifying ${REFNAME}-{INTEGER} part of the name. 1296 + */ 1297 + static int ref_and_count_parts_valid(const char *name, int len) 1298 + { 1299 + struct strbuf sb; 1300 + const char *cp; 1301 + int flags = REFNAME_ALLOW_ONELEVEL; 1302 + int ret = 1; 1303 + 1304 + /* Ensure we have at least one digit */ 1305 + if (!isxdigit(name[len-1])) 1306 + return 0; 1307 + 1308 + /* Skip over digits backwards until we get to the dash */ 1309 + for (cp = name + len - 2; name < cp; cp--) { 1310 + if (*cp == '-') 1311 + break; 1312 + if (!isxdigit(*cp)) 1313 + return 0; 1314 + } 1315 + /* Ensure we found the leading dash */ 1316 + if (*cp != '-') 1317 + return 0; 1318 + 1319 + len = cp - name; 1320 + strbuf_init(&sb, len); 1321 + strbuf_add(&sb, name, len); 1322 + ret = !check_refname_format(sb.buf, flags); 1323 + strbuf_release(&sb); 1324 + return ret; 1325 + } 1326 + 1275 1327 static int get_describe_name(struct repository *r, 1276 1328 const char *name, int len, 1277 1329 struct object_id *oid) ··· 1285 1337 /* We must be looking at g in "SOMETHING-g" 1286 1338 * for it to be describe output. 1287 1339 */ 1288 - if (ch == 'g' && cp[-1] == '-') { 1340 + if (ch == 'g' && cp[-1] == '-' && 1341 + ref_and_count_parts_valid(name, cp - 1 - name)) { 1289 1342 cp++; 1290 1343 len -= cp - name; 1291 1344 return get_short_oid(r, ··· 2052 2105 return -1; 2053 2106 } 2054 2107 for (cp = name, bracket_depth = 0; *cp; cp++) { 2055 - if (*cp == '{') 2108 + if (strchr("@^", *cp) && cp[1] == '{') { 2109 + cp++; 2056 2110 bracket_depth++; 2057 - else if (bracket_depth && *cp == '}') 2111 + } else if (bracket_depth && *cp == '}') { 2058 2112 bracket_depth--; 2059 - else if (!bracket_depth && *cp == ':') 2113 + } else if (!bracket_depth && *cp == ':') { 2060 2114 break; 2115 + } 2061 2116 } 2062 2117 if (*cp == ':') { 2063 2118 struct object_id tree_oid;
+30 -1
t/t1006-cat-file.sh
··· 240 240 git config extensions.objectformat $test_hash_algo && 241 241 git config extensions.compatobjectformat $test_compat_hash_algo && 242 242 echo_without_newline "$hello_content" > hello && 243 - git update-index --add hello 243 + git update-index --add hello && 244 + git commit -m "add hello file" 244 245 ' 245 246 246 247 run_blob_tests () { ··· 599 600 test_expect_success FUNNYNAMES '--batch-check, -Z with newline in input' ' 600 601 git cat-file --batch-check -Z <in >actual && 601 602 printf "%s\0" "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && 603 + test_cmp expect actual 604 + ' 605 + 606 + test_expect_success 'setup with curly braches in input' ' 607 + git branch "foo{bar" HEAD && 608 + git branch "foo@" HEAD 609 + ' 610 + 611 + test_expect_success 'object reference with curly brace' ' 612 + git cat-file -p "foo{bar:hello" >actual && 613 + git cat-file -p HEAD:hello >expect && 614 + test_cmp expect actual 615 + ' 616 + 617 + test_expect_success 'object reference with at-sign' ' 618 + git cat-file -p "foo@@{0}:hello" >actual && 619 + git cat-file -p HEAD:hello >expect && 620 + test_cmp expect actual 621 + ' 622 + 623 + test_expect_success 'setup with commit with colon' ' 624 + git commit-tree -m "testing: just a bunch of junk" HEAD^{tree} >out && 625 + git branch other $(cat out) 626 + ' 627 + 628 + test_expect_success 'object reference via commit text search' ' 629 + git cat-file -p "other^{/testing:}:hello" >actual && 630 + git cat-file -p HEAD:hello >expect && 602 631 test_cmp expect actual 603 632 ' 604 633
+24
t/t6120-describe.sh
··· 82 82 check_describe A-3-gHASH HEAD^^2 83 83 check_describe B HEAD^^2^ 84 84 check_describe R-1-gHASH HEAD^^^ 85 + check_describe R-1-gHASH R-1-g$(git rev-parse --short HEAD^^)~1 85 86 86 87 check_describe c-7-gHASH --tags HEAD 87 88 check_describe c-6-gHASH --tags HEAD^ 88 89 check_describe e-1-gHASH --tags HEAD^^ 89 90 check_describe c-2-gHASH --tags HEAD^^2 91 + check_describe c-2-gHASH --tags c-2-g$(git rev-parse --short HEAD^^2)^0 90 92 check_describe B --tags HEAD^^2^ 91 93 check_describe e --tags HEAD^^^ 92 94 check_describe e --tags --exact-match HEAD^^^ ··· 723 725 724 726 test_expect_success '--exact-match does not show --always fallback' ' 725 727 test_must_fail git describe --exact-match --always 728 + ' 729 + 730 + test_expect_success 'avoid being fooled by describe-like filename' ' 731 + test_when_finished rm out && 732 + 733 + git rev-parse --short HEAD >out && 734 + FILENAME=filename-g$(cat out) && 735 + touch $FILENAME && 736 + git add $FILENAME && 737 + git commit -m "Add $FILENAME" && 738 + 739 + git cat-file -t HEAD:$FILENAME >actual && 740 + 741 + echo blob >expect && 742 + test_cmp expect actual 743 + ' 744 + 745 + test_expect_success 'do not be fooled by invalid describe format ' ' 746 + test_when_finished rm out && 747 + 748 + git rev-parse --short HEAD >out && 749 + test_must_fail git cat-file -t "refs/tags/super-invalid/./../...../ ~^:/?*[////\\\\\\&}/busted.lock-42-g"$(cat out) 726 750 ' 727 751 728 752 test_done