From 756bbf548dbef5b738c50ce6517f5c63ab929373 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:42 +0000 Subject: [PATCH 1/8] gitweb: Add parse_commits, used to bulk load commit objects. Add a new method parse_commits which is able to parse multiple commit objects at once. Reworked parse_commit to share the commit object parsing logic. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 91 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 17 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d01d68934..6bd57a4e3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1270,25 +1270,13 @@ sub parse_tag { return %tag } -sub parse_commit { - my $commit_id = shift; - my $commit_text = shift; - - my @commit_lines; +sub parse_commit_text { + my ($commit_text) = @_; + my @commit_lines = split '\n', $commit_text; my %co; - if (defined $commit_text) { - @commit_lines = @$commit_text; - } else { - local $/ = "\0"; - open my $fd, "-|", git_cmd(), "rev-list", - "--header", "--parents", "--max-count=1", - $commit_id, "--" - or return; - @commit_lines = split '\n', <$fd>; - close $fd or return; - pop @commit_lines; - } + pop @commit_lines; # Remove '\0' + my $header = shift @commit_lines; if (!($header =~ m/^[0-9a-fA-F]{40}/)) { return; @@ -1375,6 +1363,75 @@ sub parse_commit { return %co; } +sub parse_commit { + my ($commit_id) = @_; + my %co; + + local $/ = "\0"; + + open my $fd, "-|", git_cmd(), "rev-list", + "--header", + "--parents", + "--max-count=1", + $commit_id, + "--", + or die_error(undef, "Open git-rev-list failed"); + %co = parse_commit_text(<$fd>); + close $fd; + + return %co; +} + +sub parse_commits { + my ($commit_id, $maxcount, $skip, $arg, $filename) = @_; + my @cos; + + $maxcount ||= 1; + $skip ||= 0; + + # Delete once rev-list supports the --skip option + if ($skip > 0) { + open my $fd, "-|", git_cmd(), "rev-list", + ($arg ? ($arg) : ()), + ("--max-count=" . ($maxcount + $skip)), + $commit_id, + "--", + ($filename ? ($filename) : ()) + or die_error(undef, "Open git-rev-list failed"); + while (my $line = <$fd>) { + if ($skip-- <= 0) { + chomp $line; + my %co = parse_commit($line); + push @cos, \%co; + } + } + close $fd; + + return wantarray ? @cos : \@cos; + } + + local $/ = "\0"; + + open my $fd, "-|", git_cmd(), "rev-list", + "--header", + "--parents", + ($arg ? ($arg) : ()), + ("--max-count=" . $maxcount), + # Add once rev-list supports the --skip option + # ("--skip=" . $skip), + $commit_id, + "--", + ($filename ? ($filename) : ()) + or die_error(undef, "Open git-rev-list failed"); + while (my $line = <$fd>) { + my %co = parse_commit_text($line); + push @cos, \%co; + } + close $fd; + + return wantarray ? @cos : \@cos; +} + # parse ref from ref_file, given by ref_id, with given type sub parse_ref { my $ref_file = shift; From 208b2dff95bb48682c351099023a1cbb0e1edf26 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:43 +0000 Subject: [PATCH 2/8] gitweb: We do longer need the --parents flag in rev-list. We only want to know the direct parents of a given commit object, these parents are available in the --header output of rev-list. If --parents is supplied with --full-history the output includes merge commits that aren't relevant. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6bd57a4e3..c645686a7 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1281,13 +1281,14 @@ sub parse_commit_text { if (!($header =~ m/^[0-9a-fA-F]{40}/)) { return; } - ($co{'id'}, my @parents) = split ' ', $header; - $co{'parents'} = \@parents; - $co{'parent'} = $parents[0]; + $co{'id'} = $header; + my @parents; while (my $line = shift @commit_lines) { last if $line eq "\n"; if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) { $co{'tree'} = $1; + } elsif ($line =~ m/^parent ([0-9a-fA-F]{40})$/) { + push @parents, $1; } elsif ($line =~ m/^author (.*) ([0-9]+) (.*)$/) { $co{'author'} = $1; $co{'author_epoch'} = $2; @@ -1314,6 +1315,8 @@ sub parse_commit_text { if (!defined $co{'tree'}) { return; }; + $co{'parents'} = \@parents; + $co{'parent'} = $parents[0]; foreach my $title (@commit_lines) { $title =~ s/^ //; @@ -1371,7 +1374,6 @@ sub parse_commit { open my $fd, "-|", git_cmd(), "rev-list", "--header", - "--parents", "--max-count=1", $commit_id, "--", @@ -1414,7 +1416,6 @@ sub parse_commits { open my $fd, "-|", git_cmd(), "rev-list", "--header", - "--parents", ($arg ? ($arg) : ()), ("--max-count=" . $maxcount), # Add once rev-list supports the --skip option From 190d7fdcf325bb444fa806f09ebbb403a4ae4ee6 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:44 +0000 Subject: [PATCH 3/8] gitweb: Change summary, shortlog actions to use parse_commits. Also added missing accesskey. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c645686a7..5f1ace98a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2704,20 +2704,19 @@ sub git_project_list_body { sub git_shortlog_body { # uses global variable $project - my ($revlist, $from, $to, $refs, $extra) = @_; + my ($commitlist, $from, $to, $refs, $extra) = @_; my $have_snapshot = gitweb_have_snapshot(); $from = 0 unless defined $from; - $to = $#{$revlist} if (!defined $to || $#{$revlist} < $to); + $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to); print "\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { - my $commit = $revlist->[$i]; - #my $ref = defined $refs ? format_ref_marker($refs, $commit) : ''; + my %co = %{$commitlist->[$i]}; + my $commit = $co{'id'}; my $ref = format_ref_marker($refs, $commit); - my %co = parse_commit($commit); if ($alternate) { print "\n"; } else { @@ -3081,14 +3080,10 @@ sub git_summary { # we need to request one more than 16 (0..15) to check if # those 16 are all - open my $fd, "-|", git_cmd(), "rev-list", "--max-count=17", - $head, "--" - or die_error(undef, "Open git-rev-list failed"); - my @revlist = map { chomp; $_ } <$fd>; - close $fd; + my @commitlist = parse_commits($head, 17); git_print_header_div('shortlog'); - git_shortlog_body(\@revlist, 0, 15, $refs, - $#revlist <= 15 ? undef : + git_shortlog_body(\@commitlist, 0, 15, $refs, + $#commitlist <= 15 ? undef : $cgi->a({-href => href(action=>"shortlog")}, "...")); if (@taglist) { @@ -4456,26 +4451,21 @@ sub git_shortlog { } my $refs = git_get_references(); - my $limit = sprintf("--max-count=%i", (100 * ($page+1))); - open my $fd, "-|", git_cmd(), "rev-list", $limit, $hash, "--" - or die_error(undef, "Open git-rev-list failed"); - my @revlist = map { chomp; $_ } <$fd>; - close $fd; + my @commitlist = parse_commits($head, 101, (100 * $page)); - my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, $#revlist); + my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, (100 * ($page+1))); my $next_link = ''; - if ($#revlist >= (100 * ($page+1)-1)) { + if ($#commitlist >= 100) { $next_link = $cgi->a({-href => href(action=>"shortlog", hash=>$hash, page=>$page+1), - -title => "Alt-n"}, "next"); + -accesskey => "n", -title => "Alt-n"}, "next"); } - git_header_html(); git_print_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav); git_print_header_div('summary', $project); - git_shortlog_body(\@revlist, ($page * 100), $#revlist, $refs, $next_link); + git_shortlog_body(\@commitlist, 0, 99, $refs, $next_link); git_footer_html(); } From 719dad28c599dc2e2917c3cb0e44152fd92bf133 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:45 +0000 Subject: [PATCH 4/8] gitweb: Change log action to use parse_commits. Also add missing next link to bottom of page. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5f1ace98a..42b744925 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3645,28 +3645,25 @@ sub git_log { } my $refs = git_get_references(); - my $limit = sprintf("--max-count=%i", (100 * ($page+1))); - open my $fd, "-|", git_cmd(), "rev-list", $limit, $hash, "--" - or die_error(undef, "Open git-rev-list failed"); - my @revlist = map { chomp; $_ } <$fd>; - close $fd; + my @commitlist = parse_commits($hash, 101, (100 * $page)); - my $paging_nav = format_paging_nav('log', $hash, $head, $page, $#revlist); + my $paging_nav = format_paging_nav('log', $hash, $head, $page, (100 * ($page+1))); git_header_html(); git_print_page_nav('log','', $hash,undef,undef, $paging_nav); - if (!@revlist) { + if (!@commitlist) { my %co = parse_commit($hash); git_print_header_div('summary', $project); print "
Last change $co{'age_string'}.

\n"; } - for (my $i = ($page * 100); $i <= $#revlist; $i++) { - my $commit = $revlist[$i]; - my $ref = format_ref_marker($refs, $commit); - my %co = parse_commit($commit); + my $to = ($#commitlist >= 99) ? (99) : ($#commitlist); + for (my $i = 0; $i <= $to; $i++) { + my %co = %{$commitlist[$i]}; next if !%co; + my $commit = $co{'id'}; + my $ref = format_ref_marker($refs, $commit); my %ad = parse_date($co{'author_epoch'}); git_print_header_div('commit', "$co{'age_string'}" . @@ -3688,6 +3685,12 @@ sub git_log { git_print_log($co{'comment'}, -final_empty_line=> 1); print "\n"; } + if ($#commitlist >= 100) { + print "
\n"; + print $cgi->a({-href => href(action=>"log", hash=>$hash, page=>$page+1), + -accesskey => "n", -title => "Alt-n"}, "next"); + print "
\n"; + } git_footer_html(); } From 5ad66088d1166bf91cf2890682f4582049756539 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:46 +0000 Subject: [PATCH 5/8] gitweb: Change header search action to use parse_commits. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 42b744925..53dd2251d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2910,18 +2910,18 @@ sub git_heads_body { } sub git_search_grep_body { - my ($greplist, $from, $to, $extra) = @_; + my ($commitlist, $from, $to, $extra) = @_; $from = 0 unless defined $from; - $to = $#{$greplist} if (!defined $to || $#{$greplist} < $to); + $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to); print "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { - my $commit = $greplist->[$i]; - my %co = parse_commit($commit); + my %co = %{$commitlist->[$i]}; if (!%co) { next; } + my $commit = $co{'id'}; if ($alternate) { print "\n"; } else { @@ -4307,13 +4307,8 @@ sub git_search { } elsif ($searchtype eq 'committer') { $greptype = "--committer="; } - open my $fd, "-|", git_cmd(), "rev-list", - ("--max-count=" . (100 * ($page+1))), - ($greptype . $searchtext), - $hash, "--" - or next; - my @revlist = map { chomp; $_ } <$fd>; - close $fd; + $greptype .= $searchtext; + my @commitlist = parse_commits($hash, 101, (100 * $page), $greptype); my $paging_nav = ''; if ($page > 0) { @@ -4330,7 +4325,7 @@ sub git_search { $paging_nav .= "first"; $paging_nav .= " ⋅ prev"; } - if ($#revlist >= (100 * ($page+1)-1)) { + if ($#commitlist >= 100) { $paging_nav .= " ⋅ " . $cgi->a({-href => href(action=>"search", hash=>$hash, searchtext=>$searchtext, searchtype=>$searchtype, @@ -4340,7 +4335,7 @@ sub git_search { $paging_nav .= " ⋅ next"; } my $next_link = ''; - if ($#revlist >= (100 * ($page+1)-1)) { + if ($#commitlist >= 100) { $next_link = $cgi->a({-href => href(action=>"search", hash=>$hash, searchtext=>$searchtext, searchtype=>$searchtype, @@ -4350,7 +4345,7 @@ sub git_search { git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav); git_print_header_div('commit', esc_html($co{'title'}), $hash); - git_search_grep_body(\@revlist, ($page * 100), $#revlist, $next_link); + git_search_grep_body(\@commitlist, 0, 99, $next_link); } if ($searchtype eq 'pickaxe') { From b6093a5c02f6dd16dadcc0e9caa1e0e76216f929 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:47 +0000 Subject: [PATCH 6/8] gitweb: Change atom, rss actions to use parse_commits. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 53dd2251d..f752a6f60 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4483,11 +4483,7 @@ sub git_feed { # log/feed of current (HEAD) branch, log of given branch, history of file/directory my $head = $hash || 'HEAD'; - open my $fd, "-|", git_cmd(), "rev-list", "--max-count=150", - $head, "--", (defined $file_name ? $file_name : ()) - or die_error(undef, "Open git-rev-list failed"); - my @revlist = map { chomp; $_ } <$fd>; - close $fd or die_error(undef, "Reading git-rev-list failed"); + my @commitlist = parse_commits($head, 150); my %latest_commit; my %latest_date; @@ -4497,8 +4493,8 @@ sub git_feed { # browser (feed reader) prefers text/xml $content_type = 'text/xml'; } - if (defined($revlist[0])) { - %latest_commit = parse_commit($revlist[0]); + if (defined($commitlist[0])) { + %latest_commit = %{$commitlist[0]}; %latest_date = parse_date($latest_commit{'author_epoch'}); print $cgi->header( -type => $content_type, @@ -4588,9 +4584,9 @@ sub git_feed { } # contents - for (my $i = 0; $i <= $#revlist; $i++) { - my $commit = $revlist[$i]; - my %co = parse_commit($commit); + for (my $i = 0; $i <= $#commitlist; $i++) { + my %co = %{$commitlist[$i]}; + my $commit = $co{'id'}; # we read 150, we always show 30 and the ones more recent than 48 hours if (($i >= 20) && ((time - $co{'author_epoch'}) > 48*60*60)) { last; @@ -4598,7 +4594,7 @@ sub git_feed { my %cd = parse_date($co{'author_epoch'}); # get list of changed files - open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, + open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, $co{'parent'}, $co{'id'}, "--", (defined $file_name ? $file_name : ()) or next; my @difftree = map { chomp; $_ } <$fd>; From a8b983bfea9daa255fd32dfc6b39e809733e4c5a Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:48 +0000 Subject: [PATCH 7/8] gitweb: Change history action to use parse_commits. Also added missing accesskey. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f752a6f60..f9994d941 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2750,23 +2750,19 @@ sub git_shortlog_body { sub git_history_body { # Warning: assumes constant type (blob or tree) during history - my ($revlist, $from, $to, $refs, $hash_base, $ftype, $extra) = @_; + my ($commitlist, $from, $to, $refs, $hash_base, $ftype, $extra) = @_; $from = 0 unless defined $from; - $to = $#{$revlist} unless (defined $to && $to <= $#{$revlist}); + $to = $#{$commitlist} unless (defined $to && $to <= $#{$commitlist}); print "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { - if ($revlist->[$i] !~ m/^([0-9a-fA-F]{40})/) { - next; - } - - my $commit = $1; - my %co = parse_commit($commit); + my %co = %{$commitlist->[$i]}; if (!%co) { next; } + my $commit = $co{'id'}; my $ref = format_ref_marker($refs, $commit); @@ -4219,12 +4215,7 @@ sub git_history { $ftype = git_get_type($hash); } - open my $fd, "-|", - git_cmd(), "rev-list", $limit, "--full-history", $hash_base, "--", $file_name - or die_error(undef, "Open git-rev-list-failed"); - my @revlist = map { chomp; $_ } <$fd>; - close $fd - or die_error(undef, "Reading git-rev-list failed"); + my @commitlist = parse_commits($hash_base, 101, (100 * $page), "--full-history", $file_name); my $paging_nav = ''; if ($page > 0) { @@ -4240,7 +4231,7 @@ sub git_history { $paging_nav .= "first"; $paging_nav .= " ⋅ prev"; } - if ($#revlist >= (100 * ($page+1)-1)) { + if ($#commitlist >= 100) { $paging_nav .= " ⋅ " . $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name, page=>$page+1), @@ -4249,11 +4240,11 @@ sub git_history { $paging_nav .= " ⋅ next"; } my $next_link = ''; - if ($#revlist >= (100 * ($page+1)-1)) { + if ($#commitlist >= 100) { $next_link = $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name, page=>$page+1), - -title => "Alt-n"}, "next"); + -accesskey => "n", -title => "Alt-n"}, "next"); } git_header_html(); @@ -4261,7 +4252,7 @@ sub git_history { git_print_header_div('commit', esc_html($co{'title'}), $hash_base); git_print_page_path($file_name, $ftype, $hash_base); - git_history_body(\@revlist, ($page * 100), $#revlist, + git_history_body(\@commitlist, 0, 99, $refs, $hash_base, $ftype, $next_link); git_footer_html(); From f47efbb7ab735fc49d8d93f9ed1c087c5da09c23 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sun, 24 Dec 2006 14:31:49 +0000 Subject: [PATCH 8/8] gitweb: Use rev-list --skip option. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f9994d941..65fcdb0f2 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1391,35 +1391,13 @@ sub parse_commits { $maxcount ||= 1; $skip ||= 0; - # Delete once rev-list supports the --skip option - if ($skip > 0) { - open my $fd, "-|", git_cmd(), "rev-list", - ($arg ? ($arg) : ()), - ("--max-count=" . ($maxcount + $skip)), - $commit_id, - "--", - ($filename ? ($filename) : ()) - or die_error(undef, "Open git-rev-list failed"); - while (my $line = <$fd>) { - if ($skip-- <= 0) { - chomp $line; - my %co = parse_commit($line); - push @cos, \%co; - } - } - close $fd; - - return wantarray ? @cos : \@cos; - } - local $/ = "\0"; open my $fd, "-|", git_cmd(), "rev-list", "--header", ($arg ? ($arg) : ()), ("--max-count=" . $maxcount), - # Add once rev-list supports the --skip option - # ("--skip=" . $skip), + ("--skip=" . $skip), $commit_id, "--", ($filename ? ($filename) : ())