X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/24b953b17157d1334f2cfc254ebfb11ea55b76624938ec7cab50ed7b7484d9d9..9f0379777eed690c9b9a097ddbfe300d8918dc019707d3395b53bdb7d3aa213b:/gitweb.perl diff --git a/gitweb.perl b/gitweb.perl index f651db1..1a8e256 100755 --- a/gitweb.perl +++ b/gitweb.perl @@ -54,13 +54,16 @@ our $stylesheet; # default is not to define style sheet, but it can be overwritten later undef $stylesheet; -# URI of GIT logo +# URI of GIT logo (72x27 size) our $logo = "++GITWEB_LOGO++"; # URI of GIT favicon, assumed to be image/png type our $favicon = "++GITWEB_FAVICON++"; -our $githelp_url = "http://git.or.cz/"; -our $githelp_label = "git homepage"; +# URI and label (title) of GIT logo link +#our $logo_url = "http://www.kernel.org/pub/software/scm/git/docs/"; +#our $logo_label = "git documentation"; +our $logo_url = "http://git.or.cz/"; +our $logo_label = "git homepage"; # source of projects list our $projects_list = "++GITWEB_LIST++"; @@ -435,6 +438,9 @@ sub href(%) { my %params = @_; my $href = $my_uri; + # XXX: Warning: If you touch this, check the search form for updating, + # too. + my @mapping = ( project => "p", action => "a", @@ -1068,6 +1074,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; @@ -1078,12 +1102,11 @@ sub parse_commit { if (defined $commit_text) { @commit_lines = @$commit_text; } else { - $/ = "\0"; + 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; - $/ = "\n"; pop @commit_lines; } my $header = shift @commit_lines; @@ -1473,11 +1496,9 @@ EOF } print "
\n" . - "" . - "\"git\"" . - "\n"; + $cgi->a({-href => esc_url($logo_url), + -title => $logo_label}, + qq()); print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / "; if (defined $project) { print $cgi->a({-href => href(action=>"summary")}, esc_html($project)); @@ -1498,6 +1519,7 @@ EOF } $cgi->param("a", "search"); $cgi->param("h", $search_hash); + $cgi->param("p", $project); print $cgi->startform(-method => "get", -action => $my_uri) . "
\n" . $cgi->hidden(-name => "p") . "\n" . @@ -1658,17 +1680,16 @@ sub git_print_page_path { my $type = shift; my $hb = shift; - if (!defined $name) { - print "
/
\n"; - } else { + + print "
"; + print $cgi->a({-href => href(action=>"tree", hash_base=>$hb), + -title => 'tree root'}, "[$project]"); + print " / "; + if (defined $name) { my @dirname = split '/', $name; my $basename = pop @dirname; my $fullname = ''; - print "
"; - print $cgi->a({-href => href(action=>"tree", hash_base=>$hb), - -title => 'tree root'}, "[$project]"); - print " / "; foreach my $dir (@dirname) { $fullname .= ($fullname ? '/' : '') . $dir; print $cgi->a({-href => href(action=>"tree", file_name=>$fullname, @@ -1684,11 +1705,12 @@ sub git_print_page_path { print $cgi->a({-href => href(action=>"tree", file_name=>$file_name, hash_base=>$hb), -title => $name}, esc_html($basename)); + print " / "; } else { print esc_html($basename); } - print "
\n"; } + print "
\n"; } # sub git_print_log (\@;%) { @@ -1765,26 +1787,28 @@ sub git_print_tree_entry { if ($t->{'type'} eq "blob") { print "" . $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'}, - file_name=>"$basedir$t->{'name'}", %base_key), - -class => "list"}, esc_html($t->{'name'})) . "\n"; + 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'}, - file_name=>"$basedir$t->{'name'}", %base_key)}, - "blame"); + 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"); } print " | " . $cgi->a({-href => href(action=>"blob_plain", hash_base=>$hash_base, - file_name=>"$basedir$t->{'name'}")}, - "raw"); + file_name=>"$basedir$t->{'name'}")}, + "raw"); print "\n"; } elsif ($t->{'type'} eq "tree") { @@ -1794,8 +1818,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"); } @@ -1852,7 +1880,7 @@ sub git_difftree_body { print ""; print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, hash_base=>$hash, file_name=>$diff{'file'}), - -class => "list"}, esc_html($diff{'file'})); + -class => "list"}, esc_html($diff{'file'})); print "\n"; print "$mode_chng\n"; print ""; @@ -1878,12 +1906,15 @@ 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") . " | "; + file_name=>$diff{'file'})}, + "blame") . " | "; print $cgi->a({-href => href(action=>"history", hash_base=>$parent, - file_name=>$diff{'file'})}, - "history"); + file_name=>$diff{'file'})}, + "history"); print "\n"; } elsif ($diff{'status'} eq "M" || $diff{'status'} eq "T") { # modified, or type changed @@ -1904,8 +1935,8 @@ sub git_difftree_body { } print ""; print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - hash_base=>$hash, file_name=>$diff{'file'}), - -class => "list"}, esc_html($diff{'file'})); + hash_base=>$hash, file_name=>$diff{'file'}), + -class => "list"}, esc_html($diff{'file'})); print "\n"; print "$mode_chnge\n"; print ""; @@ -1916,19 +1947,22 @@ sub git_difftree_body { print $cgi->a({-href => "#patch$patchno"}, "patch"); } else { print $cgi->a({-href => href(action=>"blobdiff", - hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'}, - hash_base=>$hash, hash_parent_base=>$parent, - file_name=>$diff{'file'})}, - "diff"); + hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'}, + hash_base=>$hash, hash_parent_base=>$parent, + file_name=>$diff{'file'})}, + "diff"); } 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") . " | "; + file_name=>$diff{'file'})}, + "blame") . " | "; print $cgi->a({-href => href(action=>"history", hash_base=>$hash, - file_name=>$diff{'file'})}, - "history"); + file_name=>$diff{'file'})}, + "history"); print "\n"; } elsif ($diff{'status'} eq "R" || $diff{'status'} eq "C") { # renamed or copied @@ -1956,19 +1990,22 @@ sub git_difftree_body { print $cgi->a({-href => "#patch$patchno"}, "patch"); } else { print $cgi->a({-href => href(action=>"blobdiff", - hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'}, - hash_base=>$hash, hash_parent_base=>$parent, - file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})}, - "diff"); + hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'}, + hash_base=>$hash, hash_parent_base=>$parent, + file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})}, + "diff"); } 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") . " | "; + file_name=>$diff{'from_file'})}, + "blame") . " | "; print $cgi->a({-href => href(action=>"history", hash_base=>$parent, - file_name=>$diff{'from_file'})}, - "history"); + file_name=>$diff{'from_file'})}, + "history"); print "\n"; } # we should not encounter Unmerged (U) or Unknown (X) status @@ -2130,6 +2167,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()) { @@ -2324,16 +2362,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); @@ -2383,7 +2416,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 "" . @@ -2405,8 +2438,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") . " | " . @@ -2562,7 +2595,7 @@ sub git_blame2 { if ($ftype !~ "blob") { die_error("400 Bad Request", "Object is not a blob"); } - open ($fd, "-|", git_cmd(), "blame", '--porcelain', '--', + open ($fd, "-|", git_cmd(), "blame", '-p', '--', $file_name, $hash_base) or die_error(undef, "Open git-blame failed"); git_header_html(); @@ -2591,7 +2624,7 @@ HTML while (1) { $_ = <$fd>; last unless defined $_; - my ($full_rev, $lineno, $orig_lineno, $group_size) = + my ($full_rev, $orig_lineno, $lineno, $group_size) = /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/; if (!exists $metainfo{$full_rev}) { $metainfo{$full_rev} = {}; @@ -2905,7 +2938,7 @@ sub git_tree { my $refs = git_get_references(); my $ref = format_ref_marker($refs, $hash_base); git_header_html(); - my $base = ""; + my $basedir = ''; my ($have_blame) = gitweb_check_feature('blame'); if (defined $hash_base && (my %co = parse_commit($hash_base))) { my @views_nav = (); @@ -2922,7 +2955,7 @@ sub git_tree { # FIXME: Should be available when we have no hash base as well. push @views_nav, $cgi->a({-href => href(action=>"snapshot", hash=>$hash)}, - "snapshot"); + "snapshot"); } git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav)); git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base); @@ -2933,12 +2966,39 @@ sub git_tree { print "
$hash
\n"; } if (defined $file_name) { - $base = esc_html("$file_name/"); + $basedir = $file_name; + if ($basedir ne '' && substr($basedir, -1) ne '/') { + $basedir .= '/'; + } } git_print_page_path($file_name, 'tree', $hash_base); print "
\n"; print "\n"; my $alternate = 1; + # '..' (top directory) link if possible + if (defined $hash_base && + defined $file_name && $file_name =~ m![^/]+$!) { + if ($alternate) { + print "\n"; + } else { + print "\n"; + } + $alternate ^= 1; + + my $up = $file_name; + $up =~ s!/?[^/]+$!!; + undef $up unless $up; + # based on git_print_tree_entry + print '\n"; + print '\n"; + print "\n"; + + print "\n"; + } foreach my $line (@entries) { my %t = parse_ls_tree_line($line, -z => 1); @@ -2949,7 +3009,7 @@ sub git_tree { } $alternate ^= 1; - git_print_tree_entry(\%t, $base, $hash_base, $have_blame); + git_print_tree_entry(\%t, $basedir, $hash_base, $have_blame); print "\n"; }
' . mode_str('040000') . "'; + print $cgi->a({-href => href(action=>"tree", hash_base=>$hash_base, + file_name=>$up)}, + ".."); + print "