threads / rfc / 43405

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

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

## tl;dr

3 messages between Dec 16, 2006 and Dec 16, 2006. Diffs are folded; open one to read it.

replies: 2people: 2as markdown or json

Johannes Schindelin· Dec 16, 2006, 12:36 UTC · lore

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

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(-)
Show changes to 3 files +25 −7

builtin-show-ref.c, refs.c, refs.h

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· Dec 16, 2006, 13:12 UTC · re: Johannes Schindelin · lore
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· Dec 16, 2006, 14:20 UTC · re: Junio C Hamano · lore
Hi,
On Sat, 16 Dec 2006, Junio C Hamano wrote:
Show 9 quoted lines
> 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!
Show 8 quoted lines
> > 	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.

Show 22 quoted lines
> > 	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

← back to recent threads