mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-23 23:01:20 +00:00
Merge pull request #1803 from libgit2/ntk/topic/even_more_lenient_remote_parsing
Even more lenient remote parsing
This commit is contained in:
commit
1ef05e3f0e
46
src/remote.c
46
src/remote.c
@ -233,7 +233,8 @@ static int refspec_cb(const git_config_entry *entry, void *payload)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int get_optional_config(
|
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;
|
int error = 0;
|
||||||
const char *key = git_buf_cstr(buf);
|
const char *key = git_buf_cstr(buf);
|
||||||
@ -246,6 +247,9 @@ static int get_optional_config(
|
|||||||
else
|
else
|
||||||
error = git_config_get_string(payload, config, key);
|
error = git_config_get_string(payload, config, key);
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
*found = !error;
|
||||||
|
|
||||||
if (error == GIT_ENOTFOUND) {
|
if (error == GIT_ENOTFOUND) {
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
error = 0;
|
error = 0;
|
||||||
@ -265,6 +269,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
git_config *config;
|
git_config *config;
|
||||||
struct refspec_cb_data data;
|
struct refspec_cb_data data;
|
||||||
|
bool optional_setting_found = false, found;
|
||||||
|
|
||||||
assert(out && repo && name);
|
assert(out && repo && name);
|
||||||
|
|
||||||
@ -294,21 +299,33 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
|
|||||||
goto cleanup;
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
|
optional_setting_found |= found;
|
||||||
|
|
||||||
remote->repo = repo;
|
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;
|
val = NULL;
|
||||||
git_buf_clear(&buf);
|
git_buf_clear(&buf);
|
||||||
git_buf_printf(&buf, "remote.%s.pushurl", name);
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
if (val) {
|
optional_setting_found |= found;
|
||||||
|
|
||||||
|
if (!optional_setting_found) {
|
||||||
|
error = GIT_ENOTFOUND;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found && strlen(val) > 0) {
|
||||||
remote->pushurl = git__strdup(val);
|
remote->pushurl = git__strdup(val);
|
||||||
GITERR_CHECK_ALLOC(remote->pushurl);
|
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_clear(&buf);
|
||||||
git_buf_printf(&buf, "remote.%s.fetch", name);
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
data.fetch = false;
|
data.fetch = false;
|
||||||
git_buf_clear(&buf);
|
git_buf_clear(&buf);
|
||||||
git_buf_printf(&buf, "remote.%s.push", name);
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
if (download_tags_value(remote, config) < 0)
|
if (download_tags_value(remote, config) < 0)
|
||||||
@ -534,6 +551,8 @@ const char* git_remote__urlfordirection(git_remote *remote, int direction)
|
|||||||
{
|
{
|
||||||
assert(remote);
|
assert(remote);
|
||||||
|
|
||||||
|
assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
|
||||||
|
|
||||||
if (direction == GIT_DIRECTION_FETCH) {
|
if (direction == GIT_DIRECTION_FETCH) {
|
||||||
return remote->url;
|
return remote->url;
|
||||||
}
|
}
|
||||||
@ -556,8 +575,11 @@ int git_remote_connect(git_remote *remote, git_direction direction)
|
|||||||
t = remote->transport;
|
t = remote->transport;
|
||||||
|
|
||||||
url = git_remote__urlfordirection(remote, direction);
|
url = git_remote__urlfordirection(remote, direction);
|
||||||
if (url == NULL )
|
if (url == NULL ) {
|
||||||
|
giterr_set(GITERR_INVALID,
|
||||||
|
"Malformed remote '%s' - missing URL", remote->name);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* A transport could have been supplied in advance with
|
/* A transport could have been supplied in advance with
|
||||||
* git_remote_set_transport */
|
* git_remote_set_transport */
|
||||||
@ -1087,10 +1109,10 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
|
|||||||
if (git_repository_config__weakptr(&cfg, repo) < 0)
|
if (git_repository_config__weakptr(&cfg, repo) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (git_vector_init(&list, 4, NULL) < 0)
|
if (git_vector_init(&list, 4, git__strcmp_cb) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (regcomp(&preg, "^remote\\.(.*)\\.url$", REG_EXTENDED) < 0) {
|
if (regcomp(&preg, "^remote\\.(.*)\\.(push)?url$", REG_EXTENDED) < 0) {
|
||||||
giterr_set(GITERR_OS, "Remote catch regex failed to compile");
|
giterr_set(GITERR_OS, "Remote catch regex failed to compile");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1115,6 +1137,8 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git_vector_uniq(&list, git__free);
|
||||||
|
|
||||||
remotes_list->strings = (char **)list.contents;
|
remotes_list->strings = (char **)list.contents;
|
||||||
remotes_list->count = list.length;
|
remotes_list->count = list.length;
|
||||||
|
|
||||||
|
@ -82,7 +82,10 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
|
|||||||
return new_ptr;
|
return new_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define git__free(ptr) free(ptr)
|
GIT_INLINE(void) git__free(void *ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
#define STRCMP_CASESELECT(IGNORE_CASE, STR1, STR2) \
|
#define STRCMP_CASESELECT(IGNORE_CASE, STR1, STR2) \
|
||||||
((IGNORE_CASE) ? strcasecmp((STR1), (STR2)) : strcmp((STR1), (STR2)))
|
((IGNORE_CASE) ? strcasecmp((STR1), (STR2)) : strcmp((STR1), (STR2)))
|
||||||
|
@ -220,7 +220,7 @@ void git_vector_pop(git_vector *v)
|
|||||||
v->length--;
|
v->length--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_vector_uniq(git_vector *v)
|
void git_vector_uniq(git_vector *v, void (*git_free_cb)(void *))
|
||||||
{
|
{
|
||||||
git_vector_cmp cmp;
|
git_vector_cmp cmp;
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
@ -232,9 +232,12 @@ void git_vector_uniq(git_vector *v)
|
|||||||
cmp = v->_cmp ? v->_cmp : strict_comparison;
|
cmp = v->_cmp ? v->_cmp : strict_comparison;
|
||||||
|
|
||||||
for (i = 0, j = 1 ; j < v->length; ++j)
|
for (i = 0, j = 1 ; j < v->length; ++j)
|
||||||
if (!cmp(v->contents[i], v->contents[j]))
|
if (!cmp(v->contents[i], v->contents[j])) {
|
||||||
|
if (git_free_cb)
|
||||||
|
git_free_cb(v->contents[i]);
|
||||||
|
|
||||||
v->contents[i] = v->contents[j];
|
v->contents[i] = v->contents[j];
|
||||||
else
|
} else
|
||||||
v->contents[++i] = v->contents[j];
|
v->contents[++i] = v->contents[j];
|
||||||
|
|
||||||
v->length -= j - i - 1;
|
v->length -= j - i - 1;
|
||||||
|
@ -71,7 +71,7 @@ int git_vector_insert_sorted(git_vector *v, void *element,
|
|||||||
int (*on_dup)(void **old, void *new));
|
int (*on_dup)(void **old, void *new));
|
||||||
int git_vector_remove(git_vector *v, size_t idx);
|
int git_vector_remove(git_vector *v, size_t idx);
|
||||||
void git_vector_pop(git_vector *v);
|
void git_vector_pop(git_vector *v);
|
||||||
void git_vector_uniq(git_vector *v);
|
void git_vector_uniq(git_vector *v, void (*git_free_cb)(void *));
|
||||||
void git_vector_remove_matching(
|
void git_vector_remove_matching(
|
||||||
git_vector *v, int (*match)(const git_vector *v, size_t idx));
|
git_vector *v, int (*match)(const git_vector *v, size_t idx));
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ void test_core_vector__2(void)
|
|||||||
cl_git_pass(git_vector_insert(&x, ptrs[1]));
|
cl_git_pass(git_vector_insert(&x, ptrs[1]));
|
||||||
cl_assert(x.length == 5);
|
cl_assert(x.length == 5);
|
||||||
|
|
||||||
git_vector_uniq(&x);
|
git_vector_uniq(&x, NULL);
|
||||||
cl_assert(x.length == 2);
|
cl_assert(x.length == 2);
|
||||||
|
|
||||||
git_vector_free(&x);
|
git_vector_free(&x);
|
||||||
|
@ -243,13 +243,19 @@ void test_network_remote_remotes__list(void)
|
|||||||
git_config *cfg;
|
git_config *cfg;
|
||||||
|
|
||||||
cl_git_pass(git_remote_list(&list, _repo));
|
cl_git_pass(git_remote_list(&list, _repo));
|
||||||
cl_assert(list.count == 4);
|
cl_assert(list.count == 5);
|
||||||
git_strarray_free(&list);
|
git_strarray_free(&list);
|
||||||
|
|
||||||
cl_git_pass(git_repository_config(&cfg, _repo));
|
cl_git_pass(git_repository_config(&cfg, _repo));
|
||||||
|
|
||||||
|
/* Create a new remote */
|
||||||
cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com"));
|
cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com"));
|
||||||
|
|
||||||
|
/* Update a remote (previously without any url/pushurl entry) */
|
||||||
|
cl_git_pass(git_config_set_string(cfg, "remote.no-remote-url.pushurl", "http://example.com"));
|
||||||
|
|
||||||
cl_git_pass(git_remote_list(&list, _repo));
|
cl_git_pass(git_remote_list(&list, _repo));
|
||||||
cl_assert(list.count == 5);
|
cl_assert(list.count == 7);
|
||||||
git_strarray_free(&list);
|
git_strarray_free(&list);
|
||||||
|
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
@ -367,11 +373,39 @@ void test_network_remote_remotes__can_load_with_an_empty_url(void)
|
|||||||
|
|
||||||
cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-url"));
|
cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-url"));
|
||||||
|
|
||||||
|
cl_assert(remote->url == NULL);
|
||||||
|
cl_assert(remote->pushurl == NULL);
|
||||||
|
|
||||||
|
cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH));
|
||||||
|
|
||||||
|
cl_assert(giterr_last() != NULL);
|
||||||
|
cl_assert(giterr_last()->klass == GITERR_INVALID);
|
||||||
|
|
||||||
|
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));
|
cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH));
|
||||||
|
|
||||||
git_remote_free(remote);
|
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)
|
void test_network_remote_remotes__check_structure_version(void)
|
||||||
{
|
{
|
||||||
git_transport transport = GIT_TRANSPORT_INIT;
|
git_transport transport = GIT_TRANSPORT_INIT;
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
url = git://github.com/libgit2/libgit2
|
url = git://github.com/libgit2/libgit2
|
||||||
[remote "empty-remote-url"]
|
[remote "empty-remote-url"]
|
||||||
url =
|
url =
|
||||||
|
pushurl =
|
||||||
|
[remote "empty-remote-pushurl"]
|
||||||
|
pushurl =
|
||||||
|
[remote "no-remote-url"]
|
||||||
|
fetch =
|
||||||
[remote "test_with_pushurl"]
|
[remote "test_with_pushurl"]
|
||||||
url = git://github.com/libgit2/fetchlibgit2
|
url = git://github.com/libgit2/fetchlibgit2
|
||||||
pushurl = git://github.com/libgit2/pushlibgit2
|
pushurl = git://github.com/libgit2/pushlibgit2
|
||||||
|
Loading…
Reference in New Issue
Block a user