"git branch" uses "rev-parse --all" and becomes much too slow when there are many tags (it scans all refs). Use the new "--branches" option of rev-parse to speed things up. Signed-off-by: Sean Estabrooks <seanlkml@xxxxxxxxxxxx> --- On Sat, 13 May 2006 10:38:23 -0700 Junio C Hamano <junkio@xxxxxxx> wrote: > Makes sense perhaps. > > I understand you added --tags for completeness. Probably it > would make sense to add --remotes if you are shooting for that. > Hi Junio, Here's an updated patch with --remotes as you asked. I appened _ref to the new functions to make it clear that for_each_remote didn't have anything to do with remote files. Also updated the "is_rev_argument" function which was missed first time around. On a related note, would it be okay to change "git tag -l" to produce a list of tags without the "tags/" prefix in front of every tag as it does now? Wanted to use the new "git rev-parse --tags" instead of "find" to produce the list but am not sure how important backward compatibility is in that case. Sean Documentation/git-rev-parse.txt | 9 +++++++++ git-branch.sh | 3 +-- refs.c | 23 +++++++++++++++++++---- refs.h | 3 +++ rev-parse.c | 17 ++++++++++++++++- 5 files changed, 48 insertions(+), 7 deletions(-) 260bda5eb4effca1a1dd33beb7f7e962d3eab602 diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 8b95df0..ab896fc 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -67,6 +67,15 @@ OPTIONS --all:: Show all refs found in `$GIT_DIR/refs`. +--branches:: + Show branch refs found in `$GIT_DIR/refs/heads`. + +--tags:: + Show tag refs found in `$GIT_DIR/refs/tags`. + +--remotes:: + Show tag refs found in `$GIT_DIR/refs/remotes`. + --show-prefix:: When the command is invoked from a subdirectory, show the path of the current directory relative to the top-level diff --git a/git-branch.sh b/git-branch.sh index ebcc898..134e68c 100755 --- a/git-branch.sh +++ b/git-branch.sh @@ -82,8 +82,7 @@ done case "$#" in 0) - git-rev-parse --symbolic --all | - sed -ne 's|^refs/heads/||p' | + git-rev-parse --symbolic --branches | sort | while read ref do diff --git a/refs.c b/refs.c index 275b914..6c91ae6 100644 --- a/refs.c +++ b/refs.c @@ -114,7 +114,7 @@ int read_ref(const char *filename, unsig return -1; } -static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1)) +static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1), int trim) { int retval = 0; DIR *dir = opendir(git_path("%s", base)); @@ -146,7 +146,7 @@ static int do_for_each_ref(const char *b if (stat(git_path("%s", path), &st) < 0) continue; if (S_ISDIR(st.st_mode)) { - retval = do_for_each_ref(path, fn); + retval = do_for_each_ref(path, fn, trim); if (retval) break; continue; @@ -160,7 +160,7 @@ static int do_for_each_ref(const char *b "commit object!", path); continue; } - retval = fn(path, sha1); + retval = fn(path + trim, sha1); if (retval) break; } @@ -180,7 +180,22 @@ int head_ref(int (*fn)(const char *path, int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1)) { - return do_for_each_ref("refs", fn); + return do_for_each_ref("refs", fn, 0); +} + +int for_each_tag_ref(int (*fn)(const char *path, const unsigned char *sha1)) +{ + return do_for_each_ref("refs/tags", fn, 10); +} + +int for_each_branch_ref(int (*fn)(const char *path, const unsigned char *sha1)) +{ + return do_for_each_ref("refs/heads", fn, 11); +} + +int for_each_remote_ref(int (*fn)(const char *path, const unsigned char *sha1)) +{ + return do_for_each_ref("refs/remotes", fn, 13); } static char *ref_file_name(const char *ref) diff --git a/refs.h b/refs.h index 2625596..fa816c1 100644 --- a/refs.h +++ b/refs.h @@ -7,6 +7,9 @@ #define REFS_H */ extern int head_ref(int (*fn)(const char *path, const unsigned char *sha1)); extern int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1)); +extern int for_each_tag_ref(int (*fn)(const char *path, const unsigned char *sha1)); +extern int for_each_branch_ref(int (*fn)(const char *path, const unsigned char *sha1)); +extern int for_each_remote_ref(int (*fn)(const char *path, const unsigned char *sha1)); /** Reads the refs file specified into sha1 **/ extern int get_ref_sha1(const char *ref, unsigned char *sha1); diff --git a/rev-parse.c b/rev-parse.c index 62e16af..4e2d9fb 100644 --- a/rev-parse.c +++ b/rev-parse.c @@ -36,6 +36,7 @@ static int is_rev_argument(const char *a "--all", "--bisect", "--dense", + "--branches", "--header", "--max-age=", "--max-count=", @@ -45,7 +46,9 @@ static int is_rev_argument(const char *a "--objects-edge", "--parents", "--pretty", + "--remotes", "--sparse", + "--tags", "--topo-order", "--date-order", "--unpacked", @@ -165,7 +168,7 @@ int main(int argc, char **argv) int i, as_is = 0, verify = 0; unsigned char sha1[20]; const char *prefix = setup_git_directory(); - + git_config(git_default_config); for (i = 1; i < argc; i++) { @@ -255,6 +258,18 @@ int main(int argc, char **argv) for_each_ref(show_reference); continue; } + if (!strcmp(arg, "--branches")) { + for_each_branch_ref(show_reference); + continue; + } + if (!strcmp(arg, "--tags")) { + for_each_tag_ref(show_reference); + continue; + } + if (!strcmp(arg, "--remotes")) { + for_each_remote_ref(show_reference); + continue; + } if (!strcmp(arg, "--show-prefix")) { if (prefix) puts(prefix); -- 1.3.2.g575a1 - : send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html