Skip to content

Commit 9d0d42f

Browse files
Oblomovgitster
authored andcommitted
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>
1 parent b891d52 commit 9d0d42f

File tree

2 files changed

+152
-20
lines changed

2 files changed

+152
-20
lines changed

gitweb/gitweb.perl

Lines changed: 146 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,6 +2772,44 @@ sub git_get_last_activity {
27722772
return (undef, undef);
27732773
}
27742774

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+
27752813
sub git_get_references {
27762814
my $type = shift || "";
27772815
my %refs;
@@ -5051,6 +5089,101 @@ sub git_heads_body {
50515089
print "</table>\n";
50525090
}
50535091

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+
50545187
sub git_search_grep_body {
50555188
my ($commitlist, $from, $to, $extra) = @_;
50565189
$from = 0 unless defined $from;
@@ -5197,7 +5330,7 @@ sub git_summary {
51975330
# there are more ...
51985331
my @taglist = git_get_tags_list(16);
51995332
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() : ();
52015334
my @forklist;
52025335
my $check_forks = gitweb_check_feature('forks');
52035336

@@ -5275,11 +5408,9 @@ sub git_summary {
52755408
$cgi->a({-href => href(action=>"heads")}, "..."));
52765409
}
52775410

5278-
if (@remotelist) {
5411+
if (%remotedata) {
52795412
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);
52835414
}
52845415

52855416
if (@forklist) {
@@ -5596,39 +5727,34 @@ sub git_heads {
55965727
git_footer_html();
55975728
}
55985729

5730+
# used both for single remote view and for list of all the remotes
55995731
sub git_remotes {
56005732
gitweb_check_feature('remote_heads')
56015733
or die_error(403, "Remote heads view is disabled");
56025734

56035735
my $head = git_get_head_hash($project);
56045736
my $remote = $input_params{'hash'};
56055737

5606-
my @remotelist;
5738+
my $remotedata = git_get_remotes_list($remote);
5739+
die_error(500, "Unable to get remote information") unless defined $remotedata;
56075740

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");
56185745
}
56195746

56205747
git_header_html(undef, undef, -action_extra => $remote);
56215748
git_print_page_nav('', '', $head, undef, $head,
56225749
format_ref_views($remote ? '' : 'remotes'));
56235750

5751+
fill_remote_heads($remotedata);
56245752
if (defined $remote) {
56255753
git_print_header_div('remotes', "$remote remote for $project");
5754+
git_remote_block($remote, $remotedata->{$remote}, undef, $head);
56265755
} else {
56275756
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);
56325758
}
56335759

56345760
git_footer_html();

gitweb/static/gitweb.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,12 @@ div.binary {
573573
font-style: italic;
574574
}
575575

576+
div.remote {
577+
margin: .5em;
578+
border: 1px solid #d9d8d1;
579+
display: inline-block;
580+
}
581+
576582
/* Style definition generated by highlight 2.4.5, http://www.andre-simon.de/ */
577583

578584
/* Highlighting theme definition: */

0 commit comments

Comments
 (0)