@matheusbsbs / matheus-bagliano / commits / 9d0d42f345
Fork 0

gitweb: group remote heads by remote

In remote and summary view, display a block for each remote, with the fetch and push URL(s) as well as the list of the remote heads. In summary view, if the number of remotes is higher than a prescribed limit, only display the first <limit> remotes and their fetch and push urls, without any heads information and without grouping. Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com> Acked-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Giuseppe Bilotta committed Nov 11, 2010 at 13:26 UTC 9d0d42f3450fe34737f92b9bde31ac1cf6deeadb
2 files changed +152 -20
gitweb/gitweb.perl
+146 -20
@@ -2772,6 +2772,44 @@ sub git_get_last_activity {
2772 return (undef, undef);
2773 }
2774
2775 +# Implementation note: when a single remote is wanted, we cannot use 'git
2776 +# remote show -n' because that command always work (assuming it's a remote URL
2777 +# if it's not defined), and we cannot use 'git remote show' because that would
2778 +# try to make a network roundtrip. So the only way to find if that particular
2779 +# remote is defined is to walk the list provided by 'git remote -v' and stop if
2780 +# and when we find what we want.
2781 +sub git_get_remotes_list {
2782 + my $wanted = shift;
2783 + my %remotes = ();
2784 +
2785 + open my $fd, '-|' , git_cmd(), 'remote', '-v';
2786 + return unless $fd;
2787 + while (my $remote = <$fd>) {
2788 + chomp $remote;
2789 + $remote =~ s!\t(.*?)\s+\((\w+)\)$!!;
2790 + next if $wanted and not $remote eq $wanted;
2791 + my ($url, $key) = ($1, $2);
2792 +
2793 + $remotes{$remote} ||= { 'heads' => () };
2794 + $remotes{$remote}{$key} = $url;
2795 + }
2796 + close $fd or return;
2797 + return wantarray ? %remotes : \%remotes;
2798 +}
2799 +
2800 +# Takes a hash of remotes as first parameter and fills it by adding the
2801 +# available remote heads for each of the indicated remotes.
2802 +sub fill_remote_heads {
2803 + my $remotes = shift;
2804 + my @heads = map { "remotes/$_" } keys %$remotes;
2805 + my @remoteheads = git_get_heads_list(undef, @heads);
2806 + foreach my $remote (keys %$remotes) {
2807 + $remotes->{$remote}{'heads'} = [ grep {
2808 + $_->{'name'} =~ s!^$remote/!!
2809 + } @remoteheads ];
2810 + }
2811 +}
2812 +
2813 sub git_get_references {
2814 my $type = shift || "";
2815 my %refs;
@@ -5051,6 +5089,101 @@ sub git_heads_body {
5089 print "</table>\n";
5090 }
5091
5092 +# Display a single remote block
5093 +sub git_remote_block {
5094 + my ($remote, $rdata, $limit, $head) = @_;
5095 +
5096 + my $heads = $rdata->{'heads'};
5097 + my $fetch = $rdata->{'fetch'};
5098 + my $push = $rdata->{'push'};
5099 +
5100 + my $urls_table = "<table class=\"projects_list\">\n" ;
5101 +
5102 + if (defined $fetch) {
5103 + if ($fetch eq $push) {
5104 + $urls_table .= format_repo_url("URL", $fetch);
5105 + } else {
5106 + $urls_table .= format_repo_url("Fetch URL", $fetch);
5107 + $urls_table .= format_repo_url("Push URL", $push) if defined $push;
5108 + }
5109 + } elsif (defined $push) {
5110 + $urls_table .= format_repo_url("Push URL", $push);
5111 + } else {
5112 + $urls_table .= format_repo_url("", "No remote URL");
5113 + }
5114 +
5115 + $urls_table .= "</table>\n";
5116 +
5117 + my $dots;
5118 + if (defined $limit && $limit < @$heads) {
5119 + $dots = $cgi->a({-href => href(action=>"remotes", hash=>$remote)}, "...");
5120 + }
5121 +
5122 + print $urls_table;
5123 + git_heads_body($heads, $head, 0, $limit, $dots);
5124 +}
5125 +
5126 +# Display a list of remote names with the respective fetch and push URLs
5127 +sub git_remotes_list {
5128 + my ($remotedata, $limit) = @_;
5129 + print "<table class=\"heads\">\n";
5130 + my $alternate = 1;
5131 + my @remotes = sort keys %$remotedata;
5132 +
5133 + my $limited = $limit && $limit < @remotes;
5134 +
5135 + $#remotes = $limit - 1 if $limited;
5136 +
5137 + while (my $remote = shift @remotes) {
5138 + my $rdata = $remotedata->{$remote};
5139 + my $fetch = $rdata->{'fetch'};
5140 + my $push = $rdata->{'push'};
5141 + if ($alternate) {
5142 + print "<tr class=\"dark\">\n";
5143 + } else {
5144 + print "<tr class=\"light\">\n";
5145 + }
5146 + $alternate ^= 1;
5147 + print "<td>" .
5148 + $cgi->a({-href=> href(action=>'remotes', hash=>$remote),
5149 + -class=> "list name"},esc_html($remote)) .
5150 + "</td>";
5151 + print "<td class=\"link\">" .
5152 + (defined $fetch ? $cgi->a({-href=> $fetch}, "fetch") : "fetch") .
5153 + " | " .
5154 + (defined $push ? $cgi->a({-href=> $push}, "push") : "push") .
5155 + "</td>";
5156 +
5157 + print "</tr>\n";
5158 + }
5159 +
5160 + if ($limited) {
5161 + print "<tr>\n" .
5162 + "<td colspan=\"3\">" .
5163 + $cgi->a({-href => href(action=>"remotes")}, "...") .
5164 + "</td>\n" . "</tr>\n";
5165 + }
5166 +
5167 + print "</table>";
5168 +}
5169 +
5170 +# Display remote heads grouped by remote, unless there are too many
5171 +# remotes, in which case we only display the remote names
5172 +sub git_remotes_body {
5173 + my ($remotedata, $limit, $head) = @_;
5174 + if ($limit and $limit < keys %$remotedata) {
5175 + git_remotes_list($remotedata, $limit);
5176 + } else {
5177 + fill_remote_heads($remotedata);
5178 + while (my ($remote, $rdata) = each %$remotedata) {
5179 + git_print_section({-class=>"remote", -id=>$remote},
5180 + ["remotes", $remote, $remote], sub {
5181 + git_remote_block($remote, $rdata, $limit, $head);
5182 + });
5183 + }
5184 + }
5185 +}
5186 +
5187 sub git_search_grep_body {
5188 my ($commitlist, $from, $to, $extra) = @_;
5189 $from = 0 unless defined $from;
@@ -5197,7 +5330,7 @@ sub git_summary {
5330 # there are more ...
5331 my @taglist = git_get_tags_list(16);
5332 my @headlist = git_get_heads_list(16);
5200 - my @remotelist = $remote_heads ? git_get_heads_list(16, 'remotes') : ();
5333 + my %remotedata = $remote_heads ? git_get_remotes_list() : ();
5334 my @forklist;
5335 my $check_forks = gitweb_check_feature('forks');
5336
@@ -5275,11 +5408,9 @@ sub git_summary {
5408 $cgi->a({-href => href(action=>"heads")}, "..."));
5409 }
5410
5278 - if (@remotelist) {
5411 + if (%remotedata) {
5412 git_print_header_div('remotes');
5280 - git_heads_body(\@remotelist, $head, 0, 15,
5281 - $#remotelist <= 15 ? undef :
5282 - $cgi->a({-href => href(action=>"remotes")}, "..."));
5413 + git_remotes_body(\%remotedata, 15, $head);
5414 }
5415
5416 if (@forklist) {
@@ -5596,6 +5727,7 @@ sub git_heads {
5727 git_footer_html();
5728 }
5729
5730 +# used both for single remote view and for list of all the remotes
5731 sub git_remotes {
5732 gitweb_check_feature('remote_heads')
5733 or die_error(403, "Remote heads view is disabled");
@@ -5603,32 +5735,26 @@ sub git_remotes {
5735 my $head = git_get_head_hash($project);
5736 my $remote = $input_params{'hash'};
5737
5606 - my @remotelist;
5738 + my $remotedata = git_get_remotes_list($remote);
5739 + die_error(500, "Unable to get remote information") unless defined $remotedata;
5740
5608 - if (defined $remote) {
5609 - # only display the heads in a given remote, stripping the
5610 - # remote name which is already visible elsewhere
5611 - @remotelist = map {
5612 - my $ref = $_ ;
5613 - $ref->{'name'} =~ s!^$remote/!!;
5614 - $ref
5615 - } git_get_heads_list(undef, "remotes/$remote");
5616 - } else {
5617 - @remotelist = git_get_heads_list(undef, 'remotes');
5741 + unless (%$remotedata) {
5742 + die_error(404, defined $remote ?
5743 + "Remote $remote not found" :
5744 + "No remotes found");
5745 }
5746
5747 git_header_html(undef, undef, -action_extra => $remote);
5748 git_print_page_nav('', '', $head, undef, $head,
5749 format_ref_views($remote ? '' : 'remotes'));
5750
5751 + fill_remote_heads($remotedata);
5752 if (defined $remote) {
5753 git_print_header_div('remotes', "$remote remote for $project");
5754 + git_remote_block($remote, $remotedata->{$remote}, undef, $head);
5755 } else {
5756 git_print_header_div('summary', "$project remotes");
5628 - }
5629 -
5630 - if (@remotelist) {
5631 - git_heads_body(\@remotelist, $head);
5757 + git_remotes_body($remotedata, undef, $head);
5758 }
5759
5760 git_footer_html();
gitweb/static/gitweb.css
+6
@@ -573,6 +573,12 @@ div.binary {
573 font-style: italic;
574 }
575
576 +div.remote {
577 + margin: .5em;
578 + border: 1px solid #d9d8d1;
579 + display: inline-block;
580 +}
581 +
582 /* Style definition generated by highlight 2.4.5, http://www.andre-simon.de/ */
583
584 /* Highlighting theme definition: */