From 63e02a1be308aa57f3cabd7e951a94ac3b7aeb51 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 15 Oct 2006 03:29:09 -0700 Subject: gitweb: use for-each-ref to show the latest activity across branches The project list page shows last change from the HEAD branch but often people would want to view activity on any branch. Unfortunately that is fairly expensive without the core-side support. for-each-ref was invented exactly for that. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e4ebce6224..e119e33423 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1009,6 +1009,24 @@ sub parse_tag { return %tag } +sub git_get_last_activity { + my ($path) = @_; + my $fd; + + $git_dir = "$projectroot/$path"; + open($fd, "-|", git_cmd(), 'for-each-ref', + '--format=%(refname) %(committer)', + '--sort=-committerdate', + 'refs/heads') or return; + my $most_recent = <$fd>; + close $fd or return; + if ($most_recent =~ / (\d+) [-+][01]\d\d\d$/) { + my $timestamp = $1; + my $age = time - $timestamp; + return ($age, age_string($age)); + } +} + sub parse_commit { my $commit_id = shift; my $commit_text = shift; @@ -2258,16 +2276,11 @@ sub git_project_list { die_error(undef, "No projects found"); } foreach my $pr (@list) { - my $head = git_get_head_hash($pr->{'path'}); - if (!defined $head) { - next; - } - $git_dir = "$projectroot/$pr->{'path'}"; - my %co = parse_commit($head); - if (!%co) { + my (@aa) = git_get_last_activity($pr->{'path'}); + unless (@aa) { next; } - $pr->{'commit'} = \%co; + ($pr->{'age'}, $pr->{'age_string'}) = @aa; if (!defined $pr->{'descr'}) { my $descr = git_get_project_description($pr->{'path'}) || ""; $pr->{'descr'} = chop_str($descr, 25, 5); @@ -2317,7 +2330,7 @@ sub git_project_list { "\n"; } if ($order eq "age") { - @projects = sort {$a->{'commit'}{'age'} <=> $b->{'commit'}{'age'}} @projects; + @projects = sort {$a->{'age'} <=> $b->{'age'}} @projects; print "Last Change\n"; } else { print "" . @@ -2339,8 +2352,8 @@ sub git_project_list { -class => "list"}, esc_html($pr->{'path'})) . "\n" . "" . esc_html($pr->{'descr'}) . "\n" . "" . chop_str($pr->{'owner'}, 15) . "\n"; - print "{'commit'}{'age'}) . "\">" . - $pr->{'commit'}{'age_string'} . "\n" . + print "{'age'}) . "\">" . + $pr->{'age_string'} . "\n" . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " . -- cgit v1.2.3 From 4777b0141a4812177390da4b6ebc9d40ac3da4b5 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 24 Oct 2006 05:36:10 +0200 Subject: gitweb: Restore object-named links in item lists This restores the redundant links removed earlier. It supersedes my patch to stick slashes to tree entries. Sorry about the previous version of the patch, an unrelated snapshot link addition to tree entries slipped through (and it it didn't even compile); I've dropped the idea of snapshot links in tree entries in the meantime anyway. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 65d0a145e4..5aed661850 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1789,16 +1789,18 @@ sub git_print_tree_entry { file_name=>"$basedir$t->{'name'}", %base_key), -class => "list"}, esc_html($t->{'name'})) . "\n"; print ""; + print $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'}, + file_name=>"$basedir$t->{'name'}", %base_key)}, + "blob"); if ($have_blame) { - print $cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'}, + print " | " . + $cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}", %base_key)}, "blame"); } if (defined $hash_base) { - if ($have_blame) { - print " | "; - } - print $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, + print " | " . + $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}")}, "history"); } @@ -1815,8 +1817,12 @@ sub git_print_tree_entry { esc_html($t->{'name'})); print "\n"; print ""; + print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, + file_name=>"$basedir$t->{'name'}", %base_key)}, + "tree"); if (defined $hash_base) { - print $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, + print " | " . + $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, file_name=>"$basedir$t->{'name'}")}, "history"); } @@ -1899,6 +1905,9 @@ sub git_difftree_body { print $cgi->a({-href => "#patch$patchno"}, "patch"); print " | "; } + print $cgi->a({-href => href(action=>"blob", hash=>$diff{'from_id'}, + hash_base=>$parent, file_name=>$diff{'file'})}, + "blob") . " | "; print $cgi->a({-href => href(action=>"blame", hash_base=>$parent, file_name=>$diff{'file'})}, "blame") . " | "; @@ -1944,6 +1953,9 @@ sub git_difftree_body { } print " | "; } + print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, + hash_base=>$hash, file_name=>$diff{'file'})}, + "blob") . " | "; print $cgi->a({-href => href(action=>"blame", hash_base=>$hash, file_name=>$diff{'file'})}, "blame") . " | "; @@ -1984,6 +1996,9 @@ sub git_difftree_body { } print " | "; } + print $cgi->a({-href => href(action=>"blob", hash=>$diff{'from_id'}, + hash_base=>$parent, file_name=>$diff{'from_file'})}, + "blob") . " | "; print $cgi->a({-href => href(action=>"blame", hash_base=>$parent, file_name=>$diff{'from_file'})}, "blame") . " | "; @@ -2151,6 +2166,7 @@ sub git_shortlog_body { href(action=>"commit", hash=>$commit), $ref); print "\n" . "" . + $cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") . " | " . $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") . " | " . $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree"); if (gitweb_have_snapshot()) { -- cgit v1.2.3 From 88ad729b73264025d2d4c187ff74432d7cacafb2 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 24 Oct 2006 05:15:46 +0200 Subject: gitweb: Make search type a popup menu This makes the multiple search types actually usable by the user; if you don't read the gitweb source, you don't even have an idea that you can write things like that there. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 2 ++ gitweb/gitweb.perl | 61 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 16 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 3f62b6d752..0eda98237e 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -333,6 +333,8 @@ div.index_include { } div.search { + font-size: 12px; + font-weight: normal; margin: 4px 8px; position: absolute; top: 56px; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5aed661850..e93a211e7f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -342,6 +342,13 @@ if (defined $searchtext) { $searchtext = quotemeta $searchtext; } +our $searchtype = $cgi->param('st'); +if (defined $searchtype) { + if ($searchtype =~ m/[^a-z]/) { + die_error(undef, "Invalid searchtype parameter"); + } +} + # now read PATH_INFO and use it as alternative to parameters sub evaluate_path_info { return if defined $project; @@ -406,6 +413,7 @@ my %actions = ( "log" => \&git_log, "rss" => \&git_rss, "search" => \&git_search, + "search_help" => \&git_search_help, "shortlog" => \&git_shortlog, "summary" => \&git_summary, "tag" => \&git_tag, @@ -455,6 +463,7 @@ sub href(%) { page => "pg", order => "o", searchtext => "s", + searchtype => "st", ); my %mapping = @mapping; @@ -1524,6 +1533,10 @@ EOF $cgi->hidden(-name => "p") . "\n" . $cgi->hidden(-name => "a") . "\n" . $cgi->hidden(-name => "h") . "\n" . + $cgi->popup_menu(-name => 'st', -default => 'commit', + -values => ['commit', 'author', 'committer', 'pickaxe']) . + $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) . + " search:\n", $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . "" . $cgi->end_form() . "\n"; @@ -3544,18 +3557,8 @@ sub git_search { die_error(undef, "Unknown commit object"); } - my $commit_search = 1; - my $author_search = 0; - my $committer_search = 0; - my $pickaxe_search = 0; - if ($searchtext =~ s/^author\\://i) { - $author_search = 1; - } elsif ($searchtext =~ s/^committer\\://i) { - $committer_search = 1; - } elsif ($searchtext =~ s/^pickaxe\\://i) { - $commit_search = 0; - $pickaxe_search = 1; - + $searchtype ||= 'commit'; + if ($searchtype eq 'pickaxe') { # pickaxe may take all resources of your box and run for several minutes # with every query - so decide by yourself how public you make this feature my ($have_pickaxe) = gitweb_check_feature('pickaxe'); @@ -3563,23 +3566,24 @@ sub git_search { die_error('403 Permission denied', "Permission denied"); } } + git_header_html(); git_print_page_nav('','', $hash,$co{'tree'},$hash); git_print_header_div('commit', esc_html($co{'title'}), $hash); print "\n"; my $alternate = 1; - if ($commit_search) { + if ($searchtype eq 'commit' or $searchtype eq 'author' or $searchtype eq 'committer') { $/ = "\0"; open my $fd, "-|", git_cmd(), "rev-list", "--header", "--parents", $hash or next; while (my $commit_text = <$fd>) { if (!grep m/$searchtext/i, $commit_text) { next; } - if ($author_search && !grep m/\nauthor .*$searchtext/i, $commit_text) { + if ($searchtype eq 'author' && !grep m/\nauthor .*$searchtext/i, $commit_text) { next; } - if ($committer_search && !grep m/\ncommitter .*$searchtext/i, $commit_text) { + if ($searchtype eq 'committer' && !grep m/\ncommitter .*$searchtext/i, $commit_text) { next; } my @commit_lines = split "\n", $commit_text; @@ -3621,7 +3625,7 @@ sub git_search { close $fd; } - if ($pickaxe_search) { + if ($searchtype eq 'pickaxe') { $/ = "\n"; my $git_command = git_cmd_str(); open my $fd, "-|", "$git_command rev-list $hash | " . @@ -3681,6 +3685,31 @@ sub git_search { git_footer_html(); } +sub git_search_help { + git_header_html(); + git_print_page_nav('','', $hash,$hash,$hash); + print < +
commit
+
The commit messages and authorship information will be scanned for the given string.
+
author
+
Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.
+
committer
+
Name and e-mail of the committer and date of commit will be scanned for the given string.
+EOT + my ($have_pickaxe) = gitweb_check_feature('pickaxe'); + if ($have_pickaxe) { + print <pickaxe +
All commits that caused the string to appear or disappear from any file (changes that +added, removed or "modified" the string) will be listed. This search can take a while and +takes a lot of strain on the server, so please use it wisely.
+EOT + } + print "\n"; + git_footer_html(); +} + sub git_shortlog { my $head = git_get_head_hash($project); if (!defined $hash) { -- cgit v1.2.3 From 8be2890c994102d5748342f44bd6353bd482b58b Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 24 Oct 2006 05:18:39 +0200 Subject: gitweb: Do not automatically append " git" to custom site name If you customized the site name, you probably do not want the " git" appended so that the page title is not bastardized; I want repo.or.cz pages titled "Public Git Hosting", not "Public Git Hosting git" (what's hosting what?). This slightly changes the $site_name semantics but only very insignificantly. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e93a211e7f..604780650b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -39,7 +39,8 @@ our $home_link_str = "++GITWEB_HOME_LINK_STR++"; # name of your site or organization to appear in page titles # replace this with something more descriptive for clearer bookmarks -our $site_name = "++GITWEB_SITENAME++" || $ENV{'SERVER_NAME'} || "Untitled"; +our $site_name = "++GITWEB_SITENAME++" + || ($ENV{'SERVER_NAME'} || "Untitled") . " Git"; # filename of html text to include at top of each page our $site_header = "++GITWEB_SITE_HEADER++"; @@ -1429,7 +1430,7 @@ sub git_header_html { my $status = shift || "200 OK"; my $expires = shift; - my $title = "$site_name git"; + my $title = "$site_name"; if (defined $project) { $title .= " - $project"; if (defined $action) { @@ -3818,7 +3819,7 @@ sub git_opml { - $site_name Git OPML Export + $site_name OPML Export -- cgit v1.2.3 From 447ef09a5cf98bea28ec5123b968c966afce5772 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 24 Oct 2006 05:23:46 +0200 Subject: gitweb: Show project's README.html if available If the repository includes a README.html file, show it in the summary page. The usual "this should be in the config file" argument does not apply here since this can be larger and having such a big string in the config file would be impractical. I don't know if this is suitable upstream, but it's one of the repo.or.cz custom modifications that I've thought could be interesting for others as well. Compared to the previous patch, this adds the '.html' extension to the filename, so that it's clear it is, well, HTML. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 604780650b..a201043dd3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2530,6 +2530,14 @@ sub git_summary { } print "
\n"; + if (-s "$projectroot/$project/README.html") { + if (open my $fd, "$projectroot/$project/README.html") { + print "
readme
\n"; + print $_ while (<$fd>); + close $fd; + } + } + open my $fd, "-|", git_cmd(), "rev-list", "--max-count=17", git_get_head_hash($project) or die_error(undef, "Open git-rev-list failed"); -- cgit v1.2.3 From f2069411c9b5b5c99756cdfb2e54a61aef5c9f72 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 24 Oct 2006 13:52:46 +0200 Subject: gitweb: Get rid of git_print_simplified_log Replace calls to git_print_simplified_log with its expansion, i.e. with calling git_print_log with appropriate options. Remove no longer used git_print_simplified_log subroutine. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a201043dd3..5f0a134264 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1776,15 +1776,6 @@ sub git_print_log ($;%) { } } -sub git_print_simplified_log { - my $log = shift; - my $remove_title = shift; - - git_print_log($log, - -final_empty_line=> 1, - -remove_title => $remove_title); -} - # print tree entry (row of git_tree), but without encompassing element sub git_print_tree_entry { my ($t, $basedir, $hash_base, $have_blame) = @_; @@ -3101,7 +3092,7 @@ sub git_log { "\n"; print "
\n"; - git_print_simplified_log($co{'comment'}); + git_print_log($co{'comment'}, -final_empty_line=> 1); print "
\n"; } git_footer_html(); @@ -3433,7 +3424,7 @@ sub git_commitdiff { git_print_authorship(\%co); print "
\n"; print "
\n"; - git_print_simplified_log($co{'comment'}, 1); # skip title + git_print_log($co{'comment'}, -final_empty_line=> 1, -remove_title => 1); print "
\n"; # class="log" } elsif ($format eq 'plain') { -- cgit v1.2.3 From 62fae51dd57b36cfbb25c9ade539ea5a6ef5ad84 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 24 Oct 2006 13:54:49 +0200 Subject: gitweb: Filter out commit ID from @difftree in git_commit and git_commitdiff Filter out commit ID output that git-diff-tree adds when called with only one (not only for --stdin) in git_commit and git_commitdiff. This also works with older git versions, which doesn't have --no-commit-id option to git-diff-tree. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5f0a134264..2bc14b2c2a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3115,6 +3115,9 @@ sub git_commit { my @difftree = map { chomp; $_ } <$fd>; close $fd or die_error(undef, "Reading git-diff-tree failed"); + # filter out commit ID output + @difftree = grep(!/^[0-9a-fA-F]{40}$/, @difftree); + # non-textual hash id's can be cached my $expires; if ($hash =~ m/^[0-9a-fA-F]{40}$/) { @@ -3391,7 +3394,9 @@ sub git_commitdiff { while (chomp(my $line = <$fd>)) { # empty line ends raw part of diff-tree output last unless $line; - push @difftree, $line; + # filter out commit ID output + push @difftree, $line + unless $line =~ m/^[0-9a-fA-F]{40}$/; } } elsif ($format eq 'plain') { -- cgit v1.2.3 From 82560983997c961d9deafe0074b787c8484c2e1d Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 24 Oct 2006 13:55:33 +0200 Subject: gitweb: Print commit message without title in commitdiff only if there is any Print the rest of commit message (title, i.e. first line of commit message, is printed separately) only if there is any. In repository which uses signoffs this shouldn't happen, because commit message should consist of at least title and signoff. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 2bc14b2c2a..c82fc6268b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3428,9 +3428,11 @@ sub git_commitdiff { git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash); git_print_authorship(\%co); print "
\n"; - print "
\n"; - git_print_log($co{'comment'}, -final_empty_line=> 1, -remove_title => 1); - print "
\n"; # class="log" + if (@{$co{'comment'}} > 1) { + print "
\n"; + git_print_log($co{'comment'}, -final_empty_line=> 1, -remove_title => 1); + print "
\n"; # class="log" + } } elsif ($format eq 'plain') { my $refs = git_get_references("tags"); -- cgit v1.2.3