Merge branch 'nd/branch-error-cases'

Fix various error messages and conditions in "git branch", e.g. we
advertised "branch -d/-D" to remove one or more branches but actually
implemented removal of zero or more branches---request to remove no
branches was not rejected.

* nd/branch-error-cases:
  branch: let branch filters imply --list
  docs: clarify git-branch --list behavior
  branch: mark more strings for translation
  branch: give a more helpful message on redundant arguments
  branch: reject -D/-d without branch name
This commit is contained in:
Junio C Hamano 2013-02-07 14:41:38 -08:00
commit f507784d2c
4 changed files with 64 additions and 21 deletions

View File

@ -22,13 +22,15 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
----------- -----------
With no arguments, existing branches are listed and the current branch will If `--list` is given, or if there are no non-option arguments, existing
be highlighted with an asterisk. Option `-r` causes the remote-tracking branches are listed; the current branch will be highlighted with an
branches to be listed, and option `-a` shows both. This list mode is also asterisk. Option `-r` causes the remote-tracking branches to be listed,
activated by the `--list` option (see below). and option `-a` shows both local and remote branches. If a `<pattern>`
<pattern> restricts the output to matching branches, the pattern is a shell is given, it is used as a shell wildcard to restrict the output to
wildcard (i.e., matched using fnmatch(3)). matching branches. If multiple patterns are given, a branch is shown if
Multiple patterns may be given; if any of them matches, the branch is shown. it matches any of the patterns. Note that when providing a
`<pattern>`, you must use `--list`; otherwise the command is interpreted
as branch creation.
With `--contains`, shows only the branches that contain the named commit With `--contains`, shows only the branches that contain the named commit
(in other words, the branches whose tip commits are descendants of the (in other words, the branches whose tip commits are descendants of the
@ -193,15 +195,15 @@ start-point is either a local or remote-tracking branch.
--contains [<commit>]:: --contains [<commit>]::
Only list branches which contain the specified commit (HEAD Only list branches which contain the specified commit (HEAD
if not specified). if not specified). Implies `--list`.
--merged [<commit>]:: --merged [<commit>]::
Only list branches whose tips are reachable from the Only list branches whose tips are reachable from the
specified commit (HEAD if not specified). specified commit (HEAD if not specified). Implies `--list`.
--no-merged [<commit>]:: --no-merged [<commit>]::
Only list branches whose tips are not reachable from the Only list branches whose tips are not reachable from the
specified commit (HEAD if not specified). specified commit (HEAD if not specified). Implies `--list`.
<branchname>:: <branchname>::
The name of the branch to create or delete. The name of the branch to create or delete.

View File

@ -466,7 +466,7 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,
int verbose, int abbrev) int verbose, int abbrev)
{ {
struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT; struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
const char *sub = " **** invalid ref ****"; const char *sub = _(" **** invalid ref ****");
struct commit *commit = item->commit; struct commit *commit = item->commit;
if (commit && !parse_commit(commit)) { if (commit && !parse_commit(commit)) {
@ -590,7 +590,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
struct commit *filter; struct commit *filter;
filter = lookup_commit_reference_gently(merge_filter_ref, 0); filter = lookup_commit_reference_gently(merge_filter_ref, 0);
if (!filter) if (!filter)
die("object '%s' does not point to a commit", die(_("object '%s' does not point to a commit"),
sha1_to_hex(merge_filter_ref)); sha1_to_hex(merge_filter_ref));
filter->object.flags |= UNINTERESTING; filter->object.flags |= UNINTERESTING;
@ -825,6 +825,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0) if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
list = 1; list = 1;
if (with_commit || merge_filter != NO_FILTER)
list = 1;
if (!!delete + !!rename + !!force_create + !!list + !!new_upstream + !!unset_upstream > 1) if (!!delete + !!rename + !!force_create + !!list + !!new_upstream + !!unset_upstream > 1)
usage_with_options(builtin_branch_usage, options); usage_with_options(builtin_branch_usage, options);
@ -837,9 +840,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
colopts = 0; colopts = 0;
} }
if (delete) if (delete) {
if (!argc)
die(_("branch name required"));
return delete_branches(argc, argv, delete > 1, kinds, quiet); return delete_branches(argc, argv, delete > 1, kinds, quiet);
else if (list) { } else if (list) {
int ret = print_ref_list(kinds, detached, verbose, abbrev, int ret = print_ref_list(kinds, detached, verbose, abbrev,
with_commit, argv); with_commit, argv);
print_columns(&output, colopts, NULL); print_columns(&output, colopts, NULL);
@ -852,22 +857,23 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!argc) { if (!argc) {
if (detached) if (detached)
die("Cannot give description to detached HEAD"); die(_("Cannot give description to detached HEAD"));
branch_name = head; branch_name = head;
} else if (argc == 1) } else if (argc == 1)
branch_name = argv[0]; branch_name = argv[0];
else else
usage_with_options(builtin_branch_usage, options); die(_("cannot edit description of more than one branch"));
strbuf_addf(&branch_ref, "refs/heads/%s", branch_name); strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
if (!ref_exists(branch_ref.buf)) { if (!ref_exists(branch_ref.buf)) {
strbuf_release(&branch_ref); strbuf_release(&branch_ref);
if (!argc) if (!argc)
return error("No commit on branch '%s' yet.", return error(_("No commit on branch '%s' yet."),
branch_name); branch_name);
else else
return error("No such branch '%s'.", branch_name); return error(_("No branch named '%s'."),
branch_name);
} }
strbuf_release(&branch_ref); strbuf_release(&branch_ref);
@ -879,7 +885,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
else if (argc == 2) else if (argc == 2)
rename_branch(argv[0], argv[1], rename > 1); rename_branch(argv[0], argv[1], rename > 1);
else else
usage_with_options(builtin_branch_usage, options); die(_("too many branches for a rename operation"));
} else if (new_upstream) { } else if (new_upstream) {
struct branch *branch = branch_get(argv[0]); struct branch *branch = branch_get(argv[0]);

View File

@ -73,8 +73,8 @@ test_expect_success \
test_expect_success \ test_expect_success \
'git branch -m dumps usage' \ 'git branch -m dumps usage' \
'test_expect_code 129 git branch -m 2>err && 'test_expect_code 128 git branch -m 2>err &&
test_i18ngrep "[Uu]sage: git branch" err' test_i18ngrep "too many branches for a rename operation" err'
test_expect_success \ test_expect_success \
'git branch -m m m/m should work' \ 'git branch -m m m/m should work' \

View File

@ -55,6 +55,16 @@ test_expect_success 'branch --contains=side' '
' '
test_expect_success 'branch --contains with pattern implies --list' '
git branch --contains=master master >actual &&
{
echo " master"
} >expect &&
test_cmp expect actual
'
test_expect_success 'side: branch --merged' ' test_expect_success 'side: branch --merged' '
git branch --merged >actual && git branch --merged >actual &&
@ -66,6 +76,16 @@ test_expect_success 'side: branch --merged' '
' '
test_expect_success 'branch --merged with pattern implies --list' '
git branch --merged=side master >actual &&
{
echo " master"
} >expect &&
test_cmp expect actual
'
test_expect_success 'side: branch --no-merged' ' test_expect_success 'side: branch --no-merged' '
git branch --no-merged >actual && git branch --no-merged >actual &&
@ -95,4 +115,19 @@ test_expect_success 'master: branch --no-merged' '
' '
test_expect_success 'branch --no-merged with pattern implies --list' '
git branch --no-merged=master master >actual &&
>expect &&
test_cmp expect actual
'
test_expect_success 'implicit --list conflicts with modification options' '
test_must_fail git branch --contains=master -d &&
test_must_fail git branch --contains=master -m foo
'
test_done test_done