# Re: [PATCH/RFC] avoid accessing _all_ loose refs in git-show-ref

3 messages from 2006-12-16 to 2006-12-16. Participants: Junio C Hamano, Johannes Schindelin.
Thread: https://gitlist.dev/t/43405

## Johannes Schindelin, 2006-12-16 12:36

Subject: [PATCH/RFC] avoid accessing _all_ loose refs in git-show-ref
Message-ID: <Pine.LNX.4.63.0612161335140.3635@wbgn013.biozentrum.uni-wuerzburg.de>
URL: https://gitlist.dev/e/Pine.LNX.4.63.0612161335140.3635%40wbgn013.biozentrum.uni-wuerzburg.de

```

If you want to verify a ref, it is overkill to first read all loose refs
into a linked list, and then check if the desired ref is there.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

---

	This is kind of quick and dirty.

	An alternative would be to pack the tags _per default_. I once
	argued for that, but it appears nobody liked that idea. I even
	proposed to pack _all_ refs, and I still think this would be
	a good idea.

	However, HTTP/FTP transport would have to learn about that long
	before, and/or a config option would be needed to allow public
	repos to cater for older clients.

	Isn't it a bug that --verify succeeds, if only _one_ ref passed to 
	the command exists?

 builtin-show-ref.c |   14 +++++++++++++-
 refs.c             |   17 +++++++++++------
 refs.h             |    1 +
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/builtin-show-ref.c b/builtin-show-ref.c
index 0739798..b57b074 100644
--- a/builtin-show-ref.c
+++ b/builtin-show-ref.c
@@ -157,7 +157,19 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
 	}
 	if (show_head)
 		head_ref(show_ref, NULL);
-	for_each_ref(show_ref, NULL);
+	if (verify) {
+		for (i = 0; pattern[i]; i++)
+			if (!access(git_path(pattern[i]), R_OK)) {
+				unsigned char sha1[20];
+				if (resolve_ref(pattern[i], sha1, 1, NULL)) {
+					found_match++;
+					printf("%s %s\n", sha1_to_hex(sha1),
+							pattern[i]);
+				}
+			}
+		for_each_packed_ref(show_ref, NULL);
+	} else
+		for_each_ref(show_ref, NULL);
 	if (!found_match) {
 		if (verify && !quiet)
 			die("No match");
diff --git a/refs.c b/refs.c
index a02957c..7e6a459 100644
--- a/refs.c
+++ b/refs.c
@@ -413,11 +413,11 @@ int peel_ref(const char *ref, unsigned char *sha1)
 }
 
 static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
-			   void *cb_data)
+			   void *cb_data, int packed_only)
 {
 	int retval;
 	struct ref_list *packed = get_packed_refs();
-	struct ref_list *loose = get_loose_refs();
+	struct ref_list *loose = packed_only ? NULL : get_loose_refs();
 
 	while (packed && loose) {
 		struct ref_list *entry;
@@ -456,24 +456,29 @@ int head_ref(each_ref_fn fn, void *cb_data)
 	return 0;
 }
 
+int for_each_packed_ref(each_ref_fn fn, void *cb_data)
+{
+	return do_for_each_ref("refs/", fn, 0, cb_data, 1);
+}
+
 int for_each_ref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref("refs/", fn, 0, cb_data);
+	return do_for_each_ref("refs/", fn, 0, cb_data, 0);
 }
 
 int for_each_tag_ref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref("refs/tags/", fn, 10, cb_data);
+	return do_for_each_ref("refs/tags/", fn, 10, cb_data, 0);
 }
 
 int for_each_branch_ref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref("refs/heads/", fn, 11, cb_data);
+	return do_for_each_ref("refs/heads/", fn, 11, cb_data, 0);
 }
 
 int for_each_remote_ref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref("refs/remotes/", fn, 13, cb_data);
+	return do_for_each_ref("refs/remotes/", fn, 13, cb_data, 0);
 }
 
 /* NEEDSWORK: This is only used by ssh-upload and it should go; the
diff --git a/refs.h b/refs.h
index 51aab1e..0cfe7b5 100644
--- a/refs.h
+++ b/refs.h
@@ -19,6 +19,7 @@ struct ref_lock {
  */
 typedef int each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
 extern int head_ref(each_ref_fn, void *);
+extern int for_each_packed_ref(each_ref_fn, void *);
 extern int for_each_ref(each_ref_fn, void *);
 extern int for_each_tag_ref(each_ref_fn, void *);

```

## Junio C Hamano, 2006-12-16 13:12

Subject: Re: [PATCH/RFC] avoid accessing _all_ loose refs in git-show-ref
Message-ID: <7vk60sf0hr.fsf@assigned-by-dhcp.cox.net>
URL: https://gitlist.dev/e/7vk60sf0hr.fsf%40assigned-by-dhcp.cox.net
In-Reply-To: <Pine.LNX.4.63.0612161335140.3635@wbgn013.biozentrum.uni-wuerzburg.de>

```
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> 	This is kind of quick and dirty.

Maybe I am blind, but why don't you just do a resolve_ref()
regardless of packedness?  It only builds the packed refs list
when it is not found as a loose ref, and never builds the loose
refs list.  You probably would want to reject the ones that says
REF_ISSYMREF.

> 	An alternative would be to pack the tags _per default_. I once
> 	argued for that, but it appears nobody liked that idea. I even
> 	proposed to pack _all_ refs, and I still think this would be
> 	a good idea.

I do not think packing all refs is such a good idea.  Branches
are meant to be worked on and extended so the packed ones
would become stale quickly.  Packing all tags by default is
something we would want when everybody knows how to handle
them.

> 	Isn't it a bug that --verify succeeds, if only _one_ ref passed to 
> 	the command exists?

I think --verify should insist a single parameter, just like
rev-parse.

So wouldn't the code be like:

	if (verify) {
		int flag;
        	if (pattern[1])
                	die("Eh?");
		if (resolve_ref(pattern[0], sha1, 1, &flag) &&
                	(flag & REF_ISSYMREF) == 0) {
                		printf("%s %s\n",
                                	sha1_to_hex(sha1), pattern[0]);
				exit(0);
		} else
                	die("no match");
	}

???

```

## Johannes Schindelin, 2006-12-16 14:20

Subject: Re: [PATCH/RFC] avoid accessing _all_ loose refs in git-show-ref
Message-ID: <Pine.LNX.4.63.0612161518070.3635@wbgn013.biozentrum.uni-wuerzburg.de>
URL: https://gitlist.dev/e/Pine.LNX.4.63.0612161518070.3635%40wbgn013.biozentrum.uni-wuerzburg.de
In-Reply-To: <7vk60sf0hr.fsf@assigned-by-dhcp.cox.net>

```
Hi,

On Sat, 16 Dec 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > 	This is kind of quick and dirty.
> 
> Maybe I am blind, but why don't you just do a resolve_ref()
> regardless of packedness?  It only builds the packed refs list
> when it is not found as a loose ref, and never builds the loose
> refs list.  You probably would want to reject the ones that says
> REF_ISSYMREF.

But of course!

> > 	An alternative would be to pack the tags _per default_. I once
> > 	argued for that, but it appears nobody liked that idea. I even
> > 	proposed to pack _all_ refs, and I still think this would be
> > 	a good idea.
> 
> I do not think packing all refs is such a good idea.  Branches
> are meant to be worked on and extended so the packed ones
> would become stale quickly.

My idea would have been to edit them in-place. Since the hashes all take 
the same amount of bytes, it could be done by seeking around in the file.

>  Packing all tags by default is something we would want when everybody 
> knows how to handle them.

You mean all the scripts? Because if you make it the default, you could 
hide that implementation detail away from the user.

> > 	Isn't it a bug that --verify succeeds, if only _one_ ref passed to 
> > 	the command exists?
> 
> I think --verify should insist a single parameter, just like
> rev-parse.
> 
> So wouldn't the code be like:
> 
> 	if (verify) {
> 		int flag;
>         	if (pattern[1])
>                 	die("Eh?");
> 		if (resolve_ref(pattern[0], sha1, 1, &flag) &&
>                 	(flag & REF_ISSYMREF) == 0) {
>                 		printf("%s %s\n",
>                                 	sha1_to_hex(sha1), pattern[0]);
> 				exit(0);
> 		} else
>                 	die("no match");
> 	}
> 
> ???

Ack. Scrap my patch.

Ciao,
Dscho

```
