gitweb: Do not parse refs by hand, use git-peek-remote instead
authorJakub Narebski <jnareb@gmail.com>
Fri, 15 Sep 2006 01:43:28 +0000 (03:43 +0200)
committerJunio C Hamano <junkio@cox.net>
Fri, 15 Sep 2006 05:41:13 +0000 (22:41 -0700)
This is in response to Linus's work on packed refs. Additionally it
makes gitweb work with symrefs, too.

Do not parse refs by hand, using File::Find and reading individual
heads to get hash of reference, but use git-peek-remote output
instead.  Assume that the hash for deref (with ^{}) always follows hash
for ref, and that we have derefs only for tag objects; this removes
call to git_get_type (and git-cat-file -t invocation) for tags, which
speeds "summary" and "tags" views generation, but might slow generation
of "heads" view a bit.  For now, we do not save and use the deref hash.

Remove git_get_hash_by_ref while at it, as git_get_refs_list was the
only place it was used.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
gitweb/gitweb.perl

index 1d3a4c1e5bdd7c2a81d6c35929b989e4153ed743..b28da2c4d6e831e207fd598a6e7df1d38882442c 100755 (executable)
@@ -676,19 +676,6 @@ sub git_get_hash_by_path {
 ## ......................................................................
 ## git utility functions, directly accessing git repository
 
-# assumes that PATH is not symref
-sub git_get_hash_by_ref {
-       my $path = shift;
-
-       open my $fd, "$projectroot/$path" or return undef;
-       my $head = <$fd>;
-       close $fd;
-       chomp $head;
-       if ($head =~ m/^[0-9a-fA-F]{40}$/) {
-               return $head;
-       }
-}
-
 sub git_get_project_description {
        my $path = shift;
 
@@ -1098,17 +1085,27 @@ sub git_get_refs_list {
        my @reflist;
 
        my @refs;
-       my $pfxlen = length("$projectroot/$project/$ref_dir");
-       File::Find::find(sub {
-               return if (/^\./);
-               if (-f $_) {
-                       push @refs, substr($File::Find::name, $pfxlen + 1);
+       open my $fd, "-|", $GIT, "peek-remote", "$projectroot/$project/"
+               or return;
+       while (my $line = <$fd>) {
+               chomp $line;
+               if ($line =~ m/^([0-9a-fA-F]{40})\t$ref_dir\/?([^\^]+)$/) {
+                       push @refs, { hash => $1, name => $2 };
+               } elsif ($line =~ m/^[0-9a-fA-F]{40}\t$ref_dir\/?(.*)\^\{\}$/ &&
+                        $1 eq $refs[-1]{'name'}) {
+                       # most likely a tag is followed by its peeled
+                       # (deref) one, and when that happens we know the
+                       # previous one was of type 'tag'.
+                       $refs[-1]{'type'} = "tag";
                }
-       }, "$projectroot/$project/$ref_dir");
+       }
+       close $fd;
+
+       foreach my $ref (@refs) {
+               my $ref_file = $ref->{'name'};
+               my $ref_id   = $ref->{'hash'};
 
-       foreach my $ref_file (@refs) {
-               my $ref_id = git_get_hash_by_ref("$project/$ref_dir/$ref_file");
-               my $type = git_get_type($ref_id) || next;
+               my $type = $ref->{'type'} || git_get_type($ref_id) || next;
                my %ref_item = parse_ref($ref_file, $ref_id, $type);
 
                push @reflist, \%ref_item;