diff options
author | nulltoken <emeric.fermas@gmail.com> | 2012-07-20 18:38:54 +0400 |
---|---|---|
committer | nulltoken <emeric.fermas@gmail.com> | 2012-07-24 18:09:48 +0400 |
commit | fb910281d6598e2c235f6ec93384d4e08838d655 (patch) | |
tree | 03b18d2edfc6abfff5512b2e7b15b15bfbd44950 /src/branch.c | |
parent | bf9e8cc86b9c32946a395fd12a9b1a5cb71575a9 (diff) |
branch: introduce git_branch_tracking()
Diffstat (limited to 'src/branch.c')
-rw-r--r-- | src/branch.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/branch.c b/src/branch.c index 4a56fd1b9..d0ebb2dc3 100644 --- a/src/branch.c +++ b/src/branch.c @@ -8,6 +8,8 @@ #include "common.h" #include "commit.h" #include "tag.h" +#include "config.h" +#include "refspec.h" #include "git2/branch.h" @@ -220,3 +222,69 @@ int git_branch_lookup( return retrieve_branch_reference(ref_out, repo, branch_name, branch_type == GIT_BRANCH_REMOTE); } + +int retrieve_tracking_configuration(const char **out, git_reference *branch, const char *format) +{ + git_config *config; + git_buf buf = GIT_BUF_INIT; + int error; + + if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0) + return -1; + + if (git_buf_printf(&buf, format, + git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0) + return -1; + + error = git_config_get_string(out, config, git_buf_cstr(&buf)); + git_buf_free(&buf); + return error; +} + +int git_branch_tracking( + git_reference **tracking_out, + git_reference *branch) +{ + const char *remote_name, *merge_name; + git_buf buf = GIT_BUF_INIT; + int error = -1; + git_remote *remote = NULL; + const git_refspec *refspec; + + assert(tracking_out && branch); + + if (!git_reference_is_branch(branch)) + return not_a_local_branch(branch); + + if ((error = retrieve_tracking_configuration(&remote_name, branch, "branch.%s.remote")) < 0) + goto cleanup; + + if ((error = retrieve_tracking_configuration(&merge_name, branch, "branch.%s.merge")) < 0) + goto cleanup; + + if (strcmp(".", remote_name) != 0) { + if ((error = git_remote_load(&remote, git_reference_owner(branch), remote_name)) < 0) + goto cleanup; + + refspec = git_remote_fetchspec(remote); + if (refspec == NULL) { + error = GIT_ENOTFOUND; + goto cleanup; + } + + if (git_refspec_transform_r(&buf, refspec, merge_name) < 0) + goto cleanup; + } else + if (git_buf_sets(&buf, merge_name) < 0) + goto cleanup; + + error = git_reference_lookup( + tracking_out, + git_reference_owner(branch), + git_buf_cstr(&buf)); + +cleanup: + git_remote_free(remote); + git_buf_free(&buf); + return error; +} |