int git_branch_upstream__name( git_buf *tracking_name, git_repository *repo, const char *canonical_branch_name) { 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_name && canonical_branch_name); if (!git_reference__is_branch(canonical_branch_name)) return not_a_local_branch(canonical_branch_name); if ((error = retrieve_upstream_configuration( &remote_name, repo, canonical_branch_name, "branch.%s.remote")) < 0) goto cleanup; if ((error = retrieve_upstream_configuration( &merge_name, repo, canonical_branch_name, "branch.%s.merge")) < 0) goto cleanup; if (!*remote_name || !*merge_name) { giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream", canonical_branch_name); error = GIT_ENOTFOUND; goto cleanup; } if (strcmp(".", remote_name) != 0) { if ((error = git_remote_load(&remote, repo, remote_name)) < 0) goto cleanup; refspec = git_remote__matching_refspec(remote, merge_name); if (!refspec) { 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_buf_set(tracking_name, git_buf_cstr(&buf), git_buf_len(&buf)); cleanup: git_remote_free(remote); git_buf_free(&buf); return error; }
int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname) { int error; git_config *cfg; if (!git_reference__is_branch(refname)) return not_a_local_branch(refname); if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) return error; git_buf_sanitize(buf); if ((error = retrieve_upstream_configuration(buf, cfg, refname, "branch.%s.remote")) < 0) return error; if (git_buf_len(buf) == 0) { giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream remote", refname); error = GIT_ENOTFOUND; git_buf_clear(buf); } return error; }
int git_branch_set_upstream(git_reference *branch, const char *upstream_name) { git_buf key = GIT_BUF_INIT, value = GIT_BUF_INIT; git_reference *upstream; git_repository *repo; git_remote *remote = NULL; git_config *config; const char *name, *shortname; int local, error; const git_refspec *fetchspec; name = git_reference_name(branch); if (!git_reference__is_branch(name)) return not_a_local_branch(name); if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0) return -1; shortname = name + strlen(GIT_REFS_HEADS_DIR); if (upstream_name == NULL) return unset_upstream(config, shortname); repo = git_reference_owner(branch); /* First we need to figure out whether it's a branch or remote-tracking */ if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_LOCAL) == 0) local = 1; else if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_REMOTE) == 0) local = 0; else { giterr_set(GITERR_REFERENCE, "Cannot set upstream for branch '%s'", shortname); return GIT_ENOTFOUND; } /* * If it's local, the remote is "." and the branch name is * simply the refname. Otherwise we need to figure out what * the remote-tracking branch's name on the remote is and use * that. */ if (local) error = git_buf_puts(&value, "."); else error = git_branch_remote_name(&value, repo, git_reference_name(upstream)); if (error < 0) goto on_error; if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0) goto on_error; if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0) goto on_error; if (local) { git_buf_clear(&value); if (git_buf_puts(&value, git_reference_name(upstream)) < 0) goto on_error; } else { /* Get the remoe-tracking branch's refname in its repo */ if (git_remote_lookup(&remote, repo, git_buf_cstr(&value)) < 0) goto on_error; fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream)); git_buf_clear(&value); if (!fetchspec || git_refspec_rtransform(&value, fetchspec, git_reference_name(upstream)) < 0) goto on_error; git_remote_free(remote); remote = NULL; } git_buf_clear(&key); if (git_buf_printf(&key, "branch.%s.merge", shortname) < 0) goto on_error; if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0) goto on_error; git_reference_free(upstream); git_buf_free(&key); git_buf_free(&value); return 0; on_error: git_reference_free(upstream); git_buf_free(&key); git_buf_free(&value); git_remote_free(remote); return -1; }
int git_branch_upstream_name( git_buf *out, git_repository *repo, const char *refname) { git_buf remote_name = GIT_BUF_INIT; git_buf merge_name = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT; int error = -1; git_remote *remote = NULL; const git_refspec *refspec; git_config *config; assert(out && refname); git_buf_sanitize(out); if (!git_reference__is_branch(refname)) return not_a_local_branch(refname); if ((error = git_repository_config_snapshot(&config, repo)) < 0) return error; if ((error = retrieve_upstream_configuration( &remote_name, config, refname, "branch.%s.remote")) < 0) goto cleanup; if ((error = retrieve_upstream_configuration( &merge_name, config, refname, "branch.%s.merge")) < 0) goto cleanup; if (git_buf_len(&remote_name) == 0 || git_buf_len(&merge_name) == 0) { giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream", refname); error = GIT_ENOTFOUND; goto cleanup; } if (strcmp(".", git_buf_cstr(&remote_name)) != 0) { if ((error = git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name))) < 0) goto cleanup; refspec = git_remote__matching_refspec(remote, git_buf_cstr(&merge_name)); if (!refspec) { error = GIT_ENOTFOUND; goto cleanup; } if (git_refspec_transform(&buf, refspec, git_buf_cstr(&merge_name)) < 0) goto cleanup; } else if (git_buf_set(&buf, git_buf_cstr(&merge_name), git_buf_len(&merge_name)) < 0) goto cleanup; error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf)); cleanup: git_config_free(config); git_remote_free(remote); git_buf_free(&remote_name); git_buf_free(&merge_name); git_buf_free(&buf); return error; }
int git_reference_is_branch(const git_reference *ref) { assert(ref); return git_reference__is_branch(ref->name); }