]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'jc/branch-merged'
authorJunio C Hamano <gitster@pobox.com>
Tue, 15 Jul 2008 06:47:01 +0000 (23:47 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 15 Jul 2008 06:47:01 +0000 (23:47 -0700)
* jc/branch-merged:
  branch --merged/--no-merged: allow specifying arbitrary commit
  branch --contains: default to HEAD
  parse-options: add PARSE_OPT_LASTARG_DEFAULT flag

Conflicts:
Documentation/git-branch.txt

1  2 
Documentation/git-branch.txt
builtin-branch.c

index b3e62ed011f0a99ce3f173a3f22758edc457f72b,450f90368f74ce104adaea4d8f290dbd99eb84e1..fc5a4a602fb7cbc5e73f7029a0b82bba05d0b913
@@@ -8,24 -8,27 +8,27 @@@ git-branch - List, create, or delete br
  SYNOPSIS
  --------
  [verse]
- 'git branch' [--color | --no-color] [-r | -a] [--merged | --no-merged]
-          [-v [--abbrev=<length> | --no-abbrev]]
-          [--contains <commit>]
 -'git-branch' [--color | --no-color] [-r | -a]
++'git branch' [--color | --no-color] [-r | -a]
+       [-v [--abbrev=<length> | --no-abbrev]]
+       [(--merged | --no-merged | --contains) [<commit>]]
 -'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
 -'git-branch' (-m | -M) [<oldbranch>] <newbranch>
 -'git-branch' (-d | -D) [-r] <branchname>...
 +'git branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
 +'git branch' (-m | -M) [<oldbranch>] <newbranch>
 +'git branch' (-d | -D) [-r] <branchname>...
  
  DESCRIPTION
  -----------
- With no arguments given a list of existing branches
- will be shown, the current branch will be highlighted with an asterisk.
- Option `-r` causes the remote-tracking branches to be listed,
- and option `-a` shows both.
- With `--contains <commit>`, shows only the branches that
- contains the named commit (in other words, the branches whose
- tip commits are descendant of the named commit).
- With `--merged`, only branches merged into HEAD will be listed, and
- with `--no-merged` only branches not merged into HEAD will be listed.
+ With no arguments, existing branches are listed, the current branch will
+ be highlighted with an asterisk.  Option `-r` causes the remote-tracking
+ branches to be listed, and option `-a` shows both.
+ With `--contains`, shows only the branches that contains the named commit
+ (in other words, the branches whose tip commits are descendant of the
+ named commit).  With `--merged`, only branches merged into the named
+ commit (i.e. the branches whose tip commits are reachable from the named
+ commit) will be listed.  With `--no-merged` only branches not merged into
+ the named commit will be listed.  Missing <commit> argument defaults to
+ 'HEAD' (i.e. the tip of the current branch).
  
  In its second form, a new branch named <branchname> will be created.
  It will start out with a head equal to the one given as <start-point>.
@@@ -37,7 -40,7 +40,7 @@@ working tree to it; use "git checkout <
  new branch.
  
  When a local branch is started off a remote branch, git sets up the
 -branch so that linkgit:git-pull[1] will appropriately merge from
 +branch so that 'git-pull' will appropriately merge from
  the remote branch. This behavior may be changed via the global
  `branch.autosetupmerge` configuration flag. That setting can be
  overridden by using the `--track` and `--no-track` options.
@@@ -54,7 -57,7 +57,7 @@@ has a reflog then the reflog will also 
  
  Use -r together with -d to delete remote-tracking branches. Note, that it
  only makes sense to delete remote-tracking branches if they no longer exist
 -in remote repository or if linkgit:git-fetch[1] was configured not to fetch
 +in remote repository or if 'git-fetch' was configured not to fetch
  them again. See also 'prune' subcommand of linkgit:git-remote[1] for way to
  clean up all obsolete remote-tracking branches.
  
@@@ -107,14 -110,14 +110,14 @@@ OPTION
        Display the full sha1s in output listing rather than abbreviating them.
  
  --track::
 -      When creating a new branch, set up configuration so that git-pull
 +      When creating a new branch, set up configuration so that 'git-pull'
        will automatically retrieve data from the start point, which must be
        a branch. Use this if you always pull from the same upstream branch
        into the new branch, and if you don't want to use "git pull
        <repository> <refspec>" explicitly. This behavior is the default
        when the start point is a remote branch. Set the
        branch.autosetupmerge configuration variable to `false` if you want
 -      git-checkout and git-branch to always behave as if '--no-track' were
 +      'git-checkout' and 'git-branch' to always behave as if '--no-track' were
        given. Set it to `always` if you want this behavior when the
        start-point is either a local or remote branch.
  
diff --combined builtin-branch.c
index ff71f3d8a6dd784ae08f89b8a98136e4cd369295,1926c47581050168abd0a5ed4e6ce45100cde2cf..7dae22c0197c2d3d062b0fa34c15b6c9a489eb31
@@@ -46,7 -46,12 +46,12 @@@ enum color_branch 
        COLOR_BRANCH_CURRENT = 4,
  };
  
- static int mergefilter = -1;
+ static enum merge_filter {
+       NO_FILTER = 0,
+       SHOW_NOT_MERGED,
+       SHOW_MERGED,
+ } merge_filter;
+ static unsigned char merge_filter_ref[20];
  
  static int parse_branch_color_slot(const char *var, int ofs)
  {
@@@ -234,13 -239,15 +239,15 @@@ static int append_ref(const char *refna
        if ((kind & ref_list->kinds) == 0)
                return 0;
  
-       if (mergefilter > -1) {
+       if (merge_filter != NO_FILTER) {
                branch.item = lookup_commit_reference_gently(sha1, 1);
                if (!branch.item)
                        die("Unable to lookup tip of branch %s", refname);
-               if (mergefilter == 0 && has_commit(head_sha1, &branch))
+               if (merge_filter == SHOW_NOT_MERGED &&
+                   has_commit(merge_filter_ref, &branch))
                        return 0;
-               if (mergefilter == 1 && !has_commit(head_sha1, &branch))
+               if (merge_filter == SHOW_MERGED &&
+                   !has_commit(merge_filter_ref, &branch))
                        return 0;
        }
  
@@@ -282,21 -289,6 +289,21 @@@ static int ref_cmp(const void *r1, cons
        return strcmp(c1->name, c2->name);
  }
  
 +static void fill_tracking_info(char *stat, const char *branch_name)
 +{
 +      int ours, theirs;
 +      struct branch *branch = branch_get(branch_name);
 +
 +      if (!stat_tracking_info(branch, &ours, &theirs) || (!ours && !theirs))
 +              return;
 +      if (!ours)
 +              sprintf(stat, "[behind %d] ", theirs);
 +      else if (!theirs)
 +              sprintf(stat, "[ahead %d] ", ours);
 +      else
 +              sprintf(stat, "[ahead %d, behind %d] ", ours, theirs);
 +}
 +
  static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
                           int abbrev, int current)
  {
        if (verbose) {
                struct strbuf subject;
                const char *sub = " **** invalid ref ****";
 +              char stat[128];
  
                strbuf_init(&subject, 0);
 +              stat[0] = '\0';
  
                commit = lookup_commit(item->sha1);
                if (commit && !parse_commit(commit)) {
                                            &subject, 0, NULL, NULL, 0, 0);
                        sub = subject.buf;
                }
 -              printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
 +
 +              if (item->kind == REF_LOCAL_BRANCH)
 +                      fill_tracking_info(stat, item->name);
 +
 +              printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
                       maxwidth, item->name,
                       branch_get_color(COLOR_BRANCH_RESET),
 -                     find_unique_abbrev(item->sha1, abbrev), sub);
 +                     find_unique_abbrev(item->sha1, abbrev),
 +                     stat, sub);
                strbuf_release(&subject);
        } else {
                printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
@@@ -443,6 -428,20 +450,20 @@@ static int opt_parse_with_commit(const 
        return 0;
  }
  
+ static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)
+ {
+       merge_filter = ((opt->long_name[0] == 'n')
+                       ? SHOW_NOT_MERGED
+                       : SHOW_MERGED);
+       if (unset)
+               merge_filter = SHOW_NOT_MERGED; /* b/c for --no-merged */
+       if (!arg)
+               arg = "HEAD";
+       if (get_sha1(arg, merge_filter_ref))
+               die("malformed object name %s", arg);
+       return 0;
+ }
  int cmd_branch(int argc, const char **argv, const char *prefix)
  {
        int delete = 0, rename = 0, force_create = 0;
                OPT_BOOLEAN( 0 , "color",  &branch_use_color, "use colored output"),
                OPT_SET_INT('r', NULL,     &kinds, "act on remote-tracking branches",
                        REF_REMOTE_BRANCH),
-               OPT_CALLBACK(0, "contains", &with_commit, "commit",
-                            "print only branches that contain the commit",
-                            opt_parse_with_commit),
+               {
+                       OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
+                       "print only branches that contain the commit",
+                       PARSE_OPT_LASTARG_DEFAULT,
+                       opt_parse_with_commit, (intptr_t)"HEAD",
+               },
                {
                        OPTION_CALLBACK, 0, "with", &with_commit, "commit",
                        "print only branches that contain the commit",
-                       PARSE_OPT_HIDDEN, opt_parse_with_commit,
+                       PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
+                       opt_parse_with_commit, (intptr_t) "HEAD",
                },
                OPT__ABBREV(&abbrev),
  
                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('f', NULL, &force_create, "force creation (when already exists)"),
-               OPT_SET_INT(0, "merged", &mergefilter, "list only merged branches", 1),
+               {
+                       OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
+                       "commit", "print only not merged branches",
+                       PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
+                       opt_parse_merge_filter, (intptr_t) "HEAD",
+               },
+               {
+                       OPTION_CALLBACK, 0, "merged", &merge_filter_ref,
+                       "commit", "print only merged branches",
+                       PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
+                       opt_parse_merge_filter, (intptr_t) "HEAD",
+               },
                OPT_END(),
        };
  
                branch_use_color = git_use_color_default;
  
        track = git_branch_track;
-       argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
-       if (!!delete + !!rename + !!force_create > 1)
-               usage_with_options(builtin_branch_usage, options);
  
        head = resolve_ref("HEAD", head_sha1, 0, NULL);
        if (!head)
                        die("HEAD not found below refs/heads!");
                head += 11;
        }
+       hashcpy(merge_filter_ref, head_sha1);
+       argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
+       if (!!delete + !!rename + !!force_create > 1)
+               usage_with_options(builtin_branch_usage, options);
  
        if (delete)
                return delete_branches(argc, argv, delete > 1, kinds);