Merge pull request #7148 from roberth/refs-shorthand-multi-segment

refs: honor REFSPEC_SHORTHAND for multi-segment refs
This commit is contained in:
Edward Thomson
2025-12-20 13:08:02 +00:00
committed by GitHub
2 changed files with 54 additions and 0 deletions

View File

@@ -1018,6 +1018,7 @@ int git_reference__normalize_name(
goto cleanup;
if ((segments_count > 1)
&& !(flags & GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND)
&& (is_valid_normalized_name(name, strchr(name, '/') - name)))
goto cleanup;

View File

@@ -407,3 +407,56 @@ void test_refs_normalize__negative_refspec_pattern(void)
ensure_refname_invalid(
GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "foo/^bar");
}
void test_refs_normalize__refspec_shorthand_allows_uppercase_segments(void)
{
/* Without REFSPEC_SHORTHAND, multi-level refs starting with ALL_CAPS (pseudorefs) should be rejected */
ensure_refname_invalid(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "A/b");
ensure_refname_invalid(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "FOO/BAR/BAZ");
ensure_refname_invalid(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "HEAD_TRACKER/foo");
ensure_refname_invalid(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "HEAD/feature");
ensure_refname_invalid(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "FETCH_HEAD/branch");
ensure_refname_invalid(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "MERGE_HEAD/test");
/* With REFSPEC_SHORTHAND, they should be allowed (used in refspecs like "A/b:refs/heads/A/b") */
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL | GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND,
"A/b", "A/b");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL | GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND,
"FOO/BAR/BAZ", "FOO/BAR/BAZ");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL | GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND,
"HEAD_TRACKER/foo", "HEAD_TRACKER/foo");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL | GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND,
"HEAD/feature", "HEAD/feature");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL | GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND,
"FETCH_HEAD/branch", "FETCH_HEAD/branch");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL | GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND,
"MERGE_HEAD/test", "MERGE_HEAD/test");
/* Mixed case first segments don't look like pseudorefs, so they're allowed even without SHORTHAND */
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "AaA/b", "AaA/b");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "Head/feature", "Head/feature");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL, "merge_head/test", "merge_head/test");
/* Fully qualified refs starting with uppercase should always be allowed */
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/A/b", "refs/heads/A/b");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/FOO/BAR", "refs/heads/FOO/BAR");
ensure_refname_normalized(
GIT_REFERENCE_FORMAT_NORMAL, "refs/heads/HEAD/feature", "refs/heads/HEAD/feature");
}