summaryrefslogtreecommitdiff
path: root/tests/libgit2/remote
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-11-16 23:29:22 -0500
committerEdward Thomson <ethomson@edwardthomson.com>2022-02-22 22:07:45 -0500
commit3344fddc97bbdea9c1b6ebb6f7fb6dbd70b41dfb (patch)
treefd6368a72944571c51627b40c592e7d58e0036e1 /tests/libgit2/remote
parent91ba089663f5efc3bd4ba14a5099372cf5ce57a6 (diff)
downloadlibgit2-3344fddc97bbdea9c1b6ebb6f7fb6dbd70b41dfb.tar.gz
refactor: `tests` is now `tests/libgit2`
Like we want to separate libgit2 and utility source code, we want to separate libgit2 and utility tests. Start by moving all the tests into libgit2.
Diffstat (limited to 'tests/libgit2/remote')
-rw-r--r--tests/libgit2/remote/create.c388
-rw-r--r--tests/libgit2/remote/fetch.c169
-rw-r--r--tests/libgit2/remote/httpproxy.c188
-rw-r--r--tests/libgit2/remote/insteadof.c154
-rw-r--r--tests/libgit2/remote/list.c43
5 files changed, 942 insertions, 0 deletions
diff --git a/tests/libgit2/remote/create.c b/tests/libgit2/remote/create.c
new file mode 100644
index 000000000..f92be9dfc
--- /dev/null
+++ b/tests/libgit2/remote/create.c
@@ -0,0 +1,388 @@
+#include "clar_libgit2.h"
+#include "config/config_helpers.h"
+
+static git_repository *_repo;
+static git_config *_config;
+
+#define TEST_URL "http://github.com/libgit2/libgit2.git"
+
+void test_remote_create__initialize(void)
+{
+ cl_fixture_sandbox("testrepo.git");
+
+ cl_git_pass(git_repository_open(&_repo, "testrepo.git"));
+
+ cl_git_pass(git_repository_config(&_config, _repo));
+}
+
+void test_remote_create__cleanup(void)
+{
+ git_config_free(_config);
+
+ git_repository_free(_repo);
+
+ cl_fixture_cleanup("testrepo.git");
+}
+
+void test_remote_create__manual(void)
+{
+ git_remote *remote;
+ cl_git_pass(git_config_set_string(_config, "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"));
+ cl_git_pass(git_config_set_string(_config, "remote.origin.url", TEST_URL));
+
+ cl_git_pass(git_remote_lookup(&remote, _repo, "origin"));
+ cl_assert_equal_s(git_remote_name(remote), "origin");
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+
+ git_remote_free(remote);
+}
+
+void test_remote_create__named(void)
+{
+ git_remote *remote;
+ git_config *cfg;
+ const char *cfg_val;
+
+ size_t section_count = count_config_entries_match(_repo, "remote\\.");
+
+ cl_git_pass(git_remote_create(&remote, _repo, "valid-name", TEST_URL));
+
+ cl_assert_equal_s(git_remote_name(remote), "valid-name");
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), _repo);
+
+ cl_git_pass(git_repository_config_snapshot(&cfg, _repo));
+
+ cl_git_pass(git_config_get_string(&cfg_val, cfg, "remote.valid-name.fetch"));
+ cl_assert_equal_s(cfg_val, "+refs/heads/*:refs/remotes/valid-name/*");
+
+ cl_git_pass(git_config_get_string(&cfg_val, cfg, "remote.valid-name.url"));
+ cl_assert_equal_s(cfg_val, TEST_URL);
+
+ cl_assert_equal_i(section_count + 2, count_config_entries_match(_repo, "remote\\."));
+
+ git_config_free(cfg);
+ git_remote_free(remote);
+}
+
+void test_remote_create__named_fail_on_invalid_name(void)
+{
+ const char *names[] = {
+ NULL,
+ "Inv@{id",
+ "",
+ "/",
+ "//",
+ ".lock",
+ "a.lock",
+ };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(names); i++) {
+ git_remote *remote = NULL;
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_remote_create(&remote, _repo, names[i], TEST_URL));
+ cl_assert_equal_p(remote, NULL);
+ }
+}
+
+void test_remote_create__named_fail_on_invalid_url(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_ERROR, git_remote_create(&remote, _repo, "bad-url", ""));
+ cl_assert_equal_p(remote, NULL);
+}
+
+void test_remote_create__named_fail_on_conflicting_name(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_EEXISTS, git_remote_create(&remote, _repo, "test", TEST_URL));
+ cl_assert_equal_p(remote, NULL);
+}
+
+void test_remote_create__with_fetchspec(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ size_t section_count = count_config_entries_match(_repo, "remote\\.");
+
+ cl_git_pass(git_remote_create_with_fetchspec(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", "+refs/*:refs/*"));
+ cl_assert_equal_s(git_remote_name(remote), "test-new");
+ cl_assert_equal_s(git_remote_url(remote), "git://github.com/libgit2/libgit2");
+ cl_assert_equal_p(git_remote_owner(remote), _repo);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_s("+refs/*:refs/*", array.strings[0]);
+ cl_assert_equal_i(1, array.count);
+ cl_assert_equal_i(section_count + 2, count_config_entries_match(_repo, "remote\\."));
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__with_empty_fetchspec(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ size_t section_count = count_config_entries_match(_repo, "remote\\.");
+
+ cl_git_pass(git_remote_create_with_fetchspec(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", NULL));
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(0, array.count);
+ cl_assert_equal_i(section_count + 1, count_config_entries_match(_repo, "remote\\."));
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__with_fetchspec_invalid_name(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_remote_create_with_fetchspec(&remote, _repo, NULL, TEST_URL, NULL));
+ cl_assert_equal_p(remote, NULL);
+}
+
+void test_remote_create__with_fetchspec_invalid_url(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_remote_create_with_fetchspec(&remote, _repo, NULL, "", NULL));
+ cl_assert_equal_p(remote, NULL);
+}
+
+void test_remote_create__anonymous(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ size_t section_count = count_config_entries_match(_repo, "remote\\.");
+
+ cl_git_pass(git_remote_create_anonymous(&remote, _repo, TEST_URL));
+ cl_assert_equal_s(git_remote_name(remote), NULL);
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), _repo);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(0, array.count);
+ cl_assert_equal_i(section_count, count_config_entries_match(_repo, "remote\\."));
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__anonymous_invalid_url(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_remote_create_anonymous(&remote, _repo, ""));
+ cl_assert_equal_p(remote, NULL);
+}
+
+void test_remote_create__detached(void)
+{
+ git_remote *remote;
+ git_strarray array;
+
+ size_t section_count = count_config_entries_match(_repo, "remote\\.");
+
+ cl_git_pass(git_remote_create_detached(&remote, TEST_URL));
+ cl_assert_equal_s(git_remote_name(remote), NULL);
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), NULL);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(0, array.count);
+ cl_assert_equal_i(section_count, count_config_entries_match(_repo, "remote\\."));
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__detached_invalid_url(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_remote_create_detached(&remote, ""));
+ cl_assert_equal_p(remote, NULL);
+}
+
+void test_remote_create__with_opts_named(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
+
+ opts.name = "test-new";
+ opts.repository = _repo;
+
+ cl_git_pass(git_remote_create_with_opts(&remote, TEST_URL, &opts));
+ cl_assert_equal_s(git_remote_name(remote), "test-new");
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), _repo);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(1, array.count);
+ cl_assert_equal_s("+refs/heads/*:refs/remotes/test-new/*", array.strings[0]);
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__with_opts_named_and_fetchspec(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
+
+ opts.name = "test-new";
+ opts.repository = _repo;
+ opts.fetchspec = "+refs/*:refs/*";
+
+ cl_git_pass(git_remote_create_with_opts(&remote, TEST_URL, &opts));
+ cl_assert_equal_s(git_remote_name(remote), "test-new");
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), _repo);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(1, array.count);
+ cl_assert_equal_s("+refs/*:refs/*", array.strings[0]);
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__with_opts_named_no_fetchspec(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
+
+ opts.name = "test-new";
+ opts.repository = _repo;
+ opts.flags = GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC;
+
+ cl_git_pass(git_remote_create_with_opts(&remote, TEST_URL, &opts));
+ cl_assert_equal_s(git_remote_name(remote), "test-new");
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), _repo);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(0, array.count);
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__with_opts_anonymous(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
+
+ opts.repository = _repo;
+
+ cl_git_pass(git_remote_create_with_opts(&remote, TEST_URL, &opts));
+ cl_assert_equal_s(git_remote_name(remote), NULL);
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), _repo);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(0, array.count);
+
+ git_strarray_dispose(&array);
+ git_remote_free(remote);
+}
+
+void test_remote_create__with_opts_detached(void)
+{
+ git_remote *remote;
+ git_strarray array;
+ git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
+
+ cl_git_pass(git_remote_create_with_opts(&remote, TEST_URL, &opts));
+ cl_assert_equal_s(git_remote_name(remote), NULL);
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), NULL);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(0, array.count);
+
+ git_strarray_dispose(&array);
+
+ git_remote_free(remote);
+
+ cl_git_pass(git_remote_create_with_opts(&remote, TEST_URL, NULL));
+ cl_assert_equal_s(git_remote_name(remote), NULL);
+ cl_assert_equal_s(git_remote_url(remote), TEST_URL);
+ cl_assert_equal_p(git_remote_owner(remote), NULL);
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote));
+ cl_assert_equal_i(0, array.count);
+
+ git_strarray_dispose(&array);
+
+ git_remote_free(remote);
+}
+
+
+void test_remote_create__with_opts_insteadof_disabled(void)
+{
+ git_remote *remote;
+ git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
+
+ opts.repository = _repo;
+ opts.flags = GIT_REMOTE_CREATE_SKIP_INSTEADOF;
+
+ cl_git_pass(git_remote_create_with_opts(&remote, "http://example.com/libgit2/libgit2", &opts));
+
+ cl_assert_equal_s(git_remote_url(remote), "http://example.com/libgit2/libgit2");
+ cl_assert_equal_p(git_remote_pushurl(remote), NULL);
+
+ git_remote_free(remote);
+}
+
+static int create_with_name(git_remote **remote, git_repository *repo, const char *name, const char *url)
+{
+ git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
+
+ opts.repository = repo;
+ opts.name = name;
+
+ return git_remote_create_with_opts(remote, url, &opts);
+}
+
+void test_remote_create__with_opts_invalid_name(void)
+{
+ const char *names[] = {
+ "Inv@{id",
+ "",
+ "/",
+ "//",
+ ".lock",
+ "a.lock",
+ };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(names); i++) {
+ git_remote *remote = NULL;
+ cl_git_fail_with(GIT_EINVALIDSPEC, create_with_name(&remote, _repo, names[i], TEST_URL));
+ cl_assert_equal_p(remote, NULL);
+ }
+}
+
+void test_remote_create__with_opts_conflicting_name(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_EEXISTS, create_with_name(&remote, _repo, "test", TEST_URL));
+ cl_assert_equal_p(remote, NULL);
+}
+
+void test_remote_create__with_opts_invalid_url(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(GIT_EINVALIDSPEC, create_with_name(&remote, _repo, "test-new", ""));
+ cl_assert_equal_p(remote, NULL);
+}
diff --git a/tests/libgit2/remote/fetch.c b/tests/libgit2/remote/fetch.c
new file mode 100644
index 000000000..370046267
--- /dev/null
+++ b/tests/libgit2/remote/fetch.c
@@ -0,0 +1,169 @@
+#include "../clar_libgit2.h"
+
+#include "remote.h"
+#include "repository.h"
+
+static git_repository *repo1;
+static git_repository *repo2;
+static char* repo1_path;
+static char* repo2_path;
+
+static const char *REPO1_REFNAME = "refs/heads/main";
+static const char *REPO2_REFNAME = "refs/remotes/repo1/main";
+static char *FORCE_FETCHSPEC = "+refs/heads/main:refs/remotes/repo1/main";
+static char *NON_FORCE_FETCHSPEC = "refs/heads/main:refs/remotes/repo1/main";
+
+void test_remote_fetch__initialize(void) {
+ git_config *c;
+ git_str repo1_path_buf = GIT_STR_INIT;
+ git_str repo2_path_buf = GIT_STR_INIT;
+ const char *sandbox = clar_sandbox_path();
+
+ cl_git_pass(git_str_joinpath(&repo1_path_buf, sandbox, "fetchtest_repo1"));
+ repo1_path = git_str_detach(&repo1_path_buf);
+ cl_git_pass(git_repository_init(&repo1, repo1_path, true));
+
+ cl_git_pass(git_str_joinpath(&repo2_path_buf, sandbox, "fetchtest_repo2"));
+ repo2_path = git_str_detach(&repo2_path_buf);
+ cl_git_pass(git_repository_init(&repo2, repo2_path, true));
+
+ cl_git_pass(git_repository_config(&c, repo1));
+ cl_git_pass(git_config_set_string(c, "user.email", "some@email"));
+ cl_git_pass(git_config_set_string(c, "user.name", "some@name"));
+ git_config_free(c);
+ git_str_dispose(&repo1_path_buf);
+ git_str_dispose(&repo2_path_buf);
+}
+
+void test_remote_fetch__cleanup(void) {
+ git_repository_free(repo1);
+ git_repository_free(repo2);
+
+ cl_git_pass(git_futils_rmdir_r(repo1_path, NULL, GIT_RMDIR_REMOVE_FILES));
+ free(repo1_path);
+
+ cl_git_pass(git_futils_rmdir_r(repo2_path, NULL, GIT_RMDIR_REMOVE_FILES));
+ free(repo2_path);
+}
+
+
+/**
+ * This checks that the '+' flag on fetchspecs is respected. We create a
+ * repository that has a reference to two commits, one a child of the other.
+ * We fetch this repository into a second repository. Then we reset the
+ * reference in the first repository and run the fetch again. If the '+' flag
+ * is used then the reference in the second repository will change, but if it
+ * is not then it should stay the same.
+ *
+ * @param commit1id A pointer to an OID which will be populated with the first
+ * commit.
+ * @param commit2id A pointer to an OID which will be populated with the second
+ * commit, which is a descendant of the first.
+ * @param force Whether to use a spec with '+' prefixed to force the refs
+ * to update
+ */
+static void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
+ bool force) {
+ char *refspec_strs = {
+ force ? FORCE_FETCHSPEC : NON_FORCE_FETCHSPEC,
+ };
+ git_strarray refspecs = {
+ .count = 1,
+ .strings = &refspec_strs,
+ };
+
+ /* create two commits in repo 1 and a reference to them */
+ {
+ git_oid empty_tree_id;
+ git_tree *empty_tree;
+ git_signature *sig;
+ git_treebuilder *tb;
+ cl_git_pass(git_treebuilder_new(&tb, repo1, NULL));
+ cl_git_pass(git_treebuilder_write(&empty_tree_id, tb));
+ cl_git_pass(git_tree_lookup(&empty_tree, repo1, &empty_tree_id));
+ cl_git_pass(git_signature_default(&sig, repo1));
+ cl_git_pass(git_commit_create(commit1id, repo1, REPO1_REFNAME, sig,
+ sig, NULL, "one", empty_tree, 0, NULL));
+ cl_git_pass(git_commit_create_v(commit2id, repo1, REPO1_REFNAME, sig,
+ sig, NULL, "two", empty_tree, 1, commit1id));
+
+ git_tree_free(empty_tree);
+ git_signature_free(sig);
+ git_treebuilder_free(tb);
+ }
+
+ /* fetch the reference via the remote */
+ {
+ git_remote *remote;
+
+ cl_git_pass(git_remote_create_anonymous(&remote, repo2,
+ git_repository_path(repo1)));
+ cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, "some message"));
+
+ git_remote_free(remote);
+ }
+
+ /* assert that repo2 references the second commit */
+ {
+ const git_oid *target;
+ git_reference *ref;
+ cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
+ target = git_reference_target(ref);
+ cl_assert_equal_b(git_oid_cmp(target, commit2id), 0);
+ git_reference_free(ref);
+ }
+
+ /* set the reference in repo1 to point to the older commit */
+ {
+ git_reference *ref;
+ git_reference *ref2;
+ cl_git_pass(git_reference_lookup(&ref, repo1, REPO1_REFNAME));
+ cl_git_pass(git_reference_set_target(&ref2, ref, commit1id,
+ "rollback"));
+ git_reference_free(ref);
+ git_reference_free(ref2);
+ }
+
+ /* fetch the reference again */
+ {
+ git_remote *remote;
+
+ cl_git_pass(git_remote_create_anonymous(&remote, repo2,
+ git_repository_path(repo1)));
+ cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, "some message"));
+
+ git_remote_free(remote);
+ }
+}
+
+void test_remote_fetch__dont_update_refs_if_not_descendant_and_not_force(void) {
+ const git_oid *target;
+ git_oid commit1id;
+ git_oid commit2id;
+ git_reference *ref;
+
+ do_time_travelling_fetch(&commit1id, &commit2id, false);
+
+ /* assert that the reference in repo2 has not changed */
+ cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
+ target = git_reference_target(ref);
+ cl_assert_equal_b(git_oid_cmp(target, &commit2id), 0);
+
+ git_reference_free(ref);
+}
+
+void test_remote_fetch__do_update_refs_if_not_descendant_and_force(void) {
+ const git_oid *target;
+ git_oid commit1id;
+ git_oid commit2id;
+ git_reference *ref;
+
+ do_time_travelling_fetch(&commit1id, &commit2id, true);
+
+ /* assert that the reference in repo2 has changed */
+ cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
+ target = git_reference_target(ref);
+ cl_assert_equal_b(git_oid_cmp(target, &commit1id), 0);
+
+ git_reference_free(ref);
+}
diff --git a/tests/libgit2/remote/httpproxy.c b/tests/libgit2/remote/httpproxy.c
new file mode 100644
index 000000000..f62a2545b
--- /dev/null
+++ b/tests/libgit2/remote/httpproxy.c
@@ -0,0 +1,188 @@
+#include "clar_libgit2.h"
+#include "futils.h"
+#include "net.h"
+#include "remote.h"
+
+static git_repository *repo;
+static git_net_url url = GIT_NET_URL_INIT;
+
+static int orig_proxies_need_reset = 0;
+static char *orig_http_proxy = NULL;
+static char *orig_https_proxy = NULL;
+static char *orig_no_proxy = NULL;
+
+void test_remote_httpproxy__initialize(void)
+{
+ git_remote *remote;
+
+ repo = cl_git_sandbox_init("testrepo");
+ cl_git_pass(git_remote_create(&remote, repo, "lg2", "https://github.com/libgit2/libgit2"));
+ cl_git_pass(git_net_url_parse(&url, "https://github.com/libgit2/libgit2"));
+
+ git_remote_free(remote);
+
+ orig_proxies_need_reset = 0;
+}
+
+void test_remote_httpproxy__cleanup(void)
+{
+ if (orig_proxies_need_reset) {
+ cl_setenv("HTTP_PROXY", orig_http_proxy);
+ cl_setenv("HTTPS_PROXY", orig_https_proxy);
+ cl_setenv("NO_PROXY", orig_no_proxy);
+
+ git__free(orig_http_proxy);
+ git__free(orig_https_proxy);
+ git__free(orig_no_proxy);
+ }
+
+ git_net_url_dispose(&url);
+ cl_git_sandbox_cleanup();
+}
+
+static void assert_proxy_is(const char *expected)
+{
+ git_remote *remote;
+ char *proxy;
+
+ cl_git_pass(git_remote_lookup(&remote, repo, "lg2"));
+ cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
+
+ if (expected)
+ cl_assert_equal_s(proxy, expected);
+ else
+ cl_assert_equal_p(proxy, expected);
+
+ git_remote_free(remote);
+ git__free(proxy);
+}
+
+static void assert_config_match(const char *config, const char *expected)
+{
+ git_remote *remote;
+ char *proxy;
+
+ if (config)
+ cl_repo_set_string(repo, config, expected);
+
+ cl_git_pass(git_remote_lookup(&remote, repo, "lg2"));
+ cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
+
+ if (expected)
+ cl_assert_equal_s(proxy, expected);
+ else
+ cl_assert_equal_p(proxy, expected);
+
+ git_remote_free(remote);
+ git__free(proxy);
+}
+
+void test_remote_httpproxy__config_overrides(void)
+{
+ /*
+ * http.proxy should be honored, then http.<url>.proxy should
+ * be honored in increasing specificity of the url. finally,
+ * remote.<name>.proxy is the most specific.
+ */
+ assert_config_match(NULL, NULL);
+ assert_config_match("http.proxy", "http://localhost:1/");
+ assert_config_match("http.https://github.com.proxy", "http://localhost:2/");
+ assert_config_match("http.https://github.com/.proxy", "http://localhost:3/");
+ assert_config_match("http.https://github.com/libgit2.proxy", "http://localhost:4/");
+ assert_config_match("http.https://github.com/libgit2/.proxy", "http://localhost:5/");
+ assert_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:6/");
+ assert_config_match("remote.lg2.proxy", "http://localhost:7/");
+}
+
+void test_remote_httpproxy__config_empty_overrides(void)
+{
+ /*
+ * with greater specificity, an empty config entry overrides
+ * a set one
+ */
+ assert_config_match("http.proxy", "http://localhost:1/");
+ assert_config_match("http.https://github.com.proxy", "");
+ assert_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:2/");
+ assert_config_match("remote.lg2.proxy", "");
+}
+
+static void assert_global_config_match(const char *config, const char *expected)
+{
+ git_remote *remote;
+ char *proxy;
+ git_config* cfg;
+
+ if (config) {
+ cl_git_pass(git_config_open_default(&cfg));
+ git_config_set_string(cfg, config, expected);
+ git_config_free(cfg);
+ }
+
+ cl_git_pass(git_remote_create_detached(&remote, "https://github.com/libgit2/libgit2"));
+ cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
+
+ if (expected)
+ cl_assert_equal_s(proxy, expected);
+ else
+ cl_assert_equal_p(proxy, expected);
+
+ git_remote_free(remote);
+ git__free(proxy);
+}
+
+void test_remote_httpproxy__config_overrides_detached_remote(void)
+{
+ cl_fake_home();
+
+ assert_global_config_match(NULL, NULL);
+ assert_global_config_match("http.proxy", "http://localhost:1/");
+ assert_global_config_match("http.https://github.com.proxy", "http://localhost:2/");
+ assert_global_config_match("http.https://github.com/.proxy", "http://localhost:3/");
+ assert_global_config_match("http.https://github.com/libgit2.proxy", "http://localhost:4/");
+ assert_global_config_match("http.https://github.com/libgit2/.proxy", "http://localhost:5/");
+ assert_global_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:6/");
+
+ cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES));
+}
+
+void test_remote_httpproxy__env(void)
+{
+ orig_http_proxy = cl_getenv("HTTP_PROXY");
+ orig_https_proxy = cl_getenv("HTTPS_PROXY");
+ orig_no_proxy = cl_getenv("NO_PROXY");
+ orig_proxies_need_reset = 1;
+
+ /* Clear everything for a fresh start */
+ cl_setenv("HTTP_PROXY", NULL);
+ cl_setenv("HTTPS_PROXY", NULL);
+ cl_setenv("NO_PROXY", NULL);
+
+ /* HTTP proxy is ignored for HTTPS */
+ cl_setenv("HTTP_PROXY", "http://localhost:9/");
+ assert_proxy_is(NULL);
+
+ /* HTTPS proxy is honored for HTTPS */
+ cl_setenv("HTTPS_PROXY", "http://localhost:10/");
+ assert_proxy_is("http://localhost:10/");
+
+ /* NO_PROXY is honored */
+ cl_setenv("NO_PROXY", "github.com:443");
+ assert_proxy_is(NULL);
+
+ cl_setenv("NO_PROXY", "github.com:80");
+ assert_proxy_is("http://localhost:10/");
+
+ cl_setenv("NO_PROXY", "github.com");
+ assert_proxy_is(NULL);
+
+ cl_setenv("NO_PROXY", "github.dev,github.com,github.foo");
+ assert_proxy_is(NULL);
+
+ cl_setenv("HTTPS_PROXY", "");
+ assert_proxy_is(NULL);
+
+ /* configuration overrides environment variables */
+ cl_setenv("HTTPS_PROXY", "http://localhost:10/");
+ cl_setenv("NO_PROXY", "github.none");
+ assert_config_match("http.https://github.com.proxy", "http://localhost:11/");
+}
diff --git a/tests/libgit2/remote/insteadof.c b/tests/libgit2/remote/insteadof.c
new file mode 100644
index 000000000..c39df4be7
--- /dev/null
+++ b/tests/libgit2/remote/insteadof.c
@@ -0,0 +1,154 @@
+#include "clar_libgit2.h"
+#include "remote.h"
+#include "repository.h"
+
+#define REPO_PATH "testrepo2/.gitted"
+#define REMOTE_ORIGIN "origin"
+#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;
+
+void test_remote_insteadof__initialize(void)
+{
+ g_repo = NULL;
+ g_remote = NULL;
+}
+
+void test_remote_insteadof__cleanup(void)
+{
+ git_repository_free(g_repo);
+ git_remote_free(g_remote);
+}
+
+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));
+
+ 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_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_URL_FETCH));
+
+ cl_assert_equal_s(
+ git_remote_url(g_remote),
+ "http://github.com/url/fetch/libgit2");
+ cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
+}
+
+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_INSTEADOF_URL_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),
+ "git@github.com:url/push/libgit2");
+}
+
+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_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:url/both/libgit2");
+}
+
+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/url/fetch/libgit2"));
+
+ cl_assert_equal_s(
+ git_remote_url(g_remote),
+ "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/libgit2/remote/list.c b/tests/libgit2/remote/list.c
new file mode 100644
index 000000000..4a6be3d1b
--- /dev/null
+++ b/tests/libgit2/remote/list.c
@@ -0,0 +1,43 @@
+#include "clar_libgit2.h"
+#include "config/config_helpers.h"
+
+static git_repository *_repo;
+
+#define TEST_URL "http://github.com/libgit2/libgit2.git"
+
+void test_remote_list__initialize(void)
+{
+ _repo = cl_git_sandbox_init("testrepo");
+}
+
+void test_remote_list__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+void test_remote_list__always_checks_disk_config(void)
+{
+ git_repository *repo;
+ git_strarray remotes;
+ git_remote *remote;
+
+ cl_git_pass(git_repository_open(&repo, git_repository_path(_repo)));
+
+ cl_git_pass(git_remote_list(&remotes, _repo));
+ cl_assert_equal_sz(remotes.count, 1);
+ git_strarray_dispose(&remotes);
+
+ cl_git_pass(git_remote_create(&remote, _repo, "valid-name", TEST_URL));
+
+ cl_git_pass(git_remote_list(&remotes, _repo));
+ cl_assert_equal_sz(remotes.count, 2);
+ git_strarray_dispose(&remotes);
+
+ cl_git_pass(git_remote_list(&remotes, repo));
+ cl_assert_equal_sz(remotes.count, 2);
+ git_strarray_dispose(&remotes);
+
+ git_repository_free(repo);
+ git_remote_free(remote);
+}
+