{"thread":{"id":"8188","subject":"[PATCH] Git.pm: Add remote_refs() git-ls-remote frontend","startedAt":"2007-05-17T02:37:43Z","lastAt":"2007-05-17T11:30:28Z","messageCount":3,"participants":["Petr Baudis","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"42365","messageId":"20070517023743.1982.41240.stgit@rover","threadId":"8188","inReplyTo":null,"subject":"[PATCH] Git.pm: Add remote_refs() git-ls-remote frontend","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2007-05-17T02:37:43Z","receivedAt":"2007-05-17T02:37:43Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Should support all the important features, I guess. Too bad that\n\tgit-ls-remote --heads .\n\t\nis subtly different from\n\n\tgit-ls-remote . refs/heads/\n\nso we have to provide the interface for specifying both.\n\nThis patch also converts git-svn.perl to use it.\n\nSigned-off-by: Petr Baudis <pasky@suse.cz>\n---\n\n git-remote.perl |    5 +----\n perl/Git.pm     |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 55 insertions(+), 5 deletions(-)\n\ndiff --git a/git-remote.perl b/git-remote.perl\nindex 5763799..5403d86 100755\n--- a/git-remote.perl\n+++ b/git-remote.perl\n@@ -128,10 +128,7 @@ sub update_ls_remote {\n \treturn if (($harder == 0) ||\n \t\t   (($harder == 1) && exists $info->{'LS_REMOTE'}));\n \n-\tmy @ref = map {\n-\t\ts|^[0-9a-f]{40}\\s+refs/heads/||;\n-\t\t$_;\n-\t} $git->command(qw(ls-remote --heads), $info->{'URL'});\n+\tmy @ref = keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};\n \t$info->{'LS_REMOTE'} = \\@ref;\n }\n \ndiff --git a/perl/Git.pm b/perl/Git.pm\nindex 8fd3611..9818981 100644\n--- a/perl/Git.pm\n+++ b/perl/Git.pm\n@@ -51,7 +51,7 @@ require Exporter;\n # Methods which can be called as standalone functions as well:\n @EXPORT_OK = qw(command command_oneline command_noisy\n                 command_output_pipe command_input_pipe command_close_pipe\n-                version exec_path hash_object git_cmd_try);\n+                version exec_path hash_object git_cmd_try remote_refs);\n \n \n =head1 DESCRIPTION\n@@ -550,6 +550,59 @@ sub config_bool {\n }\n \n \n+=item remote_refs ( REPOSITORY [, GROUPS [, REFGLOBS ] ] )\n+\n+This function returns a hashref of refs stored in a given remote repository.\n+The hash is in the format C<refname =\\> hash>. For tags, the C<refname> entry\n+contains the tag object while a C<refname^{}> entry gives the tagged objects.\n+\n+C<REPOSITORY> has the same meaning as the appropriate C<git-ls-remote>\n+argument; either an URL or a remote name (if called on a repository instance).\n+C<GROUPS> is an optional arrayref that can contain 'tags' to return all the\n+tags and/or 'heads' to return all the heads. C<REFGLOB> is an optional array\n+of strings containing a shell-like glob to further limit the refs returned in\n+the hash; the meaning is again the same as the appropriate C<git-ls-remote>\n+argument.\n+\n+This function may or may not be called on a repository instance. In the former\n+case, remote names as defined in the repository are recognized as repository\n+specifiers.\n+\n+=cut\n+\n+sub remote_refs {\n+\tmy ($self, $repo, $groups, $refglobs) = _maybe_self(@_);\n+\tmy @args;\n+\tif (ref $groups eq 'ARRAY') {\n+\t\tforeach (@$groups) {\n+\t\t\tif ($_ eq 'heads') {\n+\t\t\t\tpush (@args, '--heads');\n+\t\t\t} elsif ($_ eq 'tags') {\n+\t\t\t\tpush (@args, '--tags');\n+\t\t\t} else {\n+\t\t\t\t# Ignore unknown groups for future\n+\t\t\t\t# compatibility\n+\t\t\t}\n+\t\t}\n+\t}\n+\tpush (@args, $repo);\n+\tif (ref $refglobs eq 'ARRAY') {\n+\t\tpush (@args, @$refglobs);\n+\t}\n+\n+\tmy @self = $self ? ($self) : (); # Ultra trickery\n+\tmy ($fh, $ctx) = Git::command_output_pipe(@self, 'ls-remote', @args);\n+\tmy %refs;\n+\twhile (<$fh>) {\n+\t\tchomp;\n+\t\tmy ($hash, $ref) = split(/\\t/, $_, 2);\n+\t\t$refs{$ref} = $hash;\n+\t}\n+\tGit::command_close_pipe(@self, $fh, $ctx);\n+\treturn \\%refs;\n+}\n+\n+\n =item ident ( TYPE | IDENTSTR )\n \n =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )\n"},{"id":"42380","messageId":"7vk5v89ek8.fsf@assigned-by-dhcp.cox.net","threadId":"8188","inReplyTo":"20070517023743.1982.41240.stgit@rover","subject":"Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-17T05:58:31Z","receivedAt":"2007-05-17T05:58:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Baudis <pasky@suse.cz> writes:\n\n> .... Too bad that\n>\n> \tgit-ls-remote --heads .\n> \t\n> is subtly different from\n>\n> \tgit-ls-remote . refs/heads/\n>\n> so we have to provide the interface for specifying both.\n\nI've already heard you say the above elsewhere, but I am not\nsure what you exactly mean here.  Mind substantiating it a bit\nmore clearly?\n\nI think \"ls-remote --heads .\" is just a special case of giving\n\"refs/heads/*\" as the glob pattern:\n\n        $ git ls-remote --heads . | head -n 3\n        3545193735522f733fdb4e345f16ddf131e2007a\trefs/heads/ap/ident\n        b7993dd57a9cfd5b989f0e2cc5d271a524339318\trefs/heads/db/remote\n        960ccca6803c9fb57429d43572a9545a96107e32\trefs/heads/dh/pack\n\n\t$ git ls-remote . refs/heads/ | wc -l\n        0\n\n\t$ git ls-remote . \"refs/heads/*\" | head -n 3\n        3545193735522f733fdb4e345f16ddf131e2007a\trefs/heads/ap/ident\n        b7993dd57a9cfd5b989f0e2cc5d271a524339318\trefs/heads/db/remote\n        960ccca6803c9fb57429d43572a9545a96107e32\trefs/heads/dh/pack\n\n\t$ git ls-remote . \"refs/heads/???/*\"\n        7841ce79854868eaaa146c1d018b17fc4f3320be\trefs/heads/mst/connect\n\n        $ git ls-remote . \"refs/*/jc/*\" | head -n 4\n        80a767ba3b1c69fc41fa5f5fbe4a247757a9c575\trefs/heads/jc/blame\n        a1481ab7b16c51d4ec7925fd9b38d9cf21f72263\trefs/heads/jc/diff\n        4e8daa0dca5deb9d391538241939a2a2ad6d36b8\trefs/tags/hold/jc/3way\n        ff77ab7919e6f31cb6c58bc004217e624b553fb6\trefs/tags/hold/jc/changes\n\nSo if you really do not want separate interfaces, I think you\ncould just implement --heads as what it is: a shorthand for\n\"refs/heads/*\".\n"},{"id":"42388","messageId":"20070517113028.GN4489@pasky.or.cz","threadId":"8188","inReplyTo":"7vk5v89ek8.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Git.pm: Add remote_refs() git-ls-remote frontend","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2007-05-17T11:30:28Z","receivedAt":"2007-05-17T11:30:28Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"On Thu, May 17, 2007 at 07:58:31AM CEST, Junio C Hamano wrote:\n> Petr Baudis <pasky@suse.cz> writes:\n> \n> > .... Too bad that\n> >\n> > \tgit-ls-remote --heads .\n> > \t\n> > is subtly different from\n> >\n> > \tgit-ls-remote . refs/heads/\n> >\n> > so we have to provide the interface for specifying both.\n> \n> I've already heard you say the above elsewhere, but I am not\n> sure what you exactly mean here.  Mind substantiating it a bit\n> more clearly?\n\nBecause the arguments are matched like\n\n\tcase \"/$path\" in\n\t*/$pat )\n\nso if you have remote \"refs\" and refs/remote/refs/heads/x, git-ls-remote\nrefs/heads/ is ambiguous. OTOH, --heads always match start of the path.\n\nIt's somewhat obscure and probably doesn't really matter for user\ninterface, but API should be free even of obscure misbehaviour, I\nbelieve.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nEver try. Ever fail. No matter. // Try again. Fail again. Fail better.\n\t\t-- Samuel Beckett\n"}]}