diff --git a/include/git2/refs.h b/include/git2/refs.h index 1ff0d4544..e1d425352 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -422,6 +422,13 @@ typedef enum { * (e.g., foo//bar but not foo/bar). */ GIT_REF_FORMAT_REFSPEC_PATTERN = (1 << 1), + + /** + * Interpret the name as part of a refspec in shorthand form + * so the `ONELEVEL` naming rules aren't enforced and 'master' + * becomes a valid name. + */ + GIT_REF_FORMAT_REFSPEC_SHORTHAND = (1 << 2), } git_reference_normalize_t; /** diff --git a/src/refs.c b/src/refs.c index 9c6684a5a..2faa4cb83 100644 --- a/src/refs.c +++ b/src/refs.c @@ -752,6 +752,7 @@ int git_reference__normalize_name( goto cleanup; if ((segments_count == 1 ) && + !(flags & GIT_REF_FORMAT_REFSPEC_SHORTHAND) && !(is_all_caps_and_underscore(name, (size_t)segment_len) || ((flags & GIT_REF_FORMAT_REFSPEC_PATTERN) && !strcmp("*", name)))) goto cleanup; diff --git a/src/refspec.c b/src/refspec.c index fbdea9d93..256540819 100644 --- a/src/refspec.c +++ b/src/refspec.c @@ -60,7 +60,7 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch) refspec->pattern = is_glob; refspec->src = git__strndup(lhs, llen); - flags = GIT_REF_FORMAT_ALLOW_ONELEVEL + flags = GIT_REF_FORMAT_ALLOW_ONELEVEL | GIT_REF_FORMAT_REFSPEC_SHORTHAND | (is_glob ? GIT_REF_FORMAT_REFSPEC_PATTERN : 0); if (is_fetch) { diff --git a/tests-clar/network/refspecs.c b/tests-clar/network/refspecs.c index b3d80fb85..676a1fa99 100644 --- a/tests-clar/network/refspecs.c +++ b/tests-clar/network/refspecs.c @@ -81,4 +81,7 @@ void test_network_refspecs__parsing(void) assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); + + assert_refspec(GIT_DIRECTION_FETCH, "master", true); + assert_refspec(GIT_DIRECTION_PUSH, "master", true); }