threads / patch / 4127

patchAdd "--branches" and "--tags" options to git-rev-parse.

Subject: [PATCH] Add "--branches" and "--tags" options to git-rev-parse.

## tl;dr

6 messages between May 13, 2006 and May 15, 2006. Diffs are folded; open one to read it.

replies: 5people: 3as markdown or json

Sean Estabrooks· May 13, 2006, 15:13 UTC · lore

"git branch" uses rev-parse and can become slow when there are many tags. Use the new "--branches" option of rev-parse to speed things up.

Signed-off-by: Sean Estabrooks <seanlkml@sympatico.ca>
---
 Documentation/git-rev-parse.txt |    6 ++++++
 git-branch.sh                   |    3 +--
 refs.c                          |   18 ++++++++++++++----
 refs.h                          |    2 ++
 rev-parse.c                     |    8 ++++++++
 5 files changed, 31 insertions(+), 6 deletions(-)
7898e1e58b18e992e3d90516fc9e6f3476a385ed
Show changes to 5 files +31 −6

Documentation/git-rev-parse.txt, git-branch.sh, refs.c, refs.h, rev-parse.c

diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 8b95df0..c1da2bf 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -67,6 +67,12 @@ 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`.
+
 --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..9c29a73 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,17 @@ 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(int (*fn)(const char *path, const unsigned char *sha1))
+{
+	return do_for_each_ref("refs/tags", fn, 10);
+}
+
+int for_each_branch(int (*fn)(const char *path, const unsigned char *sha1))
+{
+	return do_for_each_ref("refs/heads", fn, 11);
 }
 
 static char *ref_file_name(const char *ref)
diff --git a/refs.h b/refs.h
index 2625596..f270b62 100644
--- a/refs.h
+++ b/refs.h
@@ -7,6 +7,8 @@ #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(int (*fn)(const char *path, const unsigned char *sha1));
+extern int for_each_branch(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..4eb38de 100644
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -255,6 +255,14 @@ int main(int argc, char **argv)
 				for_each_ref(show_reference);
 				continue;
 			}
+			if (!strcmp(arg, "--branches")) {
+				for_each_branch(show_reference);
+				continue;
+			}
+			if (!strcmp(arg, "--tags")) {
+				for_each_tag(show_reference);
+				continue;
+			}
 			if (!strcmp(arg, "--show-prefix")) {
 				if (prefix)
 					puts(prefix);
-- 
1.3.2.g419f
Junio C Hamano· May 13, 2006, 17:38 UTC · re: Sean Estabrooks · lore

Re: [PATCH] Add "--branches" and "--tags" options to git-rev-parse.

Sean Estabrooks <seanlkml@sympatico.ca> writes:
> "git branch" uses rev-parse and can become slow when there are many
> tags.  Use the new "--branches" option of rev-parse to speed things up.
Makes sense perhaps.

I understand you added --tags for completeness. Probably it would make sense to add --remotes if you are shooting for that.

Sean· May 14, 2006, 01:43 UTC · re: Junio C Hamano · lore

[PATCH] Add "--branches", "--tags" and "--remotes" options to git-rev-parse.

"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@sympatico.ca>
---

On Sat, 13 May 2006 10:38:23 -0700 Junio C Hamano <junkio@cox.net> wrote:

Show 5 quoted lines
> 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
Show changes to 5 files +48 −7

Documentation/git-rev-parse.txt, git-branch.sh, refs.c, refs.h, rev-parse.c

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
Junio C Hamano· May 14, 2006, 23:24 UTC · re: Sean · lore

Re: [PATCH] Add "--branches", "--tags" and "--remotes" options to git-rev-parse.

Sean <seanlkml@sympatico.ca> writes:
Show 5 quoted lines
> 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.

I do not have problem with that, but somebody else's script might; Cogito seems not to mind.

Something like this perhaps?
-- >8 --
Show changes to git-tag.sh +3 −4
diff --git a/git-tag.sh b/git-tag.sh
index dc6aa95..2286ad5 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -28,11 +28,10 @@ do
         cd "$GIT_DIR/refs" &&
 	case "$#" in
 	1)
-		find tags -type f -print ;;
-	*)
-		shift
-		find tags -type f -print | grep "$@" ;;
+		set x . ;;
 	esac
+	shift
+	find tags -type f -print | sed -e 's|^tags/||' | grep "$@"
 	exit $?
 	;;
     -m)
Sean· May 15, 2006, 00:07 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add "--branches", "--tags" and "--remotes" options to git-rev-parse.

On Sun, 14 May 2006 16:24:57 -0700 Junio C Hamano <junkio@cox.net> wrote:

> I do not have problem with that, but somebody else's script
> might; Cogito seems not to mind.
> 
> Something like this perhaps?

That looks good. If you accept the rev-parse patch, then i'd suggest the patch below instead.

Sean
Show changes to git-tag.sh +3 −5
diff --git a/git-tag.sh b/git-tag.sh
index dc6aa95..a0afa25 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -25,14 +25,12 @@ do
 	force=1
 	;;
     -l)
-        cd "$GIT_DIR/refs" &&
 	case "$#" in
 	1)
-		find tags -type f -print ;;
-	*)
-		shift
-		find tags -type f -print | grep "$@" ;;
+		set x . ;;
 	esac
+	shift
+	git rev-parse --symbolic --tags | sort | grep "$@"
 	exit $?
 	;;
     -m)
Jakub Narebski· May 15, 2006, 20:11 UTC · re: Sean · lore

Re: [PATCH] Add "--branches", "--tags" and "--remotes" options to git-rev-parse.

Sean Estabrooks wrote:
Show 7 quoted lines
> On Sat, 13 May 2006 10:38:23 -0700
> Junio C Hamano <junkio@cox.net> 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.
[...]
> +--remotes::
> +     Show tag refs found in `$GIT_DIR/refs/remotes`.
> +

In `Documentation/repository-layout.txt' there is information about `$GIT_DIR/remotes' not `$GIT_DIR/refs/remotes` so either the patch should be amended, or the layout documentation should be updated, or the layout repository should be changed.

-- 
Jakub Narebski
Warsaw, Poland

← back to recent threads