threads / patch / 9643

patchGit.pm: Add remote_refs() git-ls-remote frontend

Subject: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

## tl;dr

9 messages between Aug 25, 2007 and Aug 31, 2007. Diffs are folded; open one to read it.

replies: 8people: 3as markdown or json

Petr Baudis· Aug 25, 2007, 22:11 UTC · lore
Should support all the important features, I guess. Too bad that
	git-ls-remote --heads .
	
is subtly different from
	git-ls-remote . refs/heads/
so we have to provide the interface for specifying both.
This patch also converts git-remote.perl to use it.
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
 git-remote.perl |    5 +----
 perl/Git.pm     |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+), 5 deletions(-)
Show changes to 2 files +55 −5

git-remote.perl, perl/Git.pm

diff --git a/git-remote.perl b/git-remote.perl
index 01cf480..8ce8418 100755
--- a/git-remote.perl
+++ b/git-remote.perl
@@ -128,10 +128,7 @@ sub update_ls_remote {
 	return if (($harder == 0) ||
 		   (($harder == 1) && exists $info->{'LS_REMOTE'}));
 
-	my @ref = map {
-		s|^[0-9a-f]{40}\s+refs/heads/||;
-		$_;
-	} $git->command(qw(ls-remote --heads), $info->{'URL'});
+	my @ref = keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
 	$info->{'LS_REMOTE'} = \@ref;
 }
 
diff --git a/perl/Git.pm b/perl/Git.pm
index 3f4080c..3bce733 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -51,7 +51,7 @@ require Exporter;
 # Methods which can be called as standalone functions as well:
 @EXPORT_OK = qw(command command_oneline command_noisy
                 command_output_pipe command_input_pipe command_close_pipe
-                version exec_path hash_object git_cmd_try);
+                version exec_path hash_object git_cmd_try remote_refs);
 
 
 =head1 DESCRIPTION
@@ -550,6 +550,59 @@ sub config_bool {
 }
 
 
+=item remote_refs ( REPOSITORY [, GROUPS [, REFGLOBS ] ] )
+
+This function returns a hashref of refs stored in a given remote repository.
+The hash is in the format C<refname =\> hash>. For tags, the C<refname> entry
+contains the tag object while a C<refname^{}> entry gives the tagged objects.
+
+C<REPOSITORY> has the same meaning as the appropriate C<git-ls-remote>
+argument; either an URL or a remote name (if called on a repository instance).
+C<GROUPS> is an optional arrayref that can contain 'tags' to return all the
+tags and/or 'heads' to return all the heads. C<REFGLOB> is an optional array
+of strings containing a shell-like glob to further limit the refs returned in
+the hash; the meaning is again the same as the appropriate C<git-ls-remote>
+argument.
+
+This function may or may not be called on a repository instance. In the former
+case, remote names as defined in the repository are recognized as repository
+specifiers.
+
+=cut
+
+sub remote_refs {
+	my ($self, $repo, $groups, $refglobs) = _maybe_self(@_);
+	my @args;
+	if (ref $groups eq 'ARRAY') {
+		foreach (@$groups) {
+			if ($_ eq 'heads') {
+				push (@args, '--heads');
+			} elsif ($_ eq 'tags') {
+				push (@args, '--tags');
+			} else {
+				# Ignore unknown groups for future
+				# compatibility
+			}
+		}
+	}
+	push (@args, $repo);
+	if (ref $refglobs eq 'ARRAY') {
+		push (@args, @$refglobs);
+	}
+
+	my @self = $self ? ($self) : (); # Ultra trickery
+	my ($fh, $ctx) = Git::command_output_pipe(@self, 'ls-remote', @args);
+	my %refs;
+	while (<$fh>) {
+		chomp;
+		my ($hash, $ref) = split(/\t/, $_, 2);
+		$refs{$ref} = $hash;
+	}
+	Git::command_close_pipe(@self, $fh, $ctx);
+	return \%refs;
+}
+
+
 =item ident ( TYPE | IDENTSTR )
 
 =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
Junio C Hamano· Aug 26, 2007, 04:26 UTC · re: Petr Baudis · lore

Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

Petr Baudis <pasky@suse.cz> writes:
Show 15 quoted lines
> diff --git a/git-remote.perl b/git-remote.perl
> index 01cf480..8ce8418 100755
> --- a/git-remote.perl
> +++ b/git-remote.perl
> @@ -128,10 +128,7 @@ sub update_ls_remote {
>  	return if (($harder == 0) ||
>  		   (($harder == 1) && exists $info->{'LS_REMOTE'}));
>  
> -	my @ref = map {
> -		s|^[0-9a-f]{40}\s+refs/heads/||;
> -		$_;
> -	} $git->command(qw(ls-remote --heads), $info->{'URL'});
> +	my @ref = keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
>  	$info->{'LS_REMOTE'} = \@ref;
>  }

IIRC, ls-remote returns refs sorted and this function returns them as it receives.

Doesn't this change make @ref randomly ordered?  
Petr Baudis· Aug 26, 2007, 09:58 UTC · re: Junio C Hamano · lore

Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

On Sun, Aug 26, 2007 at 06:26:29AM CEST, Junio C Hamano wrote:
Show 22 quoted lines
> Petr Baudis <pasky@suse.cz> writes:
> 
> > diff --git a/git-remote.perl b/git-remote.perl
> > index 01cf480..8ce8418 100755
> > --- a/git-remote.perl
> > +++ b/git-remote.perl
> > @@ -128,10 +128,7 @@ sub update_ls_remote {
> >  	return if (($harder == 0) ||
> >  		   (($harder == 1) && exists $info->{'LS_REMOTE'}));
> >  
> > -	my @ref = map {
> > -		s|^[0-9a-f]{40}\s+refs/heads/||;
> > -		$_;
> > -	} $git->command(qw(ls-remote --heads), $info->{'URL'});
> > +	my @ref = keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
> >  	$info->{'LS_REMOTE'} = \@ref;
> >  }
> 
> IIRC, ls-remote returns refs sorted and this function returns
> them as it receives.
> 
> Doesn't this change make @ref randomly ordered?  

Yes, but I couldn't find any place in git-remote.perl where we rely on the @ref ordering - maybe I'm blind...

-- 
				Petr "Pasky" Baudis
Ever try. Ever fail. No matter. // Try again. Fail again. Fail better.
		-- Samuel Beckett
Jakub Narebski· Aug 30, 2007, 08:39 UTC · re: Petr Baudis · lore

Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

[Cc: Petr Baudis <pasky@suse.cz>, git@vger.kernel.org]
Petr Baudis wrote:
Show 8 quoted lines
> Should support all the important features, I guess. Too bad that
>       git-ls-remote --heads .
>       
> is subtly different from
> 
>       git-ls-remote . refs/heads/
> 
> so we have to provide the interface for specifying both.

Why do not use git-for-each-ref or git-show-refs? If I remember correctly they _were_ faster than git-ls-remote or git-peek-remote...

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Petr Baudis· Aug 30, 2007, 23:37 UTC · re: Jakub Narebski · lore

Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

On Thu, Aug 30, 2007 at 10:39:41AM CEST, Jakub Narebski wrote:
Show 15 quoted lines
> [Cc: Petr Baudis <pasky@suse.cz>, git@vger.kernel.org]
> 
> Petr Baudis wrote:
> 
> > Should support all the important features, I guess. Too bad that
> >       git-ls-remote --heads .
> >       
> > is subtly different from
> > 
> >       git-ls-remote . refs/heads/
> > 
> > so we have to provide the interface for specifying both.
> 
> Why do not use git-for-each-ref or git-show-refs? If I remember correctly
> they _were_ faster than git-ls-remote or git-peek-remote...
But we want to typically list refs in a remote repository.
-- 
				Petr "Pasky" Baudis
Early to rise and early to bed makes a male healthy and wealthy and dead.
                -- James Thurber
Petr Baudis· Aug 30, 2007, 23:37 UTC · re: Petr Baudis · lore
Should support all the important features, I guess. Too bad that
	git-ls-remote --heads .
	
is subtly different from
	git-ls-remote . refs/heads/
so we have to provide the interface for specifying both.
This patch also converts git-remote.perl to use it.
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
This version re-adds missed out stripping of refs/heads/ in git-remote.perl.
---
 git-remote.perl |    5 +----
 perl/Git.pm     |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+), 5 deletions(-)
Show changes to 2 files +55 −5

git-remote.perl, perl/Git.pm

diff --git a/git-remote.perl b/git-remote.perl
index 01cf480..1948c5c 100755
--- a/git-remote.perl
+++ b/git-remote.perl
@@ -128,10 +128,7 @@ sub update_ls_remote {
 	return if (($harder == 0) ||
 		   (($harder == 1) && exists $info->{'LS_REMOTE'}));
 
-	my @ref = map {
-		s|^[0-9a-f]{40}\s+refs/heads/||;
-		$_;
-	} $git->command(qw(ls-remote --heads), $info->{'URL'});
+	my @ref = map { s|refs/heads/||; $_; } keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
 	$info->{'LS_REMOTE'} = \@ref;
 }
 
diff --git a/perl/Git.pm b/perl/Git.pm
index 3f4080c..3bce733 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -51,7 +51,7 @@ require Exporter;
 # Methods which can be called as standalone functions as well:
 @EXPORT_OK = qw(command command_oneline command_noisy
                 command_output_pipe command_input_pipe command_close_pipe
-                version exec_path hash_object git_cmd_try);
+                version exec_path hash_object git_cmd_try remote_refs);
 
 
 =head1 DESCRIPTION
@@ -550,6 +550,59 @@ sub config_bool {
 }
 
 
+=item remote_refs ( REPOSITORY [, GROUPS [, REFGLOBS ] ] )
+
+This function returns a hashref of refs stored in a given remote repository.
+The hash is in the format C<refname =\> hash>. For tags, the C<refname> entry
+contains the tag object while a C<refname^{}> entry gives the tagged objects.
+
+C<REPOSITORY> has the same meaning as the appropriate C<git-ls-remote>
+argument; either an URL or a remote name (if called on a repository instance).
+C<GROUPS> is an optional arrayref that can contain 'tags' to return all the
+tags and/or 'heads' to return all the heads. C<REFGLOB> is an optional array
+of strings containing a shell-like glob to further limit the refs returned in
+the hash; the meaning is again the same as the appropriate C<git-ls-remote>
+argument.
+
+This function may or may not be called on a repository instance. In the former
+case, remote names as defined in the repository are recognized as repository
+specifiers.
+
+=cut
+
+sub remote_refs {
+	my ($self, $repo, $groups, $refglobs) = _maybe_self(@_);
+	my @args;
+	if (ref $groups eq 'ARRAY') {
+		foreach (@$groups) {
+			if ($_ eq 'heads') {
+				push (@args, '--heads');
+			} elsif ($_ eq 'tags') {
+				push (@args, '--tags');
+			} else {
+				# Ignore unknown groups for future
+				# compatibility
+			}
+		}
+	}
+	push (@args, $repo);
+	if (ref $refglobs eq 'ARRAY') {
+		push (@args, @$refglobs);
+	}
+
+	my @self = $self ? ($self) : (); # Ultra trickery
+	my ($fh, $ctx) = Git::command_output_pipe(@self, 'ls-remote', @args);
+	my %refs;
+	while (<$fh>) {
+		chomp;
+		my ($hash, $ref) = split(/\t/, $_, 2);
+		$refs{$ref} = $hash;
+	}
+	Git::command_close_pipe(@self, $fh, $ctx);
+	return \%refs;
+}
+
+
 =item ident ( TYPE | IDENTSTR )
 
 =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
Junio C Hamano· Aug 31, 2007, 00:26 UTC · re: Petr Baudis · lore

Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

Petr Baudis <pasky@suse.cz> writes:
Show 9 quoted lines
> Should support all the important features, I guess. Too bad that
>
> 	git-ls-remote --heads .
> 	
> is subtly different from
>
> 	git-ls-remote . refs/heads/
>
> so we have to provide the interface for specifying both.

Are they subtly different? To me they look like asking for completely different things. IIRC, the patterns are ref globs, so

	git ls-remote $URL 'refs/heads/*'
would be the same as the former one.
Show 5 quoted lines
> This patch also converts git-remote.perl to use it.
>
> Signed-off-by: Petr Baudis <pasky@suse.cz>
> ---
> This version re-adds missed out stripping of refs/heads/ in git-remote.perl.

Ah, that was the bug you were talking about on #git channel, I guess...

Petr Baudis· Aug 31, 2007, 01:37 UTC · re: Junio C Hamano · lore

Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

On Fri, Aug 31, 2007 at 02:26:22AM CEST, Junio C Hamano wrote:
Show 19 quoted lines
> Petr Baudis <pasky@suse.cz> writes:
> 
> > Should support all the important features, I guess. Too bad that
> >
> > 	git-ls-remote --heads .
> > 	
> > is subtly different from
> >
> > 	git-ls-remote . refs/heads/
> >
> > so we have to provide the interface for specifying both.
> 
> Are they subtly different?  To me they look like asking for
> completely different things.  IIRC, the patterns are ref globs,
> so
> 
> 	git ls-remote $URL 'refs/heads/*'
> 
> would be the same as the former one.

Yes, though subtly different, as I've already explained before - for the case of say

	refs/remotes/evil/refs/heads
> Ah, that was the bug you were talking about on #git channel, I
> guess...
*nod*
-- 
				Petr "Pasky" Baudis
Early to rise and early to bed makes a male healthy and wealthy and dead.
                -- James Thurber
Junio C Hamano· Aug 31, 2007, 02:13 UTC · re: Petr Baudis · lore

Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend

Petr Baudis <pasky@suse.cz> writes:
Show 8 quoted lines
>> 	git ls-remote $URL 'refs/heads/*'
>> 
>> would be the same as the former one.
>
> Yes, though subtly different, as I've already explained before - for the
> case of say
>
> 	refs/remotes/evil/refs/heads

Are you voting for removal of "ls-remote $URL 'heads/*'" support? I actually think removing it makes a perfect sense.

>> Ah, that was the bug you were talking about on #git channel, I
>> guess...
>
> *nod*

← back to recent threads