remote: Relax the parsing logic even more In order to be loaded, a remote needs to be configured with at least a `url` or a `pushurl`. ENOTFOUND will be returned when trying to git_remote_load() a remote with neither of these entries defined.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
diff --git a/src/remote.c b/src/remote.c
index 4bba1d5..7276daa 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -233,7 +233,8 @@ static int refspec_cb(const git_config_entry *entry, void *payload)
}
static int get_optional_config(
- git_config *config, git_buf *buf, git_config_foreach_cb cb, void *payload)
+ bool *found, git_config *config, git_buf *buf,
+ git_config_foreach_cb cb, void *payload)
{
int error = 0;
const char *key = git_buf_cstr(buf);
@@ -246,6 +247,9 @@ static int get_optional_config(
else
error = git_config_get_string(payload, config, key);
+ if (found)
+ *found = !error;
+
if (error == GIT_ENOTFOUND) {
giterr_clear();
error = 0;
@@ -265,6 +269,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
int error = 0;
git_config *config;
struct refspec_cb_data data;
+ bool optional_setting_found = false, found;
assert(out && repo && name);
@@ -294,21 +299,33 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
goto cleanup;
}
- if ((error = git_config_get_string(&val, config, git_buf_cstr(&buf))) < 0)
+ if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
goto cleanup;
+ optional_setting_found |= found;
+
remote->repo = repo;
- remote->url = git__strdup(val);
- GITERR_CHECK_ALLOC(remote->url);
+
+ if (found && strlen(val) > 0) {
+ remote->url = git__strdup(val);
+ GITERR_CHECK_ALLOC(remote->url);
+ }
val = NULL;
git_buf_clear(&buf);
git_buf_printf(&buf, "remote.%s.pushurl", name);
- if ((error = get_optional_config(config, &buf, NULL, (void *)&val)) < 0)
+ if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
goto cleanup;
- if (val && strlen(val) > 0) {
+ optional_setting_found |= found;
+
+ if (!optional_setting_found) {
+ error = GIT_ENOTFOUND;
+ goto cleanup;
+ }
+
+ if (found && strlen(val) > 0) {
remote->pushurl = git__strdup(val);
GITERR_CHECK_ALLOC(remote->pushurl);
}
@@ -318,14 +335,14 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
git_buf_clear(&buf);
git_buf_printf(&buf, "remote.%s.fetch", name);
- if ((error = get_optional_config(config, &buf, refspec_cb, &data)) < 0)
+ if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
goto cleanup;
data.fetch = false;
git_buf_clear(&buf);
git_buf_printf(&buf, "remote.%s.push", name);
- if ((error = get_optional_config(config, &buf, refspec_cb, &data)) < 0)
+ if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
goto cleanup;
if (download_tags_value(remote, config) < 0)
diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c
index e356526..55b233e 100644
--- a/tests-clar/network/remote/remotes.c
+++ b/tests-clar/network/remote/remotes.c
@@ -378,6 +378,28 @@ void test_network_remote_remotes__can_load_with_an_empty_url(void)
git_remote_free(remote);
}
+void test_network_remote_remotes__can_load_with_only_an_empty_pushurl(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-pushurl"));
+
+ cl_assert(remote->url == NULL);
+ cl_assert(remote->pushurl == NULL);
+
+ cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH));
+
+ git_remote_free(remote);
+}
+
+void test_network_remote_remotes__returns_ENOTFOUND_when_neither_url_nor_pushurl(void)
+{
+ git_remote *remote = NULL;
+
+ cl_git_fail_with(
+ git_remote_load(&remote, _repo, "no-remote-url"), GIT_ENOTFOUND);
+}
+
void test_network_remote_remotes__check_structure_version(void)
{
git_transport transport = GIT_TRANSPORT_INIT;
diff --git a/tests-clar/resources/testrepo.git/config b/tests-clar/resources/testrepo.git/config
index 1264f6e..dfab4ee 100644
--- a/tests-clar/resources/testrepo.git/config
+++ b/tests-clar/resources/testrepo.git/config
@@ -11,6 +11,10 @@
[remote "empty-remote-url"]
url =
pushurl =
+[remote "empty-remote-pushurl"]
+ pushurl =
+[remote "no-remote-url"]
+ fetch =
[remote "test_with_pushurl"]
url = git://github.com/libgit2/fetchlibgit2
pushurl = git://github.com/libgit2/pushlibgit2