Code

rev-parse --branches/--tags/--remotes=pattern
authorIlari Liusvaara <ilari.liusvaara@elisanet.fi>
Wed, 20 Jan 2010 09:48:26 +0000 (11:48 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 20 Jan 2010 20:30:25 +0000 (12:30 -0800)
Since local branch, tags and remote tracking branch namespaces are
most often used, add shortcut notations for globbing those in
manner similar to --glob option.

With this, one can express the "what I have but origin doesn't?"
as:

'git log --branches --not --remotes=origin'

Original-idea-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-log.txt
Documentation/git-rev-list.txt
Documentation/git-rev-parse.txt
Documentation/rev-list-options.txt
builtin-rev-parse.c
refs.c
refs.h
revision.c
t/t6018-rev-list-glob.sh

index 0b874e3d1ab41f6195dad7559ff4be60b1bcbd2a..0acd526303ec4cce8e8c0d1cbefb31411b52acde 100644 (file)
@@ -107,13 +107,13 @@ git log --follow builtin-rev-list.c::
        those commits that occurred before the file was given its
        present name.
 
-git log --branches --not --glob=remotes/origin/*::
+git log --branches --not --remotes=origin::
 
        Shows all commits that are in any of local branches but not in
        any of remote tracking branches for 'origin' (what you have that
        origin doesn't).
 
-git log master --not --glob=remotes/*/master::
+git log master --not --remotes=*/master::
 
        Shows all commits that are in local master but not in any remote
        repository master branches.
index 33122a3f335f145a79edb58ad7728c0e2c2a1ad3..f85711676b2320a739014070b6b3486919925c5e 100644 (file)
@@ -21,9 +21,9 @@ SYNOPSIS
             [ \--full-history ]
             [ \--not ]
             [ \--all ]
-            [ \--branches ]
-            [ \--tags ]
-            [ \--remotes ]
+            [ \--branches[=pattern] ]
+            [ \--tags=[pattern] ]
+            [ \--remotes=[pattern] ]
             [ \--glob=glob-pattern ]
             [ \--stdin ]
             [ \--quiet ]
index 6eb8c14f62d976e3adb6ff9d7f7a96cfca04b843..afe86999996bdac3af0499126cbec5767873dc79 100644 (file)
@@ -103,14 +103,21 @@ OPTIONS
 --all::
        Show all refs found in `$GIT_DIR/refs`.
 
---branches::
-       Show branch refs found in `$GIT_DIR/refs/heads`.
+--branches[=pattern]::
+       Show branch refs found in `$GIT_DIR/refs/heads`. If `pattern`
+       is given, only branches matching given shell glob are shown.
+       If pattern lacks '?', '*', or '[', '/*' at the end is impiled.
 
---tags::
-       Show tag refs found in `$GIT_DIR/refs/tags`.
+--tags[=pattern]::
+       Show tag refs found in `$GIT_DIR/refs/tags`. If `pattern`
+       is given, only tags matching given shell glob are shown.
+       If pattern lacks '?', '*', or '[', '/*' at the end is impiled.
 
---remotes::
-       Show tag refs found in `$GIT_DIR/refs/remotes`.
+--remotes[=pattern]::
+       Show tag refs found in `$GIT_DIR/refs/remotes`. If `pattern`
+       is given, only remote tracking branches matching given shell glob
+       are shown. If pattern lacks '?', '*', or '[', '/*' at the end is
+       impiled.
 
 --glob=glob-pattern::
        Show refs matching shell glob pattern `glob-pattern`. If pattern
index 6d03c17a684364d5c6576883d5408df833407c61..3ef71179d9b234733e392a36cae8aa37be6235b0 100644 (file)
@@ -228,20 +228,26 @@ endif::git-rev-list[]
        Pretend as if all the refs in `$GIT_DIR/refs/` are listed on the
        command line as '<commit>'.
 
---branches::
+--branches[=pattern]::
 
        Pretend as if all the refs in `$GIT_DIR/refs/heads` are listed
-       on the command line as '<commit>'.
+       on the command line as '<commit>'. If `pattern` is given, limit
+       branches to ones matching given shell glob. If pattern lacks '?',
+       '*', or '[', '/*' at the end is impiled.
 
---tags::
+--tags[=pattern]::
 
        Pretend as if all the refs in `$GIT_DIR/refs/tags` are listed
-       on the command line as '<commit>'.
+       on the command line as '<commit>'. If `pattern` is given, limit
+       tags to ones matching given shell glob. If pattern lacks '?', '*',
+       or '[', '/*' at the end is impiled.
 
---remotes::
+--remotes[=pattern]::
 
        Pretend as if all the refs in `$GIT_DIR/refs/remotes` are listed
-       on the command line as '<commit>'.
+       on the command line as '<commit>'. If `pattern`is given, limit
+       remote tracking branches to ones matching given shell glob.
+       If pattern lacks '?', '*', or '[', '/*' at the end is impiled.
 
 --glob=glob-pattern::
        Pretend as if all the refs matching shell glob `glob-pattern`
index a635dded65f1d6504bf84c872e0dc4d9efc0126d..d14fe20692aa0903f45da96bf9f31f4564b7816a 100644 (file)
@@ -41,6 +41,7 @@ static int is_rev_argument(const char *arg)
                "--all",
                "--bisect",
                "--dense",
+               "--branches=",
                "--branches",
                "--header",
                "--max-age=",
@@ -51,9 +52,11 @@ static int is_rev_argument(const char *arg)
                "--objects-edge",
                "--parents",
                "--pretty",
+               "--remotes=",
                "--remotes",
                "--glob=",
                "--sparse",
+               "--tags=",
                "--tags",
                "--topo-order",
                "--date-order",
@@ -570,10 +573,20 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                for_each_ref_in("refs/bisect/good", anti_reference, NULL);
                                continue;
                        }
+                       if (!prefixcmp(arg, "--branches=")) {
+                               for_each_glob_ref_in(show_reference, arg + 11,
+                                       "refs/heads/", NULL);
+                               continue;
+                       }
                        if (!strcmp(arg, "--branches")) {
                                for_each_branch_ref(show_reference, NULL);
                                continue;
                        }
+                       if (!prefixcmp(arg, "--tags=")) {
+                               for_each_glob_ref_in(show_reference, arg + 7,
+                                       "refs/tags/", NULL);
+                               continue;
+                       }
                        if (!strcmp(arg, "--tags")) {
                                for_each_tag_ref(show_reference, NULL);
                                continue;
@@ -582,6 +595,11 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                for_each_glob_ref(show_reference, arg + 7, NULL);
                                continue;
                        }
+                       if (!prefixcmp(arg, "--remotes=")) {
+                               for_each_glob_ref_in(show_reference, arg + 10,
+                                       "refs/remotes/", NULL);
+                               continue;
+                       }
                        if (!strcmp(arg, "--remotes")) {
                                for_each_remote_ref(show_reference, NULL);
                                continue;
diff --git a/refs.c b/refs.c
index 34fff75b0d2062b7c7445864fe9f9d70962b1bee..503a8c2bd0fa7e4fb825d543e007995701150948 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -690,15 +690,18 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
        return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data);
 }
 
-int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
+int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
+       const char *prefix, void *cb_data)
 {
        struct strbuf real_pattern = STRBUF_INIT;
        struct ref_filter filter;
        const char *has_glob_specials;
        int ret;
 
-       if (prefixcmp(pattern, "refs/"))
+       if (!prefix && prefixcmp(pattern, "refs/"))
                strbuf_addstr(&real_pattern, "refs/");
+       else if (prefix)
+               strbuf_addstr(&real_pattern, prefix);
        strbuf_addstr(&real_pattern, pattern);
 
        has_glob_specials = strpbrk(pattern, "?*[");
@@ -719,6 +722,11 @@ int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
        return ret;
 }
 
+int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
+{
+       return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
+}
+
 int for_each_rawref(each_ref_fn fn, void *cb_data)
 {
        return do_for_each_ref("refs/", fn, 0,
diff --git a/refs.h b/refs.h
index 78ad173f1b6eaf307543ea7fc5922e15cf343efc..f7648b9bd3b719936024678246d0603028e72aa7 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -26,6 +26,7 @@ extern int for_each_branch_ref(each_ref_fn, void *);
 extern int for_each_remote_ref(each_ref_fn, void *);
 extern int for_each_replace_ref(each_ref_fn, void *);
 extern int for_each_glob_ref(each_ref_fn, const char *pattern, void *);
+extern int for_each_glob_ref_in(each_ref_fn, const char *pattern, const char* prefix, void *);
 
 /* can be used to learn about broken ref and symref */
 extern int for_each_rawref(each_ref_fn, void *);
index 162b18291499886977ae2a348b78e7622bf72e16..1e9277d335aa4a5469f380c16b040c886b34ea5c 100644 (file)
@@ -1364,6 +1364,24 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                for_each_glob_ref(handle_one_ref, arg + 7, &cb);
                                continue;
                        }
+                       if (!prefixcmp(arg, "--branches=")) {
+                               struct all_refs_cb cb;
+                               init_all_refs_cb(&cb, revs, flags);
+                               for_each_glob_ref_in(handle_one_ref, arg + 11, "refs/heads/", &cb);
+                               continue;
+                       }
+                       if (!prefixcmp(arg, "--tags=")) {
+                               struct all_refs_cb cb;
+                               init_all_refs_cb(&cb, revs, flags);
+                               for_each_glob_ref_in(handle_one_ref, arg + 7, "refs/tags/", &cb);
+                               continue;
+                       }
+                       if (!prefixcmp(arg, "--remotes=")) {
+                               struct all_refs_cb cb;
+                               init_all_refs_cb(&cb, revs, flags);
+                               for_each_glob_ref_in(handle_one_ref, arg + 10, "refs/remotes/", &cb);
+                               continue;
+                       }
                        if (!strcmp(arg, "--reflog")) {
                                handle_reflog(revs, flags);
                                continue;
index 1f251e1f4364370ca4abc90bafdfd8c4b87667fa..8d3fa7d014c1e5a856f6c4c35cfb46eb8c44e684 100755 (executable)
@@ -32,7 +32,9 @@ test_expect_success 'setup' '
        git checkout -b someref master &&
        commit some &&
        git checkout master &&
-       commit master2
+       commit master2 &&
+       git tag foo/bar master &&
+       git update-ref refs/remotes/foo/baz master
 '
 
 test_expect_success 'rev-parse --glob=refs/heads/subspace/*' '
@@ -65,6 +67,24 @@ test_expect_success 'rev-parse --glob=heads/subspace' '
 
 '
 
+test_expect_success 'rev-parse --branches=subspace/*' '
+
+       compare rev-parse "subspace/one subspace/two" "--branches=subspace/*"
+
+'
+
+test_expect_success 'rev-parse --branches=subspace/' '
+
+       compare rev-parse "subspace/one subspace/two" "--branches=subspace/"
+
+'
+
+test_expect_success 'rev-parse --branches=subspace' '
+
+       compare rev-parse "subspace/one subspace/two" "--branches=subspace"
+
+'
+
 test_expect_success 'rev-parse --glob=heads/subspace/* --glob=heads/other/*' '
 
        compare rev-parse "subspace/one subspace/two other/three" "--glob=heads/subspace/* --glob=heads/other/*"
@@ -83,6 +103,18 @@ test_expect_success 'rev-parse --glob=heads/*' '
 
 '
 
+test_expect_success 'rev-parse --tags=foo' '
+
+       compare rev-parse "foo/bar" "--tags=foo"
+
+'
+
+test_expect_success 'rev-parse --remotes=foo' '
+
+       compare rev-parse "foo/baz" "--remotes=foo"
+
+'
+
 test_expect_success 'rev-list --glob=refs/heads/subspace/*' '
 
        compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
@@ -113,6 +145,23 @@ test_expect_success 'rev-list --glob=heads/subspace' '
 
 '
 
+test_expect_success 'rev-list --branches=subspace/*' '
+
+       compare rev-list "subspace/one subspace/two" "--branches=subspace/*"
+
+'
+
+test_expect_success 'rev-list --branches=subspace/' '
+
+       compare rev-list "subspace/one subspace/two" "--branches=subspace/"
+
+'
+
+test_expect_success 'rev-list --branches=subspace' '
+
+       compare rev-list "subspace/one subspace/two" "--branches=subspace"
+
+'
 test_expect_success 'rev-list --glob=heads/someref/* master' '
 
        compare rev-list "master" "--glob=heads/someref/* master"
@@ -131,4 +180,16 @@ test_expect_success 'rev-list --glob=heads/*' '
 
 '
 
+test_expect_success 'rev-list --tags=foo' '
+
+       compare rev-list "foo/bar" "--tags=foo"
+
+'
+
+test_expect_success 'rev-list --remotes=foo' '
+
+       compare rev-list "foo/baz" "--remotes=foo"
+
+'
+
 test_done