add '--remote' as long version for '-r' update documentation add tests --- Documentation/git-branch.txt | 10 +++-- builtin/branch.c | 72 ++++++++++++++++++++++++++++++++---------- t/t3200-branch.sh | 34 ++++++++++++++++++++ t/t3203-branch-output.sh | 59 ++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 21 deletions(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index c50f189..242da9c 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -8,12 +8,12 @@ git-branch - List, create, or delete branches SYNOPSIS -------- [verse] -'git branch' [--color[=<when>] | --no-color] [-r | -a] +'git branch' [--color[=<when>] | --no-color] [-r[=<remote>] | -a] [-v [--abbrev=<length> | --no-abbrev]] [(--merged | --no-merged | --contains) [<commit>]] 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>] 'git branch' (-m | -M) [<oldbranch>] <newbranch> -'git branch' (-d | -D) [-r] <branchname>... +'git branch' (-d | -D) [-r[=<remote>]] <branchname>... DESCRIPTION ----------- @@ -99,8 +99,10 @@ OPTIONS default to color output. Same as `--color=never`. --r:: - List or delete (if used with -d) the remote-tracking branches. +-r[=<remote>]:: +--remote[=<remote>]:: + List or delete (if used with -d) the remote-tracking branches from + <remote> if specified. -a:: List both remote-tracking branches and local branches. diff --git a/builtin/branch.c b/builtin/branch.c index d6ab93b..52dff04 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -17,15 +17,18 @@ #include "revision.h" static const char * const builtin_branch_usage[] = { - "git branch [options] [-r | -a] [--merged | --no-merged]", + "git branch [options] [-r[=<remote>] | -a] [--merged | --no-merged]", "git branch [options] [-l] [-f] <branchname> [<start-point>]", - "git branch [options] [-r] (-d | -D) <branchname>", + "git branch [options] [-r[=<remote>]] (-d | -D) <branchname>", "git branch [options] (-m | -M) [<oldbranch>] <newbranch>", NULL }; #define REF_LOCAL_BRANCH 0x01 #define REF_REMOTE_BRANCH 0x02 +static int kinds = REF_LOCAL_BRANCH; + +static const char *remote = NULL; static const char *head; static unsigned char head_sha1[20]; @@ -144,12 +147,12 @@ static int branch_merged(int kind, const char *name, return merged; } -static int delete_branches(int argc, const char **argv, int force, int kinds) +static int delete_branches(int argc, const char **argv, int force) { struct commit *rev, *head_rev = NULL; unsigned char sha1[20]; char *name = NULL; - const char *fmt, *remote; + const char *fmt, *remote_trans; int i; int ret = 0; struct strbuf bname = STRBUF_INIT; @@ -158,12 +161,12 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) case REF_REMOTE_BRANCH: fmt = "refs/remotes/%s"; /* TRANSLATORS: This is "remote " in "remote branch '%s' not found" */ - remote = _("remote "); + remote_trans = _("remote "); force = 1; break; case REF_LOCAL_BRANCH: fmt = "refs/heads/%s"; - remote = ""; + remote_trans = ""; break; default: die(_("cannot use -a with -d")); @@ -175,7 +178,16 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) die(_("Couldn't look up commit object for HEAD")); } for (i = 0; i < argc; i++, strbuf_release(&bname)) { - strbuf_branchname(&bname, argv[i]); + if (kinds == REF_REMOTE_BRANCH && remote) { + struct strbuf buf = STRBUF_INIT; + strbuf_addstr(&buf, remote); + strbuf_addch(&buf, '/'); + strbuf_addstr(&buf, argv[i]); + strbuf_branchname(&bname, buf.buf); + strbuf_release(&buf); + } else { + strbuf_branchname(&bname, argv[i]); + } if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) { error(_("Cannot delete the branch '%s' " "which you are currently on."), bname.buf); @@ -188,7 +200,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) name = xstrdup(mkpath(fmt, bname.buf)); if (!resolve_ref(name, sha1, 1, NULL)) { error(_("%sbranch '%s' not found."), - remote, bname.buf); + remote_trans, bname.buf); ret = 1; continue; } @@ -209,12 +221,13 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) } if (delete_ref(name, sha1, 0)) { - error(_("Error deleting %sbranch '%s'"), remote, + error(_("Error deleting %sbranch '%s'"), remote_trans, bname.buf); ret = 1; } else { struct strbuf buf = STRBUF_INIT; - printf(_("Deleted %sbranch %s (was %s).\n"), remote, + printf(_("Deleted %sbranch %s (was %s).\n"), + remote_trans, bname.buf, find_unique_abbrev(sha1, DEFAULT_ABBREV)); strbuf_addf(&buf, "branch.%s", bname.buf); @@ -492,7 +505,7 @@ static void show_detached(struct ref_list *ref_list) } } -static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) +static int print_ref_list(int detached, int verbose, int abbrev, struct commit_list *with_commit) { int i; struct append_ref_cb cb; @@ -533,6 +546,14 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru char *prefix = (kinds != REF_REMOTE_BRANCH && ref_list.list[i].kind == REF_REMOTE_BRANCH) ? "remotes/" : ""; + if (kinds == REF_REMOTE_BRANCH && remote && + ref_list.list[i].kind == REF_REMOTE_BRANCH && + ref_list.list[i].name) { + int remote_len = strlen(remote); + if (strncmp(remote, ref_list.list[i].name, strlen(remote)) || + ref_list.list[i].name[remote_len] != '/') + continue; + } print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, abbrev, current, prefix); } @@ -610,13 +631,28 @@ static int opt_parse_merge_filter(const struct option *opt, const char *arg, int return 0; } +static int parse_opt_remote_cb(const struct option *opt, const char *arg, + int unset) +{ + kinds = REF_REMOTE_BRANCH; + if (unset) + kinds = REF_LOCAL_BRANCH; + if (arg) { + if ( *arg == '=') + remote = arg + 1; /* skip '=' */ + else + remote = arg; + } else + remote = NULL; + return 0; +} + int cmd_branch(int argc, const char **argv, const char *prefix) { int delete = 0, rename = 0, force_create = 0; int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0; int reflog = 0; enum branch_track track; - int kinds = REF_LOCAL_BRANCH; struct commit_list *with_commit = NULL; struct option options[] = { @@ -628,8 +664,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_SET_INT( 0, "set-upstream", &track, "change upstream info", BRANCH_TRACK_OVERRIDE), OPT__COLOR(&branch_use_color, "use colored output"), - OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches", - REF_REMOTE_BRANCH), + { + OPTION_CALLBACK, 'r', "remote", &kinds, "remote", + "act on remote-tracking branches", + PARSE_OPT_OPTARG, parse_opt_remote_cb, 0 + }, { OPTION_CALLBACK, 0, "contains", &with_commit, "commit", "print only branches that contain the commit", @@ -695,11 +734,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix) 0); if (!!delete + !!rename + !!force_create > 1) usage_with_options(builtin_branch_usage, options); - if (delete) - return delete_branches(argc, argv, delete > 1, kinds); + return delete_branches(argc, argv, delete > 1); else if (argc == 0) - return print_ref_list(kinds, detached, verbose, abbrev, with_commit); + return print_ref_list(detached, verbose, abbrev, with_commit); else if (rename && (argc == 1)) rename_branch(head, argv[0], rename > 1); else if (rename && (argc == 2)) diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 9e69c8c..df2f0f8 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -10,6 +10,23 @@ handled. Specifically, that a bogus branch is not created. ' . ./test-lib.sh +setup_repository () { + mkdir "$1" && ( + cd "$1" && + git init && + >file && + git add file && + test_tick && + git commit -m "Initial" && + git checkout -b side && + >elif && + git add elif && + test_tick && + git commit -m "Second" && + git checkout master + ) +} + test_expect_success \ 'prepare a trivial repository' \ 'echo Hello > A && @@ -542,4 +559,21 @@ test_expect_success 'attempt to delete a branch merged to its base' ' test_must_fail git branch -d my10 ' +test_expect_success 'git branch -d -r=one another should delete another branch from remote one' ' + setup_repository one && + setup_repository onelong && + ( + cd one && git branch another + ) && + git remote add -f one one && + git remote add -f onelong onelong && + git branch -d -r=one another && + test ! -f .git/refs/remotes/one/another && + test ! -f .git/logs/refs/remotes/one/another' + +test_expect_success 'git branch -d --remote=one master should delete master branch from remote one' ' + git branch -d --remote=one master && + test ! -f .git/refs/remotes/one/master && + test ! -f .git/logs/refs/remotes/one/master' + test_done diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 6b7c118..aa8cba6 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -3,6 +3,23 @@ test_description='git branch display tests' . ./test-lib.sh +setup_repository () { + mkdir "$1" && ( + cd "$1" && + git init && + >file && + git add file && + test_tick && + git commit -m "Initial" && + git checkout -b side && + >elif && + git add elif && + test_tick && + git commit -m "Second" && + git checkout master + ) +} + test_expect_success 'make commits' ' echo content >file && git add file && @@ -43,6 +60,26 @@ test_expect_success 'git branch -r shows remote branches' ' ' cat >expect <<'EOF' + origin/HEAD -> origin/branch-one + origin/branch-one + origin/branch-two +EOF +test_expect_success 'git branch -r=origin shows remote branches from origin' ' + git branch -r=origin >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' + origin/HEAD -> origin/branch-one + origin/branch-one + origin/branch-two +EOF +test_expect_success 'git branch --remote=origin shows remote branches from origin' ' + git branch --remote=origin >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' branch-one branch-two * master @@ -78,4 +115,26 @@ test_expect_success 'git branch shows detached HEAD properly' ' test_i18ncmp expect actual ' + +cat >expect <<'EOF' + one/another + one/master + one/side +EOF + +test_expect_success 'git branch -r=one shows only branches from remote one' ' + setup_repository one && + setup_repository onelong && + ( + cd one && git branch another + ) && + git remote add -f one one && + git remote add -f onelong onelong && + git branch -r=one >actual && + test_cmp expect actual' + +test_expect_success 'git branch --remote=one shows only branches from remote one' ' + git branch --remote=one >actual && + test_cmp expect actual' + test_done -- 1.7.6.rc2.4.g36bfb.dirty -- 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