diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2021-12-23 14:12:23 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-23 14:12:23 -0500 |
commit | dca31d2427ef2321fab61bd5e3f3470306ba445d (patch) | |
tree | 7be580b3efdc2687fd4376fda2a6af724ecfde45 | |
parent | ab5b3f37f5e74805250685a08fa9f4220e5dba12 (diff) | |
parent | de665a430a36aace250845c75094b07cf9c1735c (diff) | |
download | libgit2-dca31d2427ef2321fab61bd5e3f3470306ba445d.tar.gz |
Merge pull request #6101 from mkhl/fix/instead-of
remotes: fix insteadOf/pushInsteadOf handling
-rw-r--r-- | src/remote.c | 30 | ||||
-rw-r--r-- | tests/remote/insteadof.c | 110 | ||||
-rw-r--r-- | tests/resources/testrepo2/.gitted/config | 41 |
3 files changed, 153 insertions, 28 deletions
diff --git a/src/remote.c b/src/remote.c index bde4ce779..fb9f6f8da 100644 --- a/src/remote.c +++ b/src/remote.c @@ -30,7 +30,7 @@ static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs); static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name); -char *apply_insteadof(git_config *config, const char *url, int direction); +char *apply_insteadof(bool *matched, git_config *config, const char *url, int direction); static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch) { @@ -210,7 +210,9 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem git_str var = GIT_STR_INIT; git_str specbuf = GIT_STR_INIT; const git_remote_create_options dummy_opts = GIT_REMOTE_CREATE_OPTIONS_INIT; + char *tmp; int error = -1; + bool matched; GIT_ASSERT_ARG(out); GIT_ASSERT_ARG(url); @@ -245,7 +247,12 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem goto on_error; if (opts->repository && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) { - remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH); + remote->url = apply_insteadof(&matched, config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH); + tmp = apply_insteadof(&matched, config_ro, canonical_url.ptr, GIT_DIRECTION_PUSH); + if (matched) { + remote->pushurl = tmp; + GIT_ERROR_CHECK_ALLOC(remote->pushurl); + } } else { remote->url = git__strdup(canonical_url.ptr); } @@ -457,7 +464,9 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) git_remote *remote = NULL; git_str buf = GIT_STR_INIT; const char *val; + char *tmp; int error = 0; + bool matched; git_config *config; struct refspec_cb_data data = { NULL }; bool optional_setting_found = false, found; @@ -498,8 +507,13 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; if (found && strlen(val) > 0) { - remote->url = apply_insteadof(config, val, GIT_DIRECTION_FETCH); + remote->url = apply_insteadof(&matched, config, val, GIT_DIRECTION_FETCH); GIT_ERROR_CHECK_ALLOC(remote->url); + tmp = apply_insteadof(&matched, config, val, GIT_DIRECTION_PUSH); + if (matched) { + remote->pushurl = tmp; + GIT_ERROR_CHECK_ALLOC(remote->pushurl); + } } val = NULL; @@ -518,7 +532,10 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) } if (found && strlen(val) > 0) { - remote->pushurl = apply_insteadof(config, val, GIT_DIRECTION_PUSH); + if (remote->pushurl) { + git__free(remote->pushurl); + } + remote->pushurl = apply_insteadof(&matched, config, val, GIT_DIRECTION_FETCH); GIT_ERROR_CHECK_ALLOC(remote->pushurl); } @@ -2719,7 +2736,7 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_ #define SUFFIX_FETCH "insteadof" #define SUFFIX_PUSH "pushinsteadof" -char *apply_insteadof(git_config *config, const char *url, int direction) +char *apply_insteadof(bool *matched, git_config *config, const char *url, int direction) { size_t match_length, prefix_length, suffix_length; char *replacement = NULL; @@ -2732,6 +2749,8 @@ char *apply_insteadof(git_config *config, const char *url, int direction) GIT_ASSERT_ARG_WITH_RETVAL(config, NULL); GIT_ASSERT_ARG_WITH_RETVAL(url, NULL); GIT_ASSERT_ARG_WITH_RETVAL(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH, NULL); + GIT_ASSERT_ARG_WITH_RETVAL(matched, NULL); + *matched = 0; /* Add 1 to prefix/suffix length due to the additional escaped dot */ prefix_length = strlen(PREFIX) + 1; @@ -2777,6 +2796,7 @@ char *apply_insteadof(git_config *config, const char *url, int direction) git__free(replacement); + *matched = 1; return result.ptr; } diff --git a/tests/remote/insteadof.c b/tests/remote/insteadof.c index 05d4757cf..c39df4be7 100644 --- a/tests/remote/insteadof.c +++ b/tests/remote/insteadof.c @@ -4,7 +4,12 @@ #define REPO_PATH "testrepo2/.gitted" #define REMOTE_ORIGIN "origin" -#define REMOTE_INSTEADOF "insteadof-test" +#define REMOTE_INSTEADOF_URL_FETCH "insteadof-url-fetch" +#define REMOTE_INSTEADOF_URL_PUSH "insteadof-url-push" +#define REMOTE_INSTEADOF_URL_BOTH "insteadof-url-both" +#define REMOTE_INSTEADOF_PUSHURL_FETCH "insteadof-pushurl-fetch" +#define REMOTE_INSTEADOF_PUSHURL_PUSH "insteadof-pushurl-push" +#define REMOTE_INSTEADOF_PUSHURL_BOTH "insteadof-pushurl-both" static git_repository *g_repo; static git_remote *g_remote; @@ -21,7 +26,7 @@ void test_remote_insteadof__cleanup(void) git_remote_free(g_remote); } -void test_remote_insteadof__url_insteadof_not_applicable(void) +void test_remote_insteadof__not_applicable(void) { cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_ORIGIN)); @@ -29,44 +34,121 @@ void test_remote_insteadof__url_insteadof_not_applicable(void) cl_assert_equal_s( git_remote_url(g_remote), "https://github.com/libgit2/false.git"); + cl_assert_equal_p(git_remote_pushurl(g_remote), NULL); } -void test_remote_insteadof__url_insteadof_applicable(void) +void test_remote_insteadof__url_insteadof_fetch(void) { cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); - cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF)); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_URL_FETCH)); cl_assert_equal_s( git_remote_url(g_remote), - "http://github.com/libgit2/libgit2"); + "http://github.com/url/fetch/libgit2"); + cl_assert_equal_p(git_remote_pushurl(g_remote), NULL); } -void test_remote_insteadof__pushurl_insteadof_not_applicable(void) +void test_remote_insteadof__url_insteadof_push(void) { cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); - cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_ORIGIN)); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_URL_PUSH)); - cl_assert_equal_p(git_remote_pushurl(g_remote), NULL); + cl_assert_equal_s( + git_remote_url(g_remote), + "http://example.com/url/push/libgit2"); + cl_assert_equal_s( + git_remote_pushurl(g_remote), + "git@github.com:url/push/libgit2"); } -void test_remote_insteadof__pushurl_insteadof_applicable(void) +void test_remote_insteadof__url_insteadof_both(void) { cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); - cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF)); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_URL_BOTH)); cl_assert_equal_s( + git_remote_url(g_remote), + "http://github.com/url/both/libgit2"); + cl_assert_equal_s( git_remote_pushurl(g_remote), - "git@github.com:libgit2/libgit2"); + "git@github.com:url/both/libgit2"); } -void test_remote_insteadof__anonymous_remote(void) +void test_remote_insteadof__pushurl_insteadof_fetch(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_PUSHURL_FETCH)); + + cl_assert_equal_s( + git_remote_url(g_remote), + "http://github.com/url/fetch/libgit2"); + cl_assert_equal_s( + git_remote_pushurl(g_remote), + "http://github.com/url/fetch/libgit2-push"); +} + +void test_remote_insteadof__pushurl_insteadof_push(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_PUSHURL_PUSH)); + + cl_assert_equal_s( + git_remote_url(g_remote), + "http://example.com/url/push/libgit2"); + cl_assert_equal_s( + git_remote_pushurl(g_remote), + "http://example.com/url/push/libgit2-push"); +} + +void test_remote_insteadof__pushurl_insteadof_both(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_PUSHURL_BOTH)); + + cl_assert_equal_s( + git_remote_url(g_remote), + "http://github.com/url/both/libgit2"); + cl_assert_equal_s( + git_remote_pushurl(g_remote), + "http://github.com/url/both/libgit2-push"); +} + +void test_remote_insteadof__anonymous_remote_fetch(void) { cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); cl_git_pass(git_remote_create_anonymous(&g_remote, g_repo, - "http://example.com/libgit2/libgit2")); + "http://example.com/url/fetch/libgit2")); cl_assert_equal_s( git_remote_url(g_remote), - "http://github.com/libgit2/libgit2"); + "http://github.com/url/fetch/libgit2"); cl_assert_equal_p(git_remote_pushurl(g_remote), NULL); } + +void test_remote_insteadof__anonymous_remote_push(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_create_anonymous(&g_remote, g_repo, + "http://example.com/url/push/libgit2")); + + cl_assert_equal_s( + git_remote_url(g_remote), + "http://example.com/url/push/libgit2"); + cl_assert_equal_s( + git_remote_pushurl(g_remote), + "git@github.com:url/push/libgit2"); +} + +void test_remote_insteadof__anonymous_remote_both(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_create_anonymous(&g_remote, g_repo, + "http://example.com/url/both/libgit2")); + + cl_assert_equal_s( + git_remote_url(g_remote), + "http://github.com/url/both/libgit2"); + cl_assert_equal_s( + git_remote_pushurl(g_remote), + "git@github.com:url/both/libgit2"); +} diff --git a/tests/resources/testrepo2/.gitted/config b/tests/resources/testrepo2/.gitted/config index 4af067f04..6966b8a5d 100644 --- a/tests/resources/testrepo2/.gitted/config +++ b/tests/resources/testrepo2/.gitted/config @@ -8,19 +8,42 @@ [remote "origin"] url = https://github.com/libgit2/false.git fetch = +refs/heads/*:refs/remotes/origin/* -[remote "insteadof-test"] - url = http://example.com/libgit2/libgit2 - pushurl = http://github.com/libgit2/libgit2 +[remote "insteadof-url-fetch"] + url = http://example.com/url/fetch/libgit2 + fetch = +refs/heads/*:refs/remotes/test/* +[remote "insteadof-url-push"] + url = http://example.com/url/push/libgit2 + fetch = +refs/heads/*:refs/remotes/test/* +[remote "insteadof-url-both"] + url = http://example.com/url/both/libgit2 + fetch = +refs/heads/*:refs/remotes/test/* +[remote "insteadof-pushurl-fetch"] + url = http://example.com/url/fetch/libgit2 + pushurl = http://example.com/url/fetch/libgit2-push + fetch = +refs/heads/*:refs/remotes/test/* +[remote "insteadof-pushurl-push"] + url = http://example.com/url/push/libgit2 + pushurl = http://example.com/url/push/libgit2-push + fetch = +refs/heads/*:refs/remotes/test/* +[remote "insteadof-pushurl-both"] + url = http://example.com/url/both/libgit2 + pushurl = http://example.com/url/both/libgit2-push fetch = +refs/heads/*:refs/remotes/test/* [branch "master"] remote = origin merge = refs/heads/master rebase = true [url "longer-non-prefix-match"] - insteadOf = ttp://example.com/li + # not applicable because it's not a prefix match + insteadOf = ttp://example.com/url/fetch/li [url "shorter-prefix"] - insteadOf = http://example.co -[url "http://github.com"] - insteadOf = http://example.com -[url "git@github.com:"] - pushInsteadOf = http://github.com/ + # not applicable because the matched prefix is shorter + insteadOf = http://example.com/url/fe +[url "http://github.com/url/fetch"] + insteadOf = http://example.com/url/fetch +[url "http://github.com/url/both"] + insteadOf = http://example.com/url/both +[url "git@github.com:url/push"] + pushInsteadOf = http://example.com/url/push +[url "git@github.com:url/both"] + pushInsteadOf = http://example.com/url/both |