Signed-off-by: Felipe Contreras <felipe.contreras@xxxxxxxxx> --- Documentation/git-branch.txt | 11 +++++++++ branch.c | 43 +++++++++++++++++++++++++++++++++ branch.h | 2 ++ builtin/branch.c | 57 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index 311b336..914fd62 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -14,7 +14,9 @@ SYNOPSIS [(--merged | --no-merged | --contains) [<commit>]] [<pattern>...] 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>] 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>] +'git branch' (--set-publish-to=<publish> | -p <publish>) [<branchname>] 'git branch' --unset-upstream [<branchname>] +'git branch' --unset-publish [<branchname>] 'git branch' (-m | -M) [<oldbranch>] <newbranch> 'git branch' (-d | -D) [-r] <branchname>... 'git branch' --edit-description [<branchname>] @@ -191,6 +193,15 @@ start-point is either a local or remote-tracking branch. Remove the upstream information for <branchname>. If no branch is specified it defaults to the current branch. +-p <publish>:: +--set-publish-to=<publish>:: + Set up <branchname>'s publish tracking information. If no + <branchname> is specified, then it defaults to the current branch. + +--unset-publish:: + Remove the publish information for <branchname>. If no branch + is specified it defaults to the current branch. + --edit-description:: Open an editor and edit the text to explain what the branch is for, to be used by various other commands (e.g. `request-pull`). diff --git a/branch.c b/branch.c index 723a36b..6f4fe7f 100644 --- a/branch.c +++ b/branch.c @@ -144,6 +144,49 @@ static int setup_tracking(const char *new_ref, const char *orig_ref, return 0; } +void install_branch_publish(const char *name, const char *remote, const char *remote_ref) +{ + struct strbuf key = STRBUF_INIT; + + if (!remote && !strcmp(name, remote_ref + 11) && !prefixcmp(remote_ref, "refs/heads")) { + warning(_("Not setting branch %s as its own publish branch."), name); + return; + } + + strbuf_addf(&key, "branch.%s.pushremote", name); + git_config_set(key.buf, remote ? remote : "."); + + strbuf_reset(&key); + strbuf_addf(&key, "branch.%s.push", name); + git_config_set(key.buf, remote_ref); + + strbuf_release(&key); +} + +int setup_publish(const char *name, const char *ref) +{ + struct tracking tracking; + const char *remote, *remote_ref; + + memset(&tracking, 0, sizeof(tracking)); + tracking.spec.dst = (char*)ref; + if (for_each_remote(find_tracked_branch, &tracking)) + return 1; + + if (tracking.matches > 1) + return error(_("Not tracking: ambiguous information for ref %s"), + ref); + + remote = tracking.remote; + remote_ref = tracking.src ? tracking.src : ref; + + install_branch_publish(name, remote, remote_ref); + + free(tracking.src); + + return 0; +} + struct branch_desc_cb { const char *config_name; const char *value; diff --git a/branch.h b/branch.h index 64173ab..c9b6aa9 100644 --- a/branch.h +++ b/branch.h @@ -51,5 +51,7 @@ extern void install_branch_config(int flag, const char *local, const char *origi * Read branch description */ extern int read_branch_desc(struct strbuf *, const char *branch_name); +extern int setup_publish(const char *name, const char *ref); +extern void install_branch_publish(const char *name, const char *remote, const char *remote_ref); #endif diff --git a/builtin/branch.c b/builtin/branch.c index b4d7716..17773d7 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -793,8 +793,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) int delete = 0, rename = 0, force_create = 0, list = 0; int verbose = 0, abbrev = -1, detached = 0; int reflog = 0, edit_description = 0; - int quiet = 0, unset_upstream = 0; - const char *new_upstream = NULL; + int quiet = 0, unset_upstream = 0, unset_publish = 0; + const char *new_upstream = NULL, *publish = NULL; enum branch_track track; int kinds = REF_LOCAL_BRANCH; struct commit_list *with_commit = NULL; @@ -809,7 +809,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_SET_INT( 0, "set-upstream", &track, N_("change upstream info"), BRANCH_TRACK_OVERRIDE), OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"), + OPT_STRING('p', "set-publish-to", &publish, "publish", "change the publish info"), OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"), + OPT_BOOL(0, "unset-publish", &unset_publish, "Unset the publish info"), OPT__COLOR(&branch_use_color, N_("use colored output")), OPT_SET_INT('r', "remotes", &kinds, N_("act on remote-tracking branches"), REF_REMOTE_BRANCH), @@ -878,14 +880,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, builtin_branch_usage, 0); - if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0) + if (!delete && !rename && !edit_description && !new_upstream && !publish && + !unset_upstream && !unset_publish && argc == 0) list = 1; if (with_commit || merge_filter != NO_FILTER) list = 1; - if (!!delete + !!rename + !!force_create + !!new_upstream + - list + unset_upstream > 1) + if (!!delete + !!rename + !!force_create + !!new_upstream + !!publish + + list + unset_upstream + unset_publish > 1) usage_with_options(builtin_branch_usage, options); if (abbrev == -1) @@ -990,6 +993,50 @@ int cmd_branch(int argc, const char **argv, const char *prefix) strbuf_addf(&buf, "branch.%s.merge", branch->name); git_config_set_multivar(buf.buf, NULL, NULL, 1); strbuf_release(&buf); + } else if (publish) { + struct branch *branch = branch_get(argv[0]); + char *real_ref = NULL; + unsigned char sha1[20]; + + if (argc > 1) + die(_("too many branches to set new publish branch")); + + if (!branch) { + if (!argc || !strcmp(argv[0], "HEAD")) + die(_("could not set publish branch of HEAD when " + "it does not point to any branch.")); + die(_("no such branch '%s'"), argv[0]); + } + + if (!ref_exists(branch->refname)) + die(_("branch '%s' does not exist"), branch->name); + + if (dwim_ref(publish, strlen(publish), sha1, &real_ref) != 1 || + setup_publish(branch->name, real_ref)) + die(_("Cannot setup publish branch to '%s'."), publish); + } else if (unset_publish) { + struct branch *branch = branch_get(argv[0]); + struct strbuf buf = STRBUF_INIT; + + if (argc > 1) + die(_("too many branches to unset publish branch")); + + if (!branch) { + if (!argc || !strcmp(argv[0], "HEAD")) + die(_("could not unset publish branch of HEAD when " + "it does not point to any branch.")); + die(_("no such branch '%s'"), argv[0]); + } + + if (!branch->push_name) + die(_("Branch '%s' has no publish information"), branch->name); + + strbuf_addf(&buf, "branch.%s.pushremote", branch->name); + git_config_set_multivar(buf.buf, NULL, NULL, 1); + strbuf_reset(&buf); + strbuf_addf(&buf, "branch.%s.push", branch->name); + git_config_set_multivar(buf.buf, NULL, NULL, 1); + strbuf_release(&buf); } else if (argc > 0 && argc <= 2) { struct branch *branch = branch_get(argv[0]); int branch_existed = 0, remote_tracking = 0; -- 1.9.1+fc1 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html