#include "clar_libgit2.h" #include "refspec.h" #include "remote.h" static void assert_refspec(unsigned int direction, const char *input, bool is_expected_to_be_valid) { git_refspec refspec; int error; error = git_refspec__parse(&refspec, input, direction == GIT_DIRECTION_FETCH); git_refspec__free(&refspec); if (is_expected_to_be_valid) cl_assert_equal_i(0, error); else cl_assert_equal_i(GIT_ERROR, error); } void test_network_refspecs__parsing(void) { // Ported from https://github.com/git/git/blob/abd2bde78bd994166900290434a2048e660dabed/t/t5511-refspec.sh assert_refspec(GIT_DIRECTION_PUSH, "", false); assert_refspec(GIT_DIRECTION_PUSH, ":", true); assert_refspec(GIT_DIRECTION_PUSH, "::", false); assert_refspec(GIT_DIRECTION_PUSH, "+:", true); assert_refspec(GIT_DIRECTION_FETCH, "", true); assert_refspec(GIT_DIRECTION_PUSH, ":", true); assert_refspec(GIT_DIRECTION_FETCH, "::", false); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*:refs/remotes/frotz/*", true); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*:refs/remotes/frotz", false); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads:refs/remotes/frotz/*", false); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/master:refs/remotes/frotz/xyzzy", true); /* * These have invalid LHS, but we do not have a formal "valid sha-1 * expression syntax checker" so they are not checked with the current * code. They will be caught downstream anyway, but we may want to * have tighter check later... */ //assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/master::refs/remotes/frotz/xyzzy", false); //assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*:refs/remotes/frotz/*", true); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*:refs/remotes/frotz", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads:refs/remotes/frotz/*", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/master:refs/remotes/frotz/xyzzy", true); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/master::refs/remotes/frotz/xyzzy", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false); assert_refspec(GIT_DIRECTION_PUSH, "master~1:refs/remotes/frotz/backup", true); assert_refspec(GIT_DIRECTION_FETCH, "master~1:refs/remotes/frotz/backup", false); assert_refspec(GIT_DIRECTION_PUSH, "HEAD~4:refs/remotes/frotz/new", true); assert_refspec(GIT_DIRECTION_FETCH, "HEAD~4:refs/remotes/frotz/new", false); assert_refspec(GIT_DIRECTION_PUSH, "HEAD", true); assert_refspec(GIT_DIRECTION_FETCH, "HEAD", true); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/ nitfol", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/ nitfol", false); assert_refspec(GIT_DIRECTION_PUSH, "HEAD:", false); assert_refspec(GIT_DIRECTION_FETCH, "HEAD:", true); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/ nitfol:", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/ nitfol:", false); assert_refspec(GIT_DIRECTION_PUSH, ":refs/remotes/frotz/deleteme", true); assert_refspec(GIT_DIRECTION_FETCH, ":refs/remotes/frotz/HEAD-to-me", true); assert_refspec(GIT_DIRECTION_PUSH, ":refs/remotes/frotz/delete me", false); assert_refspec(GIT_DIRECTION_FETCH, ":refs/remotes/frotz/HEAD to me", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads*/for-linus:refs/remotes/mine/*", false); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads*/for-linus:refs/remotes/mine/*", false); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); 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); assert_refspec(GIT_DIRECTION_FETCH, "refs/pull/*/head:refs/remotes/origin/pr/*", true); } static void assert_valid_transform(const char *refspec, const char *name, const char *result) { git_refspec spec; git_buf buf = GIT_BUF_INIT; git_refspec__parse(&spec, refspec, true); cl_git_pass(git_refspec_transform(&buf, &spec, name)); cl_assert_equal_s(result, buf.ptr); git_buf_free(&buf); git_refspec__free(&spec); } void test_network_refspecs__transform_mid_star(void) { assert_valid_transform("refs/pull/*/head:refs/remotes/origin/pr/*", "refs/pull/23/head", "refs/remotes/origin/pr/23"); assert_valid_transform("refs/heads/*:refs/remotes/origin/*", "refs/heads/master", "refs/remotes/origin/master"); assert_valid_transform("refs/heads/*:refs/remotes/origin/*", "refs/heads/user/feature", "refs/remotes/origin/user/feature"); assert_valid_transform("refs/heads/*:refs/heads/*", "refs/heads/master", "refs/heads/master"); assert_valid_transform("refs/heads/*:refs/heads/*", "refs/heads/user/feature", "refs/heads/user/feature"); assert_valid_transform("refs/*:refs/*", "refs/heads/master", "refs/heads/master"); } static void assert_invalid_transform(const char *refspec, const char *name) { git_refspec spec; git_buf buf = GIT_BUF_INIT; git_refspec__parse(&spec, refspec, true); cl_git_fail(git_refspec_transform(&buf, &spec, name)); git_buf_free(&buf); git_refspec__free(&spec); } void test_network_refspecs__invalid(void) { assert_invalid_transform("refs/heads/*:refs/remotes/origin/*", "master"); assert_invalid_transform("refs/heads/*:refs/remotes/origin/*", "refs/headz/master"); } static void assert_invalid_rtransform(const char *refspec, const char *name) { git_refspec spec; git_buf buf = GIT_BUF_INIT; git_refspec__parse(&spec, refspec, true); cl_git_fail(git_refspec_rtransform(&buf, &spec, name)); git_buf_free(&buf); git_refspec__free(&spec); } void test_network_refspecs__invalid_reverse(void) { assert_invalid_rtransform("refs/heads/*:refs/remotes/origin/*", "master"); assert_invalid_rtransform("refs/heads/*:refs/remotes/origin/*", "refs/remotes/o/master"); } void test_network_refspecs__matching(void) { git_refspec spec; cl_git_pass(git_refspec__parse(&spec, ":", false)); cl_assert_equal_s(":", spec.string); cl_assert_equal_s("", spec.src); cl_assert_equal_s("", spec.dst); git_refspec__free(&spec); }