From: Junio C Hamano Date: Wed, 5 Oct 2011 19:36:23 +0000 (-0700) Subject: Merge branch 'mg/branch-list' X-Git-Tag: v1.7.8-rc0~129 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/1077bf1ff676cd172a09b88204422228f21d7cbf?ds=inline;hp=-c Merge branch 'mg/branch-list' * mg/branch-list: t3200: clean up checks for file existence branch: -v does not automatically imply --list branch: allow pattern arguments branch: introduce --list option git-branch: introduce missing long forms for the options git-tag: introduce long forms for the options t6040: test branch -vv Conflicts: Documentation/git-tag.txt t/t3200-branch.sh --- 1077bf1ff676cd172a09b88204422228f21d7cbf diff --combined Documentation/git-tag.txt index fb1c0ac694,61e4b9bc08..c83cb13de6 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@@ -12,7 -12,7 +12,7 @@@ SYNOPSI 'git tag' [-a | -s | -u ] [-f] [-m | -F ] [ | ] 'git tag' -d ... -'git tag' [-n[]] -l [--contains ] [] +'git tag' [-n[]] -l [--contains ] [...] 'git tag' -v ... DESCRIPTION @@@ -43,12 -43,15 +43,15 @@@ GnuPG key for signing OPTIONS ------- -a:: + --annotate:: Make an unsigned, annotated tag object -s:: + --sign:: Make a GPG-signed tag, using the default e-mail address's key -u :: + --local-user=:: Make a GPG-signed tag, using the given key -f:: @@@ -56,9 -59,11 +59,11 @@@ Replace an existing tag with the given name (instead of failing) -d:: + --delete:: Delete existing tags with the given names. -v:: + --verify:: Verify the gpg signature of the given tag names. -n:: @@@ -69,6 -74,7 +74,7 @@@ If the tag is not annotated, the commit message is displayed instead. -l :: + --list :: List tags with names that match the given pattern (or all if no pattern is given). Running "git tag" without arguments also lists all tags. The pattern is a shell wildcard (i.e., matched @@@ -79,6 -85,7 +85,7 @@@ Only list tags which contain the specified commit. -m :: + --message=:: Use the given tag message (instead of prompting). If multiple `-m` options are given, their values are concatenated as separate paragraphs. @@@ -86,6 -93,7 +93,7 @@@ is given. -F :: + --file=:: Take the tag message from the given file. Use '-' to read the message from the standard input. Implies `-a` if none of `-a`, `-s`, or `-u ` diff --combined builtin/branch.c index f49596f826,099c75c228..009b7138ac --- a/builtin/branch.c +++ b/builtin/branch.c @@@ -71,7 -71,7 +71,7 @@@ static int parse_branch_color_slot(cons static int git_branch_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "color.branch")) { - branch_use_color = git_config_colorbool(var, value, -1); + branch_use_color = git_config_colorbool(var, value); return 0; } if (!prefixcmp(var, "color.branch.")) { @@@ -88,7 -88,7 +88,7 @@@ static const char *branch_get_color(enum color_branch ix) { - if (branch_use_color > 0) + if (want_color(branch_use_color)) return branch_colors[ix]; return ""; } @@@ -260,9 -260,22 +260,22 @@@ static char *resolve_symref(const char struct append_ref_cb { struct ref_list *ref_list; + const char **pattern; int ret; }; + static int match_patterns(const char **pattern, const char *refname) + { + if (!*pattern) + return 1; /* no pattern always matches */ + while (*pattern) { + if (!fnmatch(*pattern, refname, 0)) + return 1; + pattern++; + } + return 0; + } + static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct append_ref_cb *cb = (struct append_ref_cb *)(cb_data); @@@ -297,6 -310,9 +310,9 @@@ if ((kind & ref_list->kinds) == 0) return 0; + if (!match_patterns(cb->pattern, refname)) + return 0; + commit = NULL; if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) { commit = lookup_commit_reference_gently(sha1, 1); @@@ -492,7 -508,7 +508,7 @@@ static void show_detached(struct ref_li } } - static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) + static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern) { int i; struct append_ref_cb cb; @@@ -506,6 -522,7 +522,7 @@@ if (merge_filter != NO_FILTER) init_revisions(&ref_list.revs, NULL); cb.ref_list = &ref_list; + cb.pattern = pattern; cb.ret = 0; for_each_rawref(append_ref, &cb); if (merge_filter != NO_FILTER) { @@@ -523,7 -540,7 +540,7 @@@ qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); - if (detached) + if (detached && match_patterns(pattern, "HEAD")) show_detached(&ref_list); for (i = 0; i < ref_list.index; i++) { @@@ -566,7 -583,11 +583,7 @@@ static void rename_branch(const char *o die(_("Invalid branch name: '%s'"), oldname); } - if (strbuf_check_branch_ref(&newref, newname)) - die(_("Invalid branch name: '%s'"), newname); - - if (resolve_ref(newref.buf, sha1, 1, NULL) && !force) - die(_("A branch named '%s' already exists."), newref.buf + 11); + validate_new_branchname(newname, &newref, force, 0); strbuf_addf(&logmsg, "Branch: renamed %s to %s", oldref.buf, newref.buf); @@@ -608,7 -629,7 +625,7 @@@ static int opt_parse_merge_filter(cons int cmd_branch(int argc, const char **argv, const char *prefix) { - int delete = 0, rename = 0, force_create = 0; + int delete = 0, rename = 0, force_create = 0, list = 0; int verbose = 0, abbrev = -1, detached = 0; int reflog = 0; enum branch_track track; @@@ -624,7 -645,7 +641,7 @@@ 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", + OPT_SET_INT('r', "remotes", &kinds, "act on remote-tracking branches", REF_REMOTE_BRANCH), { OPTION_CALLBACK, 0, "contains", &with_commit, "commit", @@@ -641,13 -662,14 +658,14 @@@ OPT__ABBREV(&abbrev), OPT_GROUP("Specific git-branch actions:"), - OPT_SET_INT('a', NULL, &kinds, "list both remote-tracking and local branches", + OPT_SET_INT('a', "all", &kinds, "list both remote-tracking and local branches", REF_REMOTE_BRANCH | REF_LOCAL_BRANCH), - OPT_BIT('d', NULL, &delete, "delete fully merged branch", 1), + OPT_BIT('d', "delete", &delete, "delete fully merged branch", 1), OPT_BIT('D', NULL, &delete, "delete branch (even if not merged)", 2), - OPT_BIT('m', NULL, &rename, "move/rename a branch and its reflog", 1), + OPT_BIT('m', "move", &rename, "move/rename a branch and its reflog", 1), OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2), - OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"), + OPT_BOOLEAN(0, "list", &list, "list branch names"), + OPT_BOOLEAN('l', "create-reflog", &reflog, "create the branch's reflog"), OPT__FORCE(&force_create, "force creation (when already exists)"), { OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref, @@@ -669,6 -691,9 +687,6 @@@ git_config(git_branch_config, NULL); - if (branch_use_color == -1) - branch_use_color = git_use_color_default; - track = git_branch_track; head = resolve_ref("HEAD", head_sha1, 0, NULL); @@@ -686,7 -711,11 +704,11 @@@ argc = parse_options(argc, argv, prefix, options, builtin_branch_usage, 0); - if (!!delete + !!rename + !!force_create > 1) + + if (!delete && !rename && !force_create && argc == 0) + list = 1; + + if (!!delete + !!rename + !!force_create + !!list > 1) usage_with_options(builtin_branch_usage, options); if (abbrev == -1) @@@ -694,8 -723,9 +716,9 @@@ if (delete) return delete_branches(argc, argv, delete > 1, kinds); - else if (argc == 0) - return print_ref_list(kinds, detached, verbose, abbrev, with_commit); + else if (list) + return print_ref_list(kinds, detached, verbose, abbrev, + with_commit, argv); else if (rename && (argc == 1)) rename_branch(head, argv[0], rename > 1); else if (rename && (argc == 2)) diff --combined builtin/tag.c index 667515e527,e311911f5a..9d89616863 --- a/builtin/tag.c +++ b/builtin/tag.c @@@ -12,13 -12,11 +12,13 @@@ #include "tag.h" #include "run-command.h" #include "parse-options.h" +#include "diff.h" +#include "revision.h" static const char * const git_tag_usage[] = { "git tag [-a|-s|-u ] [-f] [-m |-F ] []", "git tag -d ...", - "git tag -l [-n[]] []", + "git tag -l [-n[]] [...]", "git tag -v ...", NULL }; @@@ -26,70 -24,17 +26,70 @@@ static char signingkey[1000]; struct tag_filter { - const char *pattern; + const char **patterns; int lines; struct commit_list *with_commit; }; +static int match_pattern(const char **patterns, const char *ref) +{ + /* no pattern means match everything */ + if (!*patterns) + return 1; + for (; *patterns; patterns++) + if (!fnmatch(*patterns, ref, 0)) + return 1; + return 0; +} + +static int in_commit_list(const struct commit_list *want, struct commit *c) +{ + for (; want; want = want->next) + if (!hashcmp(want->item->object.sha1, c->object.sha1)) + return 1; + return 0; +} + +static int contains_recurse(struct commit *candidate, + const struct commit_list *want) +{ + struct commit_list *p; + + /* was it previously marked as containing a want commit? */ + if (candidate->object.flags & TMP_MARK) + return 1; + /* or marked as not possibly containing a want commit? */ + if (candidate->object.flags & UNINTERESTING) + return 0; + /* or are we it? */ + if (in_commit_list(want, candidate)) + return 1; + + if (parse_commit(candidate) < 0) + return 0; + + /* Otherwise recurse and mark ourselves for future traversals. */ + for (p = candidate->parents; p; p = p->next) { + if (contains_recurse(p->item, want)) { + candidate->object.flags |= TMP_MARK; + return 1; + } + } + candidate->object.flags |= UNINTERESTING; + return 0; +} + +static int contains(struct commit *candidate, const struct commit_list *want) +{ + return contains_recurse(candidate, want); +} + static int show_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data) { struct tag_filter *filter = cb_data; - if (!fnmatch(filter->pattern, refname, 0)) { + if (match_pattern(filter->patterns, refname)) { int i; unsigned long size; enum object_type type; @@@ -102,7 -47,7 +102,7 @@@ commit = lookup_commit_reference_gently(sha1, 1); if (!commit) return 0; - if (!is_descendant_of(commit, filter->with_commit)) + if (!contains(commit, filter->with_commit)) return 0; } @@@ -143,12 -88,15 +143,12 @@@ return 0; } -static int list_tags(const char *pattern, int lines, +static int list_tags(const char **patterns, int lines, struct commit_list *with_commit) { struct tag_filter filter; - if (pattern == NULL) - pattern = "*"; - - filter.pattern = pattern; + filter.patterns = patterns; filter.lines = lines; filter.with_commit = with_commit; @@@ -429,21 -377,21 +429,21 @@@ int cmd_tag(int argc, const char **argv struct msg_arg msg = { 0, STRBUF_INIT }; struct commit_list *with_commit = NULL; struct option options[] = { - OPT_BOOLEAN('l', NULL, &list, "list tag names"), + OPT_BOOLEAN('l', "list", &list, "list tag names"), { OPTION_INTEGER, 'n', NULL, &lines, "n", "print lines of each tag message", PARSE_OPT_OPTARG, NULL, 1 }, - OPT_BOOLEAN('d', NULL, &delete, "delete tags"), - OPT_BOOLEAN('v', NULL, &verify, "verify tags"), + OPT_BOOLEAN('d', "delete", &delete, "delete tags"), + OPT_BOOLEAN('v', "verify", &verify, "verify tags"), OPT_GROUP("Tag creation options"), - OPT_BOOLEAN('a', NULL, &annotate, + OPT_BOOLEAN('a', "annotate", &annotate, "annotated tag, needs a message"), - OPT_CALLBACK('m', NULL, &msg, "message", + OPT_CALLBACK('m', "message", &msg, "message", "tag message", parse_msg_arg), - OPT_FILENAME('F', NULL, &msgfile, "read message from file"), - OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"), - OPT_STRING('u', NULL, &keyid, "key-id", + OPT_FILENAME('F', "file", &msgfile, "read message from file"), + OPT_BOOLEAN('s', "sign", &sign, "annotated and GPG-signed tag"), + OPT_STRING('u', "local-user", &keyid, "key-id", "use another key to sign the tag"), OPT__FORCE(&force, "replace the tag if exists"), @@@ -477,7 -425,7 +477,7 @@@ if (list + delete + verify > 1) usage_with_options(git_tag_usage, options); if (list) - return list_tags(argv[0], lines == -1 ? 0 : lines, + return list_tags(argv, lines == -1 ? 0 : lines, with_commit); if (lines != -1) die(_("-n option is only allowed with -l.")); diff --combined t/t3200-branch.sh index 7633930bb4,d530103878..2f5eada0d2 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@@ -23,7 -23,7 +23,7 @@@ test_expect_success test_expect_success \ 'git branch --help should not have created a bogus branch' ' git branch --help /dev/null 2>/dev/null; - ! test -f .git/refs/heads/--help + test_path_is_missing .git/refs/heads/--help ' test_expect_success 'branch -h in broken repository' ' @@@ -39,11 -39,11 +39,11 @@@ test_expect_success \ 'git branch abc should create a branch' \ - 'git branch abc && test -f .git/refs/heads/abc' + 'git branch abc && test_path_is_file .git/refs/heads/abc' test_expect_success \ 'git branch a/b/c should create a branch' \ - 'git branch a/b/c && test -f .git/refs/heads/a/b/c' + 'git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c' cat >expect < 1117150200 +0000 branch: Created from master @@@ -52,15 -52,15 +52,15 @@@ test_expect_success 'git branch -l d/e/f should create a branch and a log' \ 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ git branch -l d/e/f && - test -f .git/refs/heads/d/e/f && - test -f .git/logs/refs/heads/d/e/f && + test_path_is_file .git/refs/heads/d/e/f && + test_path_is_file .git/logs/refs/heads/d/e/f && test_cmp expect .git/logs/refs/heads/d/e/f' test_expect_success \ 'git branch -d d/e/f should delete a branch and a log' \ 'git branch -d d/e/f && - test ! -f .git/refs/heads/d/e/f && - test ! -f .git/logs/refs/heads/d/e/f' + test_path_is_missing .git/refs/heads/d/e/f && + test_path_is_missing .git/logs/refs/heads/d/e/f' test_expect_success \ 'git branch j/k should work after branch j has been deleted' \ @@@ -78,13 -78,13 +78,13 @@@ test_expect_success 'git branch -m m m/m should work' \ 'git branch -l m && git branch -m m m/m && - test -f .git/logs/refs/heads/m/m' + test_path_is_file .git/logs/refs/heads/m/m' test_expect_success \ 'git branch -m n/n n should work' \ 'git branch -l n/n && git branch -m n/n n - test -f .git/logs/refs/heads/n' + test_path_is_file .git/logs/refs/heads/n' test_expect_success 'git branch -m o/o o should fail when o/p exists' ' git branch o/o && @@@ -98,18 -98,38 +98,50 @@@ test_expect_success 'git branch -m q r/ test_must_fail git branch -m q r/q ' +test_expect_success 'git branch -M foo bar should fail when bar is checked out' ' + git branch bar && + git checkout -b foo && + test_must_fail git branch -M bar foo +' + +test_expect_success 'git branch -M baz bam should succeed when baz is checked out' ' + git checkout -b baz && + git branch bam && + git branch -M baz bam +' + + test_expect_success 'git branch -v -d t should work' ' + git branch t && + test_path_is_file .git/refs/heads/t && + git branch -v -d t && + test_path_is_missing .git/refs/heads/t + ' + + test_expect_success 'git branch -v -m t s should work' ' + git branch t && + test_path_is_file .git/refs/heads/t && + git branch -v -m t s && + test_path_is_missing .git/refs/heads/t && + test_path_is_file .git/refs/heads/s && + git branch -d s + ' + + test_expect_success 'git branch -m -d t s should fail' ' + git branch t && + test_path_is_file .git/refs/heads/t && + test_must_fail git branch -m -d t s && + git branch -d t && + test_path_is_missing .git/refs/heads/t + ' + + test_expect_success 'git branch --list -d t should fail' ' + git branch t && + test_path_is_file .git/refs/heads/t && + test_must_fail git branch --list -d t && + git branch -d t && + test_path_is_missing .git/refs/heads/t + ' + mv .git/config .git/config-saved test_expect_success 'git branch -m q q2 without config should succeed' ' @@@ -124,12 -144,12 +156,12 @@@ git config branch.s/s.dummy Hell test_expect_success \ 'git branch -m s/s s should work when s/t is deleted' \ 'git branch -l s/s && - test -f .git/logs/refs/heads/s/s && + test_path_is_file .git/logs/refs/heads/s/s && git branch -l s/t && - test -f .git/logs/refs/heads/s/t && + test_path_is_file .git/logs/refs/heads/s/t && git branch -d s/t && git branch -m s/s s && - test -f .git/logs/refs/heads/s' + test_path_is_file .git/logs/refs/heads/s' test_expect_success 'config information was renamed, too' \ "test $(git config branch.s.dummy) = Hello && @@@ -140,8 -160,8 +172,8 @@@ test_expect_success 'renaming a symref git symbolic-ref refs/heads/master2 refs/heads/master && test_must_fail git branch -m master2 master3 && git symbolic-ref refs/heads/master2 && - test -f .git/refs/heads/master && - ! test -f .git/refs/heads/master3 + test_path_is_file .git/refs/heads/master && + test_path_is_missing .git/refs/heads/master3 ' test_expect_success SYMLINKS \ @@@ -250,8 -270,8 +282,8 @@@ test_expect_success 'git checkout -b g/h/i -l should create a branch and a log' \ 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ git checkout -b g/h/i -l master && - test -f .git/refs/heads/g/h/i && - test -f .git/logs/refs/heads/g/h/i && + test_path_is_file .git/refs/heads/g/h/i && + test_path_is_file .git/logs/refs/heads/g/h/i && test_cmp expect .git/logs/refs/heads/g/h/i' test_expect_success 'checkout -b makes reflog by default' ' @@@ -554,17 -574,4 +586,17 @@@ test_expect_success 'attempt to delete test_must_fail git branch -d my10 ' +test_expect_success 'use set-upstream on the current branch' ' + git checkout master && + git --bare init myupstream.git && + git push myupstream.git master:refs/heads/frotz && + git remote add origin myupstream.git && + git fetch && + git branch --set-upstream master origin/frotz && + + test "z$(git config branch.master.remote)" = "zorigin" && + test "z$(git config branch.master.merge)" = "zrefs/heads/frotz" + +' + test_done diff --combined t/t6040-tracking-info.sh index 19de5b16eb,4e57dc8cdc..19272bc551 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@@ -51,6 -51,22 +51,22 @@@ test_expect_success 'branch -v' test_i18ncmp expect actual ' + cat >expect <<\EOF + b1 origin/master: ahead 1, behind 1 + b2 origin/master: ahead 1, behind 1 + b3 origin/master: behind 1 + b4 origin/master: ahead 2 + EOF + + test_expect_success 'branch -vv' ' + ( + cd test && + git branch -vv + ) | + sed -n -e "$script" >actual && + test_i18ncmp expect actual + ' + test_expect_success 'checkout' ' ( cd test && git checkout b1 @@@ -110,18 -126,4 +126,18 @@@ test_expect_success '--set-upstream doe grep -q "^refs/heads/master$" actual && cmp expect2 actual2 ' + +test_expect_success '--set-upstream @{-1}' ' + git checkout from-master && + git checkout from-master2 && + git config branch.from-master2.merge > expect2 && + git branch --set-upstream @{-1} follower && + git config branch.from-master.merge > actual && + git config branch.from-master2.merge > actual2 && + git branch --set-upstream from-master follower && + git config branch.from-master.merge > expect && + test_cmp expect2 actual2 && + test_cmp expect actual +' + test_done