diff options
-rw-r--r-- | include/git2.h | 3 | ||||
-rw-r--r-- | include/git2/branch.h | 9 | ||||
-rw-r--r-- | include/git2/refspec.h | 22 | ||||
-rw-r--r-- | include/git2/remote.h | 58 | ||||
-rw-r--r-- | include/git2/types.h | 3 | ||||
-rw-r--r-- | src/refspec.c | 66 | ||||
-rw-r--r-- | src/refspec.h | 14 | ||||
-rw-r--r-- | src/remote.c | 186 | ||||
-rw-r--r-- | src/remote.h | 14 |
9 files changed, 375 insertions, 0 deletions
diff --git a/include/git2.h b/include/git2.h index ff1c1185a..e04b0bd18 100644 --- a/include/git2.h +++ b/include/git2.h @@ -54,4 +54,7 @@ #include "git2/index.h" #include "git2/config.h" +#include "git2/remote.h" +#include "git2/refspec.h" + #endif diff --git a/include/git2/branch.h b/include/git2/branch.h new file mode 100644 index 000000000..456b7d1ac --- /dev/null +++ b/include/git2/branch.h @@ -0,0 +1,9 @@ +#ifndef INCLUDE_branch_h__ +#define INCLUDE_branch_h__ + +struct git_branch { + char *remote; /* TODO: Make this a git_remote */ + char *merge; +}; + +#endif diff --git a/include/git2/refspec.h b/include/git2/refspec.h new file mode 100644 index 000000000..d45364f71 --- /dev/null +++ b/include/git2/refspec.h @@ -0,0 +1,22 @@ +#ifndef INCLUDE_git_refspec_h__ +#define INCLUDE_git_refspec_h__ + +#include "git2/types.h" + +/** + * Get the source specifier + * + * @param refspec the refspec + * @return the refspec's source specifier + */ +const char *git_refspec_src(const git_refspec *refspec); + +/** + * Get the destination specifier + * + * @param refspec the refspec + * @return the refspec's destination specifier + */ +const char *git_refspec_dst(const git_refspec *refspec); + +#endif diff --git a/include/git2/remote.h b/include/git2/remote.h new file mode 100644 index 000000000..8edb743d8 --- /dev/null +++ b/include/git2/remote.h @@ -0,0 +1,58 @@ +#ifndef INCLUDE_git_remote_h__ +#define INCLUDE_git_remote_h__ + +#include "git2/common.h" +#include "git2/repository.h" +#include "git2/refspec.h" + +/** + * Get the information for a particular remote + * + * @param out pointer to the new remote object + * @param cfg the repository's configuration + * @param name the remote's name + * @return 0 on success; error value otherwise + */ +GIT_EXTERN(int) git_remote_get(struct git_remote **out, struct git_config *cfg, const char *name); + +/** + * Get the remote's name + * + * @param remote the remote + * @return a pointer to the name + */ +GIT_EXTERN(const char *) git_remote_name(struct git_remote *remote); + +/** + * Get the remote's url + * + * @param remote the remote + * @return a pointer to the url + */ +GIT_EXTERN(const char *) git_remote_url(struct git_remote *remote); + +/** + * Get the fetch refspec + * + * @param remote the remote + * @return a pointer to the fetch refspec or NULL if it doesn't exist + */ +GIT_EXTERN(const git_refspec *) git_remote_fetchspec(struct git_remote *remote); + +/** + * Get the push refspec + * + * @param remote the remote + * @return a pointer to the push refspec or NULL if it doesn't exist + */ + +GIT_EXTERN(const git_refspec *) git_remote_fetchspec(struct git_remote *remote); + +/** + * Free the memory associated with a remote + * + * @param remote the remote to free + */ +GIT_EXTERN(void) git_remote_free(struct git_remote *remote); + +#endif diff --git a/include/git2/types.h b/include/git2/types.h index 499ba98ad..963156f85 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -167,6 +167,9 @@ typedef enum { GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC|GIT_REF_PACKED, } git_rtype; +typedef struct git_refspec git_refspec; +typedef struct git_remote git_remote; + /** @} */ GIT_END_DECL diff --git a/src/refspec.c b/src/refspec.c new file mode 100644 index 000000000..7a85259f3 --- /dev/null +++ b/src/refspec.c @@ -0,0 +1,66 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "common.h" +#include "refspec.h" + +int git_refspec_parse(git_refspec *refspec, const char *str) +{ + char *delim; + + memset(refspec, 0x0, sizeof(git_refspec)); + + if (*str == '+') { + refspec->force = 1; + str++; + } + + delim = strchr(str, ':'); + if (delim == NULL) + return git__throw(GIT_EOBJCORRUPTED, "Failed to parse refspec. No ':'"); + + refspec->src = git__strndup(str, delim - str); + if (refspec->src == NULL) + return GIT_ENOMEM; + + refspec->dst = git__strdup(delim + 1); + if (refspec->dst == NULL) { + free(refspec->src); + refspec->src = NULL; + return GIT_ENOMEM; + } + + return GIT_SUCCESS; +} + +const char *git_refspec_src(const git_refspec *refspec) +{ + return refspec->src; +} + +const char *git_refspec_dst(const git_refspec *refspec) +{ + return refspec->dst; +} diff --git a/src/refspec.h b/src/refspec.h new file mode 100644 index 000000000..230135a4a --- /dev/null +++ b/src/refspec.h @@ -0,0 +1,14 @@ +#ifndef INCLUDE_refspec_h__ +#define INCLUDE_refspec_h__ + +#include "git2/refspec.h" + +struct git_refspec { + int force; + char *src; + char *dst; +}; + +int git_refspec_parse(struct git_refspec *refspec, const char *str); + +#endif diff --git a/src/remote.c b/src/remote.c new file mode 100644 index 000000000..7da6e653e --- /dev/null +++ b/src/remote.c @@ -0,0 +1,186 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "git2/remote.h" +#include "git2/config.h" +#include "git2/types.h" + +#include "config.h" +#include "repository.h" +#include "remote.h" + +static int refspec_parse(git_refspec *refspec, const char *str) +{ + char *delim; + + memset(refspec, 0x0, sizeof(git_refspec)); + + if (*str == '+') { + refspec->force = 1; + str++; + } + + delim = strchr(str, ':'); + if (delim == NULL) + return git__throw(GIT_EOBJCORRUPTED, "Failed to parse refspec. No ':'"); + + refspec->src = git__strndup(str, delim - str); + if (refspec->src == NULL) + return GIT_ENOMEM; + + refspec->dst = git__strdup(delim + 1); + if (refspec->dst == NULL) { + free(refspec->src); + refspec->src = NULL; + return GIT_ENOMEM; + } + + return GIT_SUCCESS; +} + +static int parse_remote_refspec(git_config *cfg, git_refspec *refspec, const char *var) +{ + const char *val; + int error; + + error = git_config_get_string(cfg, var, &val); + if (error < GIT_SUCCESS) + return error; + + return git_refspec_parse(refspec, val); +} + +int git_remote_get(git_remote **out, git_config *cfg, const char *name) +{ + git_remote *remote; + char *buf = NULL; + const char *val; + int ret, error, buf_len; + + remote = git__malloc(sizeof(git_remote)); + if (remote == NULL) + return GIT_ENOMEM; + + memset(remote, 0x0, sizeof(git_remote)); + remote->name = git__strdup(name); + if (remote->name == NULL) { + error = GIT_ENOMEM; + goto cleanup; + } + + /* "fetch" is the longest var name we're interested in */ + buf_len = STRLEN("remote.") + STRLEN(".fetch") + strlen(name) + 1; + buf = git__malloc(buf_len); + if (buf == NULL) { + error = GIT_ENOMEM; + goto cleanup; + } + + ret = snprintf(buf, buf_len, "%s.%s.%s", "remote", name, "url"); + if (ret < 0) { + error = git__throw(GIT_EOSERR, "Failed to build config var name"); + goto cleanup; + } + + error = git_config_get_string(cfg, buf, &val); + if (error < GIT_SUCCESS) { + error = git__rethrow(error, "Remote's url doesn't exist"); + goto cleanup; + } + + remote->url = git__strdup(val); + if (remote->url == NULL) { + error = GIT_ENOMEM; + goto cleanup; + } + + ret = snprintf(buf, buf_len, "%s.%s.%s", "remote", name, "fetch"); + if (ret < 0) { + error = git__throw(GIT_EOSERR, "Failed to build config var name"); + goto cleanup; + } + + error = git_config_get_string(cfg, buf, &val); + if (error < GIT_SUCCESS) + goto cleanup; + + error = refspec_parse(&remote->fetch, val); + if (error < GIT_SUCCESS) + goto cleanup; + + ret = snprintf(buf, buf_len, "%s.%s.%s", "remote", name, "push"); + if (ret < 0) { + error = git__throw(GIT_EOSERR, "Failed to build config var name"); + goto cleanup; + } + + error = git_config_get_string(cfg, buf, &val); + if (error < GIT_SUCCESS) + goto cleanup; + + error = refspec_parse(&remote->push, val); + if (error < GIT_SUCCESS) + goto cleanup; + + *out = remote; + +cleanup: + free(buf); + if (error < GIT_SUCCESS) + git_remote_free(remote); + + return error; +} + +const char *git_remote_name(struct git_remote *remote) +{ + return remote->name; +} + +const char *git_remote_url(struct git_remote *remote) +{ + return remote->url; +} + +const git_refspec *git_remote_fetchspec(struct git_remote *remote) +{ + return &remote->fetch; +} + +const git_refspec *git_remote_pushspec(struct git_remote *remote) +{ + return &remote->push; +} + +void git_remote_free(git_remote *remote) +{ + free(remote->fetch.src); + free(remote->fetch.dst); + free(remote->push.src); + free(remote->push.dst); + free(remote->url); + free(remote->name); + free(remote); +} diff --git a/src/remote.h b/src/remote.h new file mode 100644 index 000000000..afd2d1bb9 --- /dev/null +++ b/src/remote.h @@ -0,0 +1,14 @@ +#ifndef INCLUDE_remote_h__ +#define INCLUDE_remote_h__ + +#include "remote.h" +#include "refspec.h" + +struct git_remote { + char *name; + char *url; + struct git_refspec fetch; + struct git_refspec push; +}; + +#endif |