fix(remote): apply insteadOf from global config for detached remotes

Detached remotes already read global/system config for http proxy
settings, but did not apply url.*.insteadOf or url.*.pushInsteadOf
rules. This inconsistency meant that `git_remote_create_detached`
behaved differently from git's `ls-remote`, which was the primary
use case for detached remotes.

This fixes it by loading the default config when no repository is
provided and apply insteadOf rules consistently.

While this is a behavior change, it still respects
`GIT_REMOTE_CREATE_SKIP_INSTEADOF`, meaning that user can restore
the previous behavior with minimal effort

Fixes https://github.com/libgit2/libgit2/issues/5469
This commit is contained in:
Weihang Lo
2026-01-14 01:21:59 -05:00
parent aa5d9886d1
commit d375ab70c1
2 changed files with 12 additions and 20 deletions

View File

@@ -236,6 +236,9 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
if (opts->repository) {
if ((error = git_repository_config_snapshot(&config_ro, opts->repository)) < 0)
goto on_error;
} else if (!(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
if ((error = git_config_open_default(&config_ro)) < 0)
goto on_error;
}
remote = git__calloc(1, sizeof(git_remote));
@@ -247,7 +250,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
(error = canonicalize_url(&canonical_url, url)) < 0)
goto on_error;
if (opts->repository && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
if (config_ro && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
if ((error = apply_insteadof(&remote->url, config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH, true)) < 0 ||
(error = apply_insteadof(&remote->pushurl, config_ro, canonical_url.ptr, GIT_DIRECTION_PUSH, false)) < 0)
goto on_error;

View File

@@ -167,14 +167,9 @@ void test_remote_insteadof__detached_remote_fetch_insteadof(void)
cl_git_pass(git_remote_create_detached(&g_remote,
"http://example.com/url/fetch/libgit2"));
/*
* TODO: this should be "http://github.com/url/fetch/libgit2" once
* git_remote_create_detached applies insteadOf from global config.
* See: https://github.com/libgit2/libgit2/issues/5469
*/
cl_assert_equal_s(
git_remote_url(g_remote),
"http://example.com/url/fetch/libgit2");
"http://github.com/url/fetch/libgit2");
cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
}
@@ -195,12 +190,9 @@ void test_remote_insteadof__detached_remote_push_insteadof(void)
cl_assert_equal_s(
git_remote_url(g_remote),
"http://example.com/url/push/libgit2");
/*
* TODO: this should be "git@github.com:url/push/libgit2" once
* git_remote_create_detached applies pushInsteadOf from global config.
* See: https://github.com/libgit2/libgit2/issues/5469
*/
cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
cl_assert_equal_s(
git_remote_pushurl(g_remote),
"git@github.com:url/push/libgit2");
}
void test_remote_insteadof__detached_remote_both_insteadof(void)
@@ -219,13 +211,10 @@ void test_remote_insteadof__detached_remote_both_insteadof(void)
cl_git_pass(git_remote_create_detached(&g_remote,
"http://example.com/url/both/libgit2"));
/*
* TODO: these should be the rewritten URLs once
* git_remote_create_detached applies insteadOf from global config.
* See: https://github.com/libgit2/libgit2/issues/5469
*/
cl_assert_equal_s(
git_remote_url(g_remote),
"http://example.com/url/both/libgit2");
cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
"http://github.com/url/both/libgit2");
cl_assert_equal_s(
git_remote_pushurl(g_remote),
"git@github.com:url/both/libgit2");
}