X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/12a3deae85cff6a6da42f5312b653e02547b0b6016e7859642bd6765a1f884ec..3d2d863f75be984b8d788025d50f5d36fe89bc63c3799291af41f625f2a3b1ac:/gitweb.perl diff --git a/gitweb.perl b/gitweb.perl index 875be2d..daab942 100755 --- a/gitweb.perl +++ b/gitweb.perl @@ -48,6 +48,8 @@ our $home_text = "++GITWEB_HOMETEXT++"; our $stylesheet = "++GITWEB_CSS++"; # URI of GIT logo our $logo = "++GITWEB_LOGO++"; +# URI of GIT favicon, assumed to be image/png type +our $favicon = "++GITWEB_FAVICON++"; # source of projects list our $projects_list = "++GITWEB_LIST++"; @@ -152,7 +154,7 @@ sub feature_snapshot { our @diff_opts = ('-M'); # taken from git_commit our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++"; -require $GITWEB_CONFIG if -e $GITWEB_CONFIG; +do $GITWEB_CONFIG if -e $GITWEB_CONFIG; # version of the core git binary our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown"; @@ -1027,9 +1029,30 @@ sub parse_difftree_raw_line { } } # 'c512b523472485aef4fff9e57b229d9d243c967f' - #elsif ($line =~ m/^([0-9a-fA-F]{40})$/) { - # $res{'commit'} = $1; - #} + elsif ($line =~ m/^([0-9a-fA-F]{40})$/) { + $res{'commit'} = $1; + } + + return wantarray ? %res : \%res; +} + +# parse line of git-ls-tree output +sub parse_ls_tree_line ($;%) { + my $line = shift; + my %opts = @_; + my %res; + + #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c' + $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/; + + $res{'mode'} = $1; + $res{'type'} = $2; + $res{'hash'} = $3; + if ($opts{'-z'}) { + $res{'name'} = $4; + } else { + $res{'name'} = unquote($4); + } return wantarray ? %res : \%res; } @@ -1201,6 +1224,9 @@ EOF 'href="%s" type="application/rss+xml"/>'."\n", esc_param($project), href(action=>"rss")); } + if (defined $favicon) { + print qq(\n); + } print "\n" . "\n" . @@ -1354,6 +1380,24 @@ sub git_print_header_div { "\n\n"; } +#sub git_print_authorship (\%) { +sub git_print_authorship { + my $co = shift; + + my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'}); + print "
" . + esc_html($co->{'author_name'}) . + " [$ad{'rfc2822'}"; + if ($ad{'hour_local'} < 6) { + printf(" (%02d:%02d %s)", + $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); + } else { + printf(" (%02d:%02d %s)", + $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); + } + print "]
\n"; +} + sub git_print_page_path { my $name = shift; my $type = shift; @@ -1361,25 +1405,44 @@ sub git_print_page_path { if (!defined $name) { print "
/
\n"; - } elsif (defined $type && $type eq 'blob') { + } else { + my @dirname = split '/', $name; + my $basename = pop @dirname; + my $fullname = ''; + print "
"; - if (defined $hb) { + foreach my $dir (@dirname) { + $fullname .= $dir . '/'; + print $cgi->a({-href => href(action=>"tree", file_name=>$fullname, + hash_base=>$hb), + -title => $fullname}, esc_html($dir)); + print "/"; + } + if (defined $type && $type eq 'blob') { print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name, - hash_base=>$hb)}, - esc_html($name)); + hash_base=>$hb), + -title => $name}, esc_html($basename)); + } elsif (defined $type && $type eq 'tree') { + print $cgi->a({-href => href(action=>"tree", file_name=>$file_name, + hash_base=>$hb), + -title => $name}, esc_html($basename)); + print "/"; } else { - print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name)}, - esc_html($name)); + print esc_html($basename); } print "
\n"; - } else { - print "
" . esc_html($name) . "
\n"; } } -sub git_print_log { +# sub git_print_log (\@;%) { +sub git_print_log ($;%) { my $log = shift; + my %opts = @_; + if ($opts{'-remove_title'}) { + # remove title, i.e. first line of log + shift @$log; + } # remove leading empty lines while (defined $log->[0] && $log->[0] eq "") { shift @$log; @@ -1389,6 +1452,20 @@ sub git_print_log { my $signoff = 0; my $empty = 0; foreach my $line (@$log) { + if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) { + $signoff = 1; + $empty = 0; + if (! $opts{'-remove_signoff'}) { + print "" . esc_html($line) . "
\n"; + next; + } else { + # remove signoff lines + next; + } + } else { + $signoff = 0; + } + # print only one empty line # do not print empty line after signoff if ($line eq "") { @@ -1397,13 +1474,13 @@ sub git_print_log { } else { $empty = 0; } - if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) { - $signoff = 1; - print "" . esc_html($line) . "
\n"; - } else { - $signoff = 0; - print format_log_line_html($line) . "
\n"; - } + + print format_log_line_html($line) . "
\n"; + } + + if ($opts{'-final_empty_line'}) { + # end with single empty line + print "
\n" unless $empty; } } @@ -1411,30 +1488,65 @@ sub git_print_simplified_log { my $log = shift; my $remove_title = shift; - shift @$log if $remove_title; - # remove leading empty lines - while (defined $log->[0] && $log->[0] eq "") { - shift @$log; - } + git_print_log($log, + -final_empty_line=> 1, + -remove_title => $remove_title); +} - # simplify and print log - my $empty = 0; - foreach my $line (@$log) { - # remove signoff lines - if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) { - next; +# print tree entry (row of git_tree), but without encompassing element +sub git_print_tree_entry { + my ($t, $basedir, $hash_base, $have_blame) = @_; + + my %base_key = (); + $base_key{hash_base} = $hash_base if defined $hash_base; + + print "" . mode_str($t->{'mode'}) . "\n"; + 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" . + "" . + $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 only one empty line - if ($line eq "") { - next if $empty; - $empty = 1; - } else { - $empty = 0; + if (defined $hash_base) { + print " | " . + $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, + hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}")}, + "history"); } - print format_log_line_html($line) . "
\n"; + print " | " . + $cgi->a({-href => href(action=>"blob_plain", + hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}")}, + "raw") . + "\n"; + + } elsif ($t->{'type'} eq "tree") { + print "" . + $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, + file_name=>"$basedir$t->{'name'}", %base_key)}, + esc_html($t->{'name'})) . + "\n" . + "" . + $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, + file_name=>"$basedir$t->{'name'}")}, + "history"); + } + print "\n"; } - # end with single empty line - print "
\n" unless $empty; } ## ...................................................................... @@ -1451,6 +1563,7 @@ sub git_difftree_body { print "\n"; my $alternate = 0; + my $patchno = 0; foreach my $line (@{$difftree}) { my %diff = parse_difftree_raw_line($line); @@ -1491,8 +1604,14 @@ sub git_difftree_body { "\n"; + "blob"); + if ($action eq 'commitdiff') { + # link to patch + $patchno++; + print " | " . + $cgi->a({-href => "#patch$patchno"}, "patch"); + } + print "\n"; } elsif ($diff{'status'} eq "D") { # deleted my $mode_chng = "[deleted $from_file_type]"; @@ -1506,8 +1625,14 @@ sub git_difftree_body { $cgi->a({-href => href(action=>"blob", hash=>$diff{'from_id'}, hash_base=>$parent, file_name=>$diff{'file'})}, "blob") . - " | " . - $cgi->a({-href => href(action=>"history", hash_base=>$parent, + " | "; + if ($action eq 'commitdiff') { + # link to patch + $patchno++; + print " | " . + $cgi->a({-href => "#patch$patchno"}, "patch"); + } + print $cgi->a({-href => href(action=>"history", hash_base=>$parent, file_name=>$diff{'file'})}, "history") . "\n"; @@ -1543,16 +1668,23 @@ sub git_difftree_body { print "\n" . "\n" . "\n"; @@ -1620,7 +1759,7 @@ sub git_patchset_body { # first patch in patchset $patch_found = 1; } - print "
\n"; + print "
\n"; if (ref($difftree->[$patch_idx]) eq "HASH") { $diffinfo = $difftree->[$patch_idx]; @@ -2130,7 +2269,8 @@ sub git_blame2 { my $fd; my $ftype; - if (!gitweb_check_feature('blame')) { + my ($have_blame) = gitweb_check_feature('blame'); + if (!$have_blame) { die_error('403 Permission denied', "Permission denied"); } die_error('404 Not Found', "File name not defined") if (!$file_name); @@ -2199,7 +2339,8 @@ HTML sub git_blame { my $fd; - if (!gitweb_check_feature('blame')) { + my ($have_blame) = gitweb_check_feature('blame'); + if (!$have_blame) { die_error('403 Permission denied', "Permission denied"); } die_error('404 Not Found', "File name not defined") if (!$file_name); @@ -2373,7 +2514,7 @@ sub git_blob { die_error(undef, "No file name defined"); } } - my $have_blame = gitweb_check_feature('blame'); + my ($have_blame) = gitweb_check_feature('blame'); open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash or die_error(undef, "Couldn't cat $file_name, $hash"); my $mimetype = blob_mimetype($fd, $file_name); @@ -2448,14 +2589,13 @@ sub git_tree { my $refs = git_get_references(); my $ref = format_ref_marker($refs, $hash_base); git_header_html(); - my %base_key = (); my $base = ""; - my $have_blame = gitweb_check_feature('blame'); + my ($have_blame) = gitweb_check_feature('blame'); if (defined $hash_base && (my %co = parse_commit($hash_base))) { - $base_key{hash_base} = $hash_base; git_print_page_nav('tree','', $hash_base); git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base); } else { + undef $hash_base; print "
\n"; print "

\n"; print "
$hash
\n"; @@ -2468,54 +2608,17 @@ sub git_tree { print "
" . $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, hash_base=>$hash, file_name=>$diff{'file'})}, - "blob") . - "$mode_chnge" . - $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - hash_base=>$hash, file_name=>$diff{'file'})}, - "blob"); + $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, + hash_base=>$hash, file_name=>$diff{'file'})}, + "blob"); if ($diff{'to_id'} ne $diff{'from_id'}) { # modified - 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"); + if ($action eq 'commitdiff') { + # link to patch + $patchno++; + 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"); + } } print " | " . $cgi->a({-href => href(action=>"history", @@ -1582,12 +1714,19 @@ sub git_difftree_body { hash=>$diff{'to_id'}, file_name=>$diff{'to_file'})}, "blob"); if ($diff{'to_id'} ne $diff{'from_id'}) { - 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"); + if ($action eq 'commitdiff') { + # link to patch + $patchno++; + 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"); + } } print "
\n"; my $alternate = 0; foreach my $line (@entries) { - #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c' - $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/; - my $t_mode = $1; - my $t_type = $2; - my $t_hash = $3; - my $t_name = validate_input($4); + my %t = parse_ls_tree_line($line, -z => 1); + if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; - print "\n"; - if ($t_type eq "blob") { - print "\n" . - "\n"; - } elsif ($t_type eq "tree") { - print "\n" . - "\n"; - } + + git_print_tree_entry(\%t, $base, $hash_base, $have_blame); + print "\n"; } print "
" . mode_str($t_mode) . "" . - $cgi->a({-href => href(action=>"blob", hash=>$t_hash, file_name=>"$base$t_name", %base_key), - -class => "list"}, esc_html($t_name)) . - "" . - $cgi->a({-href => href(action=>"blob", hash=>$t_hash, file_name=>"$base$t_name", %base_key)}, - "blob"); - if ($have_blame) { - print " | " . - $cgi->a({-href => href(action=>"blame", hash=>$t_hash, file_name=>"$base$t_name", %base_key)}, - "blame"); - } - print " | " . - $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, - hash=>$t_hash, file_name=>"$base$t_name")}, - "history") . - " | " . - $cgi->a({-href => href(action=>"blob_plain", - hash=>$t_hash, file_name=>"$base$t_name")}, - "raw") . - "" . - $cgi->a({-href => href(action=>"tree", hash=>$t_hash, file_name=>"$base$t_name", %base_key)}, - esc_html($t_name)) . - "" . - $cgi->a({-href => href(action=>"tree", hash=>$t_hash, file_name=>"$base$t_name", %base_key)}, - "tree") . - " | " . - $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, file_name=>"$base$t_name")}, - "history") . - "
\n" . @@ -2696,7 +2799,7 @@ sub git_commit { "" . $cgi->a({-href => href(action=>"commit", hash=>$par)}, "commit") . " | " . - $cgi->a({-href => href(action=>"commitdiff", hash=>$hash, hash_parent=>$par)}, "commitdiff") . + $cgi->a({-href => href(action=>"commitdiff", hash=>$hash, hash_parent=>$par)}, "diff") . "" . "\n"; } @@ -2734,10 +2837,6 @@ sub git_blobdiff { @difftree or die_error('404 Not Found', "Blob diff not found"); - } elsif (defined $hash) { # try to find filename from $hash - if ($hash !~ /[0-9a-fA-F]{40}/) { - $hash = git_to_hash($hash); - } } elsif (defined $hash && $hash =~ /[0-9a-fA-F]{40}/) { # try to find filename from $hash @@ -2935,6 +3034,7 @@ sub git_commitdiff { git_header_html(undef, $expires); git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav); git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash); + git_print_authorship(\%co); print "
\n"; print "
\n"; git_print_simplified_log($co{'comment'}, 1); # skip title @@ -2967,8 +3067,8 @@ TEXT # write patch if ($format eq 'html') { - #git_difftree_body(\@difftree, $hash, $hash_parent); - #print "
\n"; + git_difftree_body(\@difftree, $hash, $hash_parent); + print "
\n"; git_patchset_body($fd, \@difftree, $hash, $hash_parent); close $fd;