summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-12-23 14:12:23 -0500
committerGitHub <noreply@github.com>2021-12-23 14:12:23 -0500
commitdca31d2427ef2321fab61bd5e3f3470306ba445d (patch)
tree7be580b3efdc2687fd4376fda2a6af724ecfde45
parentab5b3f37f5e74805250685a08fa9f4220e5dba12 (diff)
parentde665a430a36aace250845c75094b07cf9c1735c (diff)
downloadlibgit2-dca31d2427ef2321fab61bd5e3f3470306ba445d.tar.gz
Merge pull request #6101 from mkhl/fix/instead-of
remotes: fix insteadOf/pushInsteadOf handling
-rw-r--r--src/remote.c30
-rw-r--r--tests/remote/insteadof.c110
-rw-r--r--tests/resources/testrepo2/.gitted/config41
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