diff options
author | Vicent Martà <tanoku@gmail.com> | 2012-02-26 10:45:23 -0800 |
---|---|---|
committer | Vicent Martà <tanoku@gmail.com> | 2012-02-26 10:45:23 -0800 |
commit | e07c2d225deec42e592133df49ad8c564d4d66c7 (patch) | |
tree | 5c65164a5974f11de34b1f6eeb050ef1b3ac2bc3 | |
parent | 6b63589e3512cb8ad895dcac8482850c2f256f29 (diff) | |
parent | 8171998f8d90574ecf36016192b6426ed74751f6 (diff) | |
download | libgit2-e07c2d225deec42e592133df49ad8c564d4d66c7.tar.gz |
Merge pull request #574 from carlosmn/remotes
Add git_remote_list()
-rw-r--r-- | include/git2/remote.h | 11 | ||||
-rw-r--r-- | src/remote.c | 69 | ||||
-rw-r--r-- | tests-clar/network/remotes.c | 18 |
3 files changed, 98 insertions, 0 deletions
diff --git a/include/git2/remote.h b/include/git2/remote.h index 9339434e5..e6537ec52 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -197,6 +197,17 @@ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); */ GIT_EXTERN(int) git_remote_valid_url(const char *url); +/** + * Get a list of the configured remotes for a repo + * + * The string array must be freed by the user. + * + * @param remotes_list a string array with the names of the remotes + * @param repo the repository to query + * @return GIT_SUCCESS or an error code + */ +GIT_EXTERN(int) git_remote_list(git_strarray *remotes_list, git_repository *repo); + /** @} */ GIT_END_DECL #endif diff --git a/src/remote.c b/src/remote.c index 3e0dbf051..5b442e934 100644 --- a/src/remote.c +++ b/src/remote.c @@ -15,6 +15,8 @@ #include "fetch.h" #include "refs.h" +#include <regex.h> + static int refspec_parse(git_refspec *refspec, const char *str) { char *delim; @@ -423,3 +425,70 @@ void git_remote_free(git_remote *remote) git_remote_disconnect(remote); git__free(remote); } + +struct cb_data { + git_vector *list; + regex_t *preg; +}; + +static int remote_list_cb(const char *name, const char *GIT_UNUSED(value), void *data_) +{ + struct cb_data *data = (struct cb_data *)data_; + size_t nmatch = 2; + regmatch_t pmatch[2]; + int error; + GIT_UNUSED_ARG(value); + + if (!regexec(data->preg, name, nmatch, pmatch, 0)) { + char *remote_name = git__strndup(&name[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); + if (remote_name == NULL) + return GIT_ENOMEM; + + error = git_vector_insert(data->list, remote_name); + if (error < GIT_SUCCESS) + return error; + } + + return GIT_SUCCESS; +} + +int git_remote_list(git_strarray *remotes_list, git_repository *repo) +{ + git_config *cfg; + git_vector list; + regex_t preg; + struct cb_data data; + int error; + + error = git_repository_config__weakptr(&cfg, repo); + if (error < GIT_SUCCESS) + return error; + + error = git_vector_init(&list, 4, NULL); + if (error < GIT_SUCCESS) + return error; + + error = regcomp(&preg, "^remote\\.(.*)\\.url$", REG_EXTENDED); + if (error < 0) + return GIT_EOSERR; + + data.list = &list; + data.preg = &preg; + error = git_config_foreach(cfg, remote_list_cb, &data); + regfree(&preg); + if (error < GIT_SUCCESS) { + size_t i; + char *elem; + git_vector_foreach(&list, i, elem) { + free(elem); + } + + git_vector_free(&list); + return error; + } + + remotes_list->strings = (char **)list.contents; + remotes_list->count = list.length; + + return GIT_SUCCESS; +} diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c index cc453e36a..36b945f9a 100644 --- a/tests-clar/network/remotes.c +++ b/tests-clar/network/remotes.c @@ -114,3 +114,21 @@ void test_network_remotes__missing_refspecs(void) git_config_free(cfg); } + +void test_network_remotes__list(void) +{ + git_strarray list; + git_config *cfg; + + cl_git_pass(git_remote_list(&list, _repo)); + cl_assert(list.count == 1); + git_strarray_free(&list); + + cl_git_pass(git_repository_config(&cfg, _repo)); + cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com")); + cl_git_pass(git_remote_list(&list, _repo)); + cl_assert(list.count == 2); + git_strarray_free(&list); + + git_config_free(cfg); +} |