So that it's possible to remove certain refs from the list without
removing the objects that are referenced by other refs.

For example this repository:

  * 374e8dd (crap) crap
  * 4cbbf7b (test) two
  * d025ae0 (HEAD, master) one

When using '--branches --except crap':

  * 4cbbf7b (test) two
  * d025ae0 (HEAD, master) one

But when using '--branches --not crap' nothing will come out.

Signed-off-by: Felipe Contreras <felipe.contre...@gmail.com>
---
 Documentation/git-rev-parse.txt        |  6 ++++++
 contrib/completion/git-completion.bash |  2 +-
 revision.c                             | 10 ++++++++++
 revision.h                             |  3 ++-
 t/t6112-rev-list-except.sh             | 35 ++++++++++++++++++++++++++++++++++
 5 files changed, 54 insertions(+), 2 deletions(-)
 create mode 100755 t/t6112-rev-list-except.sh

diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 2b126c0..fe5cc6b 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -110,6 +110,12 @@ can be used.
        strip '{caret}' prefix from the object names that already have
        one.
 
+--except::
+       Skip the following object names. For example:
+       '--branches --except master' will show all the branches, except master.
+       This differs from --not in that --except will still show the object, if
+       they are referenced by another object name.
+
 --symbolic::
        Usually the object names are output in SHA-1 form (with
        possible '{caret}' prefix); this option makes them output in a
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 5da920e..aed8c12 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1386,7 +1386,7 @@ _git_ls_tree ()
 
 # Options that go well for log, shortlog and gitk
 __git_log_common_options="
-       --not --all
+       --not --except --all
        --branches --tags --remotes
        --first-parent --merges --no-merges
        --max-count=
diff --git a/revision.c b/revision.c
index 84ccc05..375adab 100644
--- a/revision.c
+++ b/revision.c
@@ -1984,6 +1984,8 @@ static int handle_revision_pseudo_opt(const char 
*submodule,
                handle_reflog(revs, *flags);
        } else if (!strcmp(arg, "--not")) {
                *flags ^= UNINTERESTING | BOTTOM;
+       } else if (!strcmp(arg, "--except")) {
+               *flags ^= SKIP;
        } else if (!strcmp(arg, "--no-walk")) {
                revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
        } else if (!prefixcmp(arg, "--no-walk=")) {
@@ -2578,6 +2580,7 @@ int prepare_revision_walk(struct rev_info *revs)
        int nr = revs->pending.nr;
        struct object_array_entry *e, *list;
        struct commit_list **next = &revs->commits;
+       int i;
 
        e = list = revs->pending.objects;
        revs->pending.nr = 0;
@@ -2585,12 +2588,19 @@ int prepare_revision_walk(struct rev_info *revs)
        revs->pending.objects = NULL;
        while (--nr >= 0) {
                struct commit *commit = handle_commit(revs, e->item, e->name);
+               for (i = 0; i < revs->cmdline.nr; i++) {
+                       struct rev_cmdline_entry *ce;
+                       ce = &revs->cmdline.rev[i];
+                       if ((ce->flags & SKIP) && !strcmp(ce->name, e->name))
+                               goto next;
+               }
                if (commit) {
                        if (!(commit->object.flags & SEEN)) {
                                commit->object.flags |= SEEN;
                                next = commit_list_append(commit, next);
                        }
                }
+next:
                e++;
        }
        if (!revs->leak_pending)
diff --git a/revision.h b/revision.h
index 95859ba..89f5037 100644
--- a/revision.h
+++ b/revision.h
@@ -17,7 +17,8 @@
 #define SYMMETRIC_LEFT (1u<<8)
 #define PATCHSAME      (1u<<9)
 #define BOTTOM         (1u<<10)
-#define ALL_REV_FLAGS  ((1u<<11)-1)
+#define SKIP           (1u<<11)
+#define ALL_REV_FLAGS  ((1u<<12)-1)
 
 #define DECORATE_SHORT_REFS    1
 #define DECORATE_FULL_REFS     2
diff --git a/t/t6112-rev-list-except.sh b/t/t6112-rev-list-except.sh
new file mode 100755
index 0000000..b8f9a61
--- /dev/null
+++ b/t/t6112-rev-list-except.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description='test for rev-list --except'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+       echo one > content &&
+       git add content &&
+       git commit -m one &&
+       git checkout -b test master &&
+       echo two > content &&
+       git commit -a -m two &&
+       git checkout -b merge master &&
+       git merge test
+'
+
+test_expect_success 'rev-list --except' '
+
+       git rev-list --topo-order --branches --except merge > actual &&
+       git rev-list --topo-order test > expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'rev-list --except with extra' '
+
+       echo three > content &&
+       git commit -a -m three &&
+       git rev-list --topo-order --branches --except merge > actual &&
+       git rev-list --topo-order test > expect &&
+       test_cmp expect actual
+'
+
+test_done
-- 
1.8.4-fc

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to