From 630e0d6e295b25ccfaab58b1cee0e339db843880 Mon Sep 17 00:00:00 2001 From: Stricted Date: Sun, 23 Jun 2013 20:21:00 +0200 Subject: [PATCH] add newest gitweb files --- gitweb.css | 77 ++++---- index.cgi | 561 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 416 insertions(+), 222 deletions(-) mode change 100644 => 100755 index.cgi diff --git a/gitweb.css b/gitweb.css index 44a65da..8b0811d 100644 --- a/gitweb.css +++ b/gitweb.css @@ -195,18 +195,6 @@ table { border-spacing: 0; } -table.shortlog td { - padding: 0px 8px; - vertical-align: middle; - height:20px; -} - -img.graph { - padding: 0px; - margin: 0px; - display: block; -} - table.diff_tree { font-family: monospace; } @@ -260,14 +248,6 @@ table.blame .dark:hover { background-color: #f6f6f0; } -tr.header { - background-color: #d9d8d1; -} - -tr.header td { - vertical-align: center; -} - /* currently both use the same, but it can change */ tr.light:hover, tr.dark:hover { @@ -287,7 +267,7 @@ tr.color2 { background-color: #f6f6ff; } tr.color3 { background-color: #fff6f6; } td { - padding: 2px 5px; + padding: 0px 5px; font-size: 100%; vertical-align: top; } @@ -353,17 +333,22 @@ table.diff_tree span.file_status.copied { /* age1: 60*60*2 <= age < 60*60*24*2 */ .age1 { color: #009900; - background: transparent; + font-style: italic; } /* age0: age < 60*60*2 */ - .age0 { color: #009900; - background: transparent; + font-style: italic; font-weight: bold; } +img.graph { + padding: 0px; + margin: 0px; + display: block; +} + td.pre, div.pre, div.diff { font-family: monospace; font-size: 12px; @@ -441,39 +426,47 @@ div.diff a.hash:hover { div.diff.to_file a.path, div.diff.to_file { - color: #000000; + color: #007000; +} + +div.diff.add { + color: #008800; +} + +div.diff.add span.marked { + background-color: #aaffaa; } div.diff.from_file a.path, div.diff.from_file { - color: #000000; + color: #aa0000; } -.rem , -.from_file { - background-color: #ffdddd; + +div.diff.rem { + color: #cc0000; } -.add , -.to_file{ - background-color: #ddffdd; + +div.diff.rem span.marked { + background-color: #ffaaaa; } div.diff.chunk_header a, div.diff.chunk_header { - color: #999; + color: #990099; } +div.diff.chunk_header { + border: dotted #ffe0ff; + border-width: 1px 0px 0px 0px; + margin-top: 2px; +} div.diff.chunk_header span.chunk_info { - background: #eaf2f5; - color: #999; -} -.chunk_header { - background: #eaf2f5; - color: #999; + background-color: #ffeeff; } div.diff.chunk_header span.section { - color: #999; + color: #aa22aa; } div.diff.incomplete { @@ -514,6 +507,7 @@ div.chunk_block.ctx div div.diff.ctx { color: #404040; } + div.index_include { border: solid #d9d8d1; border-width: 0px 0px 1px; @@ -529,7 +523,7 @@ div.search { right: 12px } -.projsearch { +div.projsearch { text-align: center; margin: 20px 0px; } @@ -662,6 +656,7 @@ div.remote { cursor: pointer; } + /* Style definition generated by highlight 2.4.5, http://www.andre-simon.de/ */ /* Highlighting theme definition: */ diff --git a/index.cgi b/index.cgi old mode 100644 new mode 100755 index aa1d860..735dfc8 --- a/index.cgi +++ b/index.cgi @@ -27,7 +27,7 @@ BEGIN { CGI->compile() if $ENV{'MOD_PERL'}; } -our $version = "1.7.10.4-Stricted"; +our $version = "1.8.1.2-Stricted"; our ($my_url, $my_uri, $base_url, $path_info, $home_link); sub evaluate_uri { @@ -54,6 +54,11 @@ sub evaluate_uri { # to build the base URL ourselves: our $path_info = decode_utf8($ENV{"PATH_INFO"}); if ($path_info) { + # $path_info has already been URL-decoded by the web server, but + # $my_url and $my_uri have not. URL-decode them so we can properly + # strip $path_info. + $my_url = unescape($my_url); + $my_uri = unescape($my_uri); if ($my_url =~ s,\Q$path_info\E$,, && $my_uri =~ s,\Q$path_info\E$,, && defined $ENV{'SCRIPT_NAME'}) { @@ -110,11 +115,9 @@ our $javascript = "static/gitweb.js"; #our $logo_label = "git documentation"; our $logo_url = "http://git-scm.com/"; our $logo_label = "git homepage"; - # URI and label (title) of footer our $footer_url = "http://git-scm.com/"; our $footer_label = "git homepage"; - # source of projects list our $projects_list = ""; @@ -137,6 +140,12 @@ our $default_projects_order = "project"; # (only effective if this variable evaluates to true) our $export_ok = ""; +# don't generate age column on the projects list page +our $omit_age_column = 0; + +# don't generate information about owners of repositories +our $omit_owner=0; + # show repository only if this subroutine returns true # when given the path to the project, for example: # sub { return -e "$_[0]/git-daemon-export-ok"; } @@ -162,7 +171,7 @@ our $mimetypes_file = undef; # for which encoding all byte sequences are valid, for example # 'iso-8859-1' aka 'latin1' (it is decoded without checking, so it # could be even 'utf-8' for the old behavior) -our $fallback_encoding = 'iso-8859-1'; +our $fallback_encoding = 'latin1'; # rename detection options for git-diff and git-diff-tree # - default is '-M', with the cost proportional to @@ -263,16 +272,15 @@ our %highlight_basename = ( our %highlight_ext = ( # main extensions, defining name of syntax; # see files in /usr/share/highlight/langDefs/ directory - map { $_ => $_ } - qw(py c cpp rb java css php sh pl js tex bib xml awk bat ini spec tcl sql make), + (map { $_ => $_ } qw(py rb java css js tex bib xml awk bat ini spec tcl sql)), # alternate extensions, see /etc/highlight/filetypes.conf - 'h' => 'c', - map { $_ => 'sh' } qw(bash zsh ksh), - map { $_ => 'cpp' } qw(cxx c++ cc), - map { $_ => 'php' } qw(php3 php4 php5 phps), - map { $_ => 'pl' } qw(perl pm cgi), - map { $_ => 'make'} qw(mak mk), - map { $_ => 'xml' } qw(xhtml html htm), + (map { $_ => 'c' } qw(c h)), + (map { $_ => 'sh' } qw(sh bash zsh ksh)), + (map { $_ => 'cpp' } qw(cpp cxx c++ cc)), + (map { $_ => 'php' } qw(php php3 php4 php5 phps)), + (map { $_ => 'pl' } qw(pl perl pm)), # perhaps also 'cgi' + (map { $_ => 'make'} qw(make mak mk)), + (map { $_ => 'xml' } qw(xml xhtml html htm)), ); # You define site-wide feature defaults here; override them with @@ -522,6 +530,7 @@ our %feature = ( # To enable system wide have in $GITWEB_CONFIG # $feature{'highlight'}{'default'} = [1]; + 'highlight' => { 'sub' => sub { feature_bool('highlight', @_) }, 'override' => 0, @@ -533,7 +542,7 @@ our %feature = ( # $feature{'remote_heads'}{'default'} = [1]; # To have project specific config enable override in $GITWEB_CONFIG # $feature{'remote_heads'}{'override'} = 1; - # and in project config gitweb.remote_heads = 0|1; + # and in project config gitweb.remoteheads = 0|1; 'remote_heads' => { 'sub' => sub { feature_bool('remote_heads', @_) }, 'override' => 0, @@ -1549,7 +1558,7 @@ sub sanitize { return undef unless defined $str; $str = to_utf8($str); - $str =~ s|([[:cntrl:]])|($1 =~ /[\t\n\r]/ ? $1 : quot_cec($1))|eg; + $str =~ s|([[:cntrl:]])|(index("\t\n\r", $1) != -1 ? $1 : quot_cec($1))|eg; return $str; } @@ -1735,20 +1744,29 @@ sub chop_and_escape_str { # 'foobar' sub esc_html_hl_regions { my ($str, $css_class, @sel) = @_; - return esc_html($str) unless @sel; + my %opts = grep { ref($_) ne 'ARRAY' } @sel; + @sel = grep { ref($_) eq 'ARRAY' } @sel; + return esc_html($str, %opts) unless @sel; my $out = ''; my $pos = 0; for my $s (@sel) { - $out .= esc_html(substr($str, $pos, $s->[0] - $pos)) - if ($s->[0] - $pos > 0); - $out .= $cgi->span({-class => $css_class}, - esc_html(substr($str, $s->[0], $s->[1] - $s->[0]))); + my ($begin, $end) = @$s; - $pos = $s->[1]; + # Don't create empty elements. + next if $end <= $begin; + + my $escaped = esc_html(substr($str, $begin, $end - $begin), + %opts); + + $out .= esc_html(substr($str, $pos, $begin - $pos), %opts) + if ($begin - $pos > 0); + $out .= $cgi->span({-class => $css_class}, $escaped); + + $pos = $end; } - $out .= esc_html(substr($str, $pos)) + $out .= esc_html(substr($str, $pos), %opts) if ($pos < length($str)); return $out; @@ -2424,26 +2442,32 @@ sub format_cc_diff_chunk_header { } # process patch (diff) line (not to be used for diff headers), -# returning class and HTML-formatted (but not wrapped) line -sub process_diff_line { - my $line = shift; - my ($from, $to) = @_; - - my $diff_class = diff_line_class($line, $from, $to); - - chomp $line; - $line = untabify($line); +# returning HTML-formatted (but not wrapped) line. +# If the line is passed as a reference, it is treated as HTML and not +# esc_html()'ed. +sub format_diff_line { + my ($line, $diff_class, $from, $to) = @_; + + if (ref($line)) { + $line = $$line; + } else { + chomp $line; + $line = untabify($line); - if ($from && $to && $line =~ m/^\@{2} /) { - $line = format_unidiff_chunk_header($line, $from, $to); - return $diff_class, $line; + if ($from && $to && $line =~ m/^\@{2} /) { + $line = format_unidiff_chunk_header($line, $from, $to); + } elsif ($from && $to && $line =~ m/^\@{3}/) { + $line = format_cc_diff_chunk_header($line, $from, $to); + } else { + $line = esc_html($line, -nbsp=>1); + } + } - } elsif ($from && $to && $line =~ m/^\@{3}/) { - $line = format_cc_diff_chunk_header($line, $from, $to); - return $diff_class, $line; + my $diff_classes = "diff"; + $diff_classes .= " $diff_class" if ($diff_class); + $line = "
$line
\n"; - } - return $diff_class, esc_html($line, -nbsp=>1); + return $line; } # Generates undef or something like "_snapshot_" or "snapshot (_tbz2_ _zip_)", @@ -2674,12 +2698,15 @@ sub git_get_project_config { # only subsection, if exists, is case sensitive, # and not lowercased by 'git config -z -l' if (my ($hi, $mi, $lo) = ($key =~ /^([^.]*)\.(.*)\.([^.]*)$/)) { + $lo =~ s/_//g; $key = join(".", lc($hi), $mi, lc($lo)); + return if ($lo =~ /\W/ || $hi =~ /\W/); } else { $key = lc($key); + $key =~ s/_//g; + return if ($key =~ /\W/); } $key =~ s/^gitweb\.//; - return if ($key =~ m/\W/); # type sanity check if (defined $type) { @@ -3000,9 +3027,11 @@ sub git_get_projects_list { } if (check_export_ok("$projectroot/$path")) { my $pr = { - path => $path, - owner => to_utf8($owner), + path => $path }; + if ($owner) { + $pr->{'owner'} = to_utf8($owner); + } push @list, $pr; } } @@ -3889,6 +3918,7 @@ sub print_feed_meta { '-type' => "application/$type+xml" ); + $href_params{'extra_options'} = undef; $href_params{'action'} = $type; $link_attr{'-href'} = href(%href_params); print "" . esc_html($line) . "

\n"; - next; - } else { - # remove signoff lines - next; + $skip_blank_line = 1; } - } else { - $signoff = 0; + next; + } + + if ($line =~ m,\s*([a-z]*link): (https?://\S+),i) { + if (! $opts{'-remove_signoff'}) { + print "" . esc_html($1) . ": " . + "" . esc_html($2) . "" . + "
\n"; + $skip_blank_line = 1; + } + next; } # print only one empty line # do not print empty line after signoff if ($line eq "") { - next if ($empty || $signoff); - $empty = 1; + next if ($skip_blank_line); + $skip_blank_line = 1; } else { - $empty = 0; + $skip_blank_line = 0; } print format_log_line_html($line) . "
\n"; @@ -4497,7 +4530,7 @@ sub git_print_log { if ($opts{'-final_empty_line'}) { # end with single empty line - print "
\n" unless $empty; + print "
\n" unless $skip_blank_line; } } @@ -4999,10 +5032,186 @@ sub git_difftree_body { print "\n"; } -sub print_sidebyside_diff_chunk { - my @chunk = @_; +# Print context lines and then rem/add lines in a side-by-side manner. +sub print_sidebyside_diff_lines { + my ($ctx, $rem, $add) = @_; + + # print context block before add/rem block + if (@$ctx) { + print join '', + '
', + '
', + @$ctx, + '
', + '
', + @$ctx, + '
', + '
'; + } + + if (!@$add) { + # pure removal + print join '', + '
', + '
', + @$rem, + '
', + '
'; + } elsif (!@$rem) { + # pure addition + print join '', + '
', + '
', + @$add, + '
', + '
'; + } else { + print join '', + '
', + '
', + @$rem, + '
', + '
', + @$add, + '
', + '
'; + } +} + +# Print context lines and then rem/add lines in inline manner. +sub print_inline_diff_lines { + my ($ctx, $rem, $add) = @_; + + print @$ctx, @$rem, @$add; +} + +# Format removed and added line, mark changed part and HTML-format them. +# Implementation is based on contrib/diff-highlight +sub format_rem_add_lines_pair { + my ($rem, $add, $num_parents) = @_; + + # We need to untabify lines before split()'ing them; + # otherwise offsets would be invalid. + chomp $rem; + chomp $add; + $rem = untabify($rem); + $add = untabify($add); + + my @rem = split(//, $rem); + my @add = split(//, $add); + my ($esc_rem, $esc_add); + # Ignore leading +/- characters for each parent. + my ($prefix_len, $suffix_len) = ($num_parents, 0); + my ($prefix_has_nonspace, $suffix_has_nonspace); + + my $shorter = (@rem < @add) ? @rem : @add; + while ($prefix_len < $shorter) { + last if ($rem[$prefix_len] ne $add[$prefix_len]); + + $prefix_has_nonspace = 1 if ($rem[$prefix_len] !~ /\s/); + $prefix_len++; + } + + while ($prefix_len + $suffix_len < $shorter) { + last if ($rem[-1 - $suffix_len] ne $add[-1 - $suffix_len]); + + $suffix_has_nonspace = 1 if ($rem[-1 - $suffix_len] !~ /\s/); + $suffix_len++; + } + + # Mark lines that are different from each other, but have some common + # part that isn't whitespace. If lines are completely different, don't + # mark them because that would make output unreadable, especially if + # diff consists of multiple lines. + if ($prefix_has_nonspace || $suffix_has_nonspace) { + $esc_rem = esc_html_hl_regions($rem, 'marked', + [$prefix_len, @rem - $suffix_len], -nbsp=>1); + $esc_add = esc_html_hl_regions($add, 'marked', + [$prefix_len, @add - $suffix_len], -nbsp=>1); + } else { + $esc_rem = esc_html($rem, -nbsp=>1); + $esc_add = esc_html($add, -nbsp=>1); + } + + return format_diff_line(\$esc_rem, 'rem'), + format_diff_line(\$esc_add, 'add'); +} + +# HTML-format diff context, removed and added lines. +sub format_ctx_rem_add_lines { + my ($ctx, $rem, $add, $num_parents) = @_; + my (@new_ctx, @new_rem, @new_add); + my $can_highlight = 0; + my $is_combined = ($num_parents > 1); + + # Highlight if every removed line has a corresponding added line. + if (@$add > 0 && @$add == @$rem) { + $can_highlight = 1; + + # Highlight lines in combined diff only if the chunk contains + # diff between the same version, e.g. + # + # - a + # - b + # + c + # + d + # + # Otherwise the highlightling would be confusing. + if ($is_combined) { + for (my $i = 0; $i < @$add; $i++) { + my $prefix_rem = substr($rem->[$i], 0, $num_parents); + my $prefix_add = substr($add->[$i], 0, $num_parents); + + $prefix_rem =~ s/-/+/g; + + if ($prefix_rem ne $prefix_add) { + $can_highlight = 0; + last; + } + } + } + } + + if ($can_highlight) { + for (my $i = 0; $i < @$add; $i++) { + my ($line_rem, $line_add) = format_rem_add_lines_pair( + $rem->[$i], $add->[$i], $num_parents); + push @new_rem, $line_rem; + push @new_add, $line_add; + } + } else { + @new_rem = map { format_diff_line($_, 'rem') } @$rem; + @new_add = map { format_diff_line($_, 'add') } @$add; + } + + @new_ctx = map { format_diff_line($_, 'ctx') } @$ctx; + + return (\@new_ctx, \@new_rem, \@new_add); +} + +# Print context lines and then rem/add lines. +sub print_diff_lines { + my ($ctx, $rem, $add, $diff_style, $num_parents) = @_; + my $is_combined = $num_parents > 1; + + ($ctx, $rem, $add) = format_ctx_rem_add_lines($ctx, $rem, $add, + $num_parents); + + if ($diff_style eq 'sidebyside' && !$is_combined) { + print_sidebyside_diff_lines($ctx, $rem, $add); + } else { + # default 'inline' style and unknown styles + print_inline_diff_lines($ctx, $rem, $add); + } +} + +sub print_diff_chunk { + my ($diff_style, $num_parents, $from, $to, @chunk) = @_; my (@ctx, @rem, @add); + # The class of the previous line. + my $prev_class = ''; + return unless @chunk; # incomplete last line might be among removed or added lines, @@ -5021,55 +5230,19 @@ sub print_sidebyside_diff_chunk { # print chunk headers if ($class && $class eq 'chunk_header') { - print $line; + print format_diff_line($line, $class, $from, $to); next; } - ## print from accumulator when type of class of lines change - # empty contents block on start rem/add block, or end of chunk - if (@ctx && (!$class || $class eq 'rem' || $class eq 'add')) { - print join '', - '
', - '
', - @ctx, - '
', - '
', - @ctx, - '
', - '
'; - @ctx = (); - } - # empty add/rem block on start context block, or end of chunk - if ((@rem || @add) && (!$class || $class eq 'ctx')) { - if (!@add) { - # pure removal - print join '', - '
', - '
', - @rem, - '
', - '
'; - } elsif (!@rem) { - # pure addition - print join '', - '
', - '
', - @add, - '
', - '
'; - } else { - # assume that it is change - print join '', - '
', - '
', - @rem, - '
', - '
', - @add, - '
', - '
'; - } - @rem = @add = (); + ## print from accumulator when have some add/rem lines or end + # of chunk (flush context lines), or when have add and rem + # lines and new block is reached (otherwise add/rem lines could + # be reordered) + if (!$class || ((@rem || @add) && $class eq 'ctx') || + (@rem && @add && $class ne $prev_class)) { + print_diff_lines(\@ctx, \@rem, \@add, + $diff_style, $num_parents); + @ctx = @rem = @add = (); } ## adding lines to accumulator @@ -5085,6 +5258,8 @@ sub print_sidebyside_diff_chunk { if ($class eq 'ctx') { push @ctx, $line; } + + $prev_class = $class; } } @@ -5206,27 +5381,19 @@ sub git_patchset_body { next PATCH if ($patch_line =~ m/^diff /); - my ($class, $line) = process_diff_line($patch_line, \%from, \%to); - my $diff_classes = "diff"; - $diff_classes .= " $class" if ($class); - $line = "
$line
\n"; + my $class = diff_line_class($patch_line, \%from, \%to); - if ($diff_style eq 'sidebyside' && !$is_combined) { - if ($class eq 'chunk_header') { - print_sidebyside_diff_chunk(@chunk); - @chunk = ( [ $class, $line ] ); - } else { - push @chunk, [ $class, $line ]; - } - } else { - # default 'inline' style and unknown styles - print $line; + if ($class eq 'chunk_header') { + print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk); + @chunk = (); } + + push @chunk, [ $class, $patch_line ]; } } continue { if (@chunk) { - print_sidebyside_diff_chunk(@chunk); + print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk); @chunk = (); } print "\n"; # class="patch" @@ -5276,7 +5443,7 @@ sub git_project_search_form { if (defined $project_filter); print $cgi->textfield(-name => 's', -value => $searchtext, -title => "Search project by name and description$limit", - -size => 20) . "\n" . + -size => 60) . "\n" . "" . $cgi->checkbox(-name => 'sr', -value => 1, -label => 're', -checked => $search_use_regexp) . @@ -5285,7 +5452,7 @@ sub git_project_search_form { $cgi->end_form() . "\n" . $cgi->a({-href => href(project => undef, searchtext => undef, project_filter => $project_filter)}, - ) . "
\n"; + esc_html("List all projects$limit")) . "
\n"; print "\n"; } @@ -5366,23 +5533,30 @@ sub fill_project_list_info { sub sort_projects_list { my ($projlist, $order) = @_; - my @projects; - my %order_info = ( - project => { key => 'path', type => 'str' }, - descr => { key => 'descr_long', type => 'str' }, - owner => { key => 'owner', type => 'str' }, - age => { key => 'age', type => 'num' } - ); - my $oi = $order_info{$order}; - return @$projlist unless defined $oi; - if ($oi->{'type'} eq 'str') { - @projects = sort {$a->{$oi->{'key'}} cmp $b->{$oi->{'key'}}} @$projlist; - } else { - @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @$projlist; + sub order_str { + my $key = shift; + return sub { $a->{$key} cmp $b->{$key} }; } - return @projects; + sub order_num_then_undef { + my $key = shift; + return sub { + defined $a->{$key} ? + (defined $b->{$key} ? $a->{$key} <=> $b->{$key} : -1) : + (defined $b->{$key} ? 1 : 0) + }; + } + + my %orderings = ( + project => order_str('path'), + descr => order_str('descr_long'), + owner => order_str('owner'), + age => order_num_then_undef('age'), + ); + + my $ordering = $orderings{$order}; + return defined $ordering ? sort $ordering @$projlist : @$projlist; } # returns a hash of categories, containing the list of project @@ -5430,9 +5604,11 @@ sub git_project_list_rows { $from = 0 unless defined $from; $to = $#$projlist if (!defined $to || $#$projlist < $to); + my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my $pr = $projlist->[$i]; + if ($alternate) { print "\n"; } else { @@ -5464,11 +5640,15 @@ sub git_project_list_rows { ? esc_html_match_hl_chopped($pr->{'descr_long'}, $pr->{'descr'}, $search_regexp) : esc_html($pr->{'descr'})) . - "\n" . - "" . chop_and_escape_str($pr->{'owner'}, 15) . "\n"; - print "{'age'}) . "\">" . - (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "\n" . - "" . + "\n"; + unless ($omit_owner) { + print "" . chop_and_escape_str($pr->{'owner'}, 15) . "\n"; + } + unless ($omit_age_column) { + print "{'age'}) . "\">" . + (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "\n"; + } + print"" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"log")}, "log") . " | " . @@ -5477,7 +5657,7 @@ sub git_project_list_rows { "\n" . "\n"; } - print ""; + print ""; if ($check_forks) { print " "; } else { @@ -5506,7 +5686,10 @@ sub git_project_list_body { 'tagfilter' => $tagfilter) if ($tagfilter || $search_regexp); # fill the rest - @projects = fill_project_list_info(\@projects); + my @all_fields = ('descr', 'descr_long', 'ctags', 'category'); + push @all_fields, ('age', 'age_string') unless($omit_age_column); + push @all_fields, 'owner' unless($omit_owner); + @projects = fill_project_list_info(\@projects, @all_fields); $order ||= $default_projects_order; $from = 0 unless defined $from; @@ -5537,8 +5720,8 @@ sub git_project_list_body { } print_sort_th('project', $order, 'Project'); print_sort_th('descr', $order, 'Description'); - print_sort_th('owner', $order, 'Owner'); - print_sort_th('age', $order, 'Last Change'); + print_sort_th('owner', $order, 'Owner') unless $omit_owner; + print_sort_th('age', $order, 'Last Change') unless $omit_age_column; print "\n" . # for links "\n"; } @@ -5623,7 +5806,7 @@ sub git_shortlog_body { print "\n"; my $alternate = 1; my $graph_rand = int(rand(99999)); - my $head = git_get_head_hash($project); + my $head = git_get_head_hash($project); my $graph_hash; if (defined $allrefs && $allrefs == 1) { $graph_hash = "all"; @@ -6314,8 +6497,10 @@ sub git_summary { print "
 
\n"; print "
\n" . - "\n" . - "\n"; + "\n"; + unless ($omit_owner) { + print "\n"; + } if (defined $cd{'rfc2822'}) { print "" . "\n"; @@ -6364,7 +6549,7 @@ sub git_summary { git_print_header_div('shortlog'); git_shortlog_body(\@commitlist, 0, 15, $refs, $#commitlist <= 15 ? undef : - $cgi->a({-href => href(action=>"shortlog")}, "..."), 0, 0, 0, 1); + $cgi->a({-href => href(action=>"shortlog")}, "..."), 0, 0, 0, 1);; } if (@taglist) { @@ -7037,6 +7222,28 @@ sub snapshot_name { return wantarray ? ($name, $name) : $name; } +sub exit_if_unmodified_since { + my ($latest_epoch) = @_; + our $cgi; + + my $if_modified = $cgi->http('IF_MODIFIED_SINCE'); + if (defined $if_modified) { + my $since; + if (eval { require HTTP::Date; 1; }) { + $since = HTTP::Date::str2time($if_modified); + } elsif (eval { require Time::ParseDate; 1; }) { + $since = Time::ParseDate::parsedate($if_modified, GMT => 1); + } + if (defined $since && $latest_epoch <= $since) { + my %latest_date = parse_date($latest_epoch); + print $cgi->header( + -last_modified => $latest_date{'rfc2822'}, + -status => '304 Not Modified'); + goto DONE_GITWEB; + } + } +} + sub git_snapshot { my $format = $input_params{'snapshot_format'}; if (!@snapshot_fmts) { @@ -7063,6 +7270,10 @@ sub git_snapshot { my ($name, $prefix) = snapshot_name($project, $hash); my $filename = "$name$known_snapshot_formats{$format}{'suffix'}"; + + my %co = parse_commit($hash); + exit_if_unmodified_since($co{'committer_epoch'}) if %co; + my $cmd = quote_command( git_cmd(), 'archive', "--format=$known_snapshot_formats{$format}{'format'}", @@ -7072,9 +7283,15 @@ sub git_snapshot { } $filename =~ s/(["\\])/\\$1/g; + my %latest_date; + if (%co) { + %latest_date = parse_date($co{'committer_epoch'}, $co{'committer_tz'}); + } + print $cgi->header( -type => $known_snapshot_formats{$format}{'type'}, -content_disposition => 'inline; filename="' . $filename . '"', + %co ? (-last_modified => $latest_date{'rfc2822'}) : (), -status => '200 OK'); open my $fd, "-|", $cmd @@ -7089,10 +7306,10 @@ sub git_log_generic { my ($fmt_name, $body_subr, $base, $parent, $file_name, $file_hash) = @_; my $head = git_get_head_hash($project); - my $allrefs; + my $allrefs; if (!defined $base) { $base = $head; - $allrefs = 1; + $allrefs = 1; } if (!defined $page) { $page = 0; @@ -7100,10 +7317,10 @@ sub git_log_generic { my $refs = git_get_references(); my $commit_hash = $base; - if (defined $allrefs) { - $commit_hash = "--all"; - } - if (defined $parent) { + if (defined $allrefs) { + $commit_hash = "--all"; + } + if (defined $parent) { $commit_hash = "$parent..$base"; } my @commitlist = @@ -7859,33 +8076,14 @@ sub git_feed { if (defined($commitlist[0])) { %latest_commit = %{$commitlist[0]}; my $latest_epoch = $latest_commit{'committer_epoch'}; - %latest_date = parse_date($latest_epoch, $latest_commit{'comitter_tz'}); - my $if_modified = $cgi->http('IF_MODIFIED_SINCE'); - if (defined $if_modified) { - my $since; - if (eval { require HTTP::Date; 1; }) { - $since = HTTP::Date::str2time($if_modified); - } elsif (eval { require Time::ParseDate; 1; }) { - $since = Time::ParseDate::parsedate($if_modified, GMT => 1); - } - if (defined $since && $latest_epoch <= $since) { - print $cgi->header( - -type => $content_type, - -charset => 'utf-8', - -last_modified => $latest_date{'rfc2822'}, - -status => '304 Not Modified'); - return; - } - } - print $cgi->header( - -type => $content_type, - -charset => 'utf-8', - -last_modified => $latest_date{'rfc2822'}); - } else { - print $cgi->header( - -type => $content_type, - -charset => 'utf-8'); + exit_if_unmodified_since($latest_epoch); + %latest_date = parse_date($latest_epoch, $latest_commit{'committer_tz'}); } + print $cgi->header( + -type => $content_type, + -charset => 'utf-8', + %latest_date ? (-last_modified => $latest_date{'rfc2822'}) : (), + -status => '200 OK'); # Optimization: skip generating the body if client asks only # for Last-Modified date. @@ -7906,6 +8104,7 @@ sub git_feed { $feed_type = 'history'; } $title .= " $feed_type"; + $title = esc_html($title); my $descr = git_get_project_description($project); if (defined $descr) { $descr = esc_html($descr); -- 2.20.1
description" . esc_html($descr) . "
owner" . esc_html($owner) . "
description" . esc_html($descr) . "
owner" . esc_html($owner) . "
last change".format_timestamp_html(\%cd)."