From: John 'Warthog9' Hawley Date: Thu, 14 Jan 2010 01:23:04 GMT Subject: [PATCH 8/9] gitweb: Convert output to using indirect file handle Message-ID: <1263432185-21334-9-git-send-email-warthog9@eaglescrag.net> In-Reply-To: <1263432185-21334-8-git-send-email-warthog9@eaglescrag.net> This converts the output handling of gitweb to using an indirect file handle. This is in preparation to add the caching layer. This is a slight modification to the way I was originally doing it by passing the output around. This should be a nop and this shouldn't change the behavior of gitweb. This does leave error reporting functions (die_error specifically) continuing to output directly as I want to garauntee those will report their errors regardless of what may be going on with respect to the rest of the output. --- gitweb/gitweb.perl | 880 ++++++++++++++++++++++++++-------------------------- 1 files changed, 448 insertions(+), 432 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c4a177d..8bb323c 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -450,6 +450,13 @@ our %feature = ( 'default' => [0]}, ); +# Basic file handler for all of gitweb, there are two of them. The first +# is the basic text/html file handler which is used for everything other +# then the binary files, that uses a separate file handler though +# these are both set to STDOUT for the time being. +our $output_handler = *STDOUT; +our $output_handler_bin = *STDOUT; + sub gitweb_get_feature { my ($name) = @_; return unless exists $feature{$name}; @@ -3081,7 +3088,7 @@ sub insert_file { my $filename = shift; open my $fd, '<', $filename; - print map { to_utf8($_) } <$fd>; + print {$output_handler} map { to_utf8($_) } <$fd>; close $fd; } @@ -3198,10 +3205,10 @@ sub git_header_html { } else { $content_type = 'text/html'; } - print $cgi->header(-type=>$content_type, -charset => 'utf-8', + print {$output_handler} $cgi->header(-type=>$content_type, -charset => 'utf-8', -status=> $status, -expires => $expires); my $mod_perl_version = $ENV{'MOD_PERL'} ? " $ENV{'MOD_PERL'}" : ''; - print < @@ -3216,16 +3223,16 @@ EOF # the stylesheet, favicon etc urls won't work correctly with path_info # unless we set the appropriate base URL if ($ENV{'PATH_INFO'}) { - print "\n"; + print {$output_handler} "\n"; } # print out each stylesheet that exist, providing backwards capability # for those people who defined $stylesheet in a config file if (defined $stylesheet) { - print ''."\n"; + print {$output_handler} ''."\n"; } else { foreach my $stylesheet (@stylesheets) { next unless $stylesheet; - print ''."\n"; + print {$output_handler} ''."\n"; } } if (defined $project) { @@ -3244,7 +3251,7 @@ EOF $href_params{'action'} = $type; $link_attr{'-href'} = href(%href_params); - print "'."\n", $site_name, href(project=>undef, action=>"project_index")); - printf(''."\n", $site_name, href(project=>undef, action=>"opml")); } if (defined $favicon) { - print qq(\n); + print {$output_handler} qq(\n); } - print "\n" . + print {$output_handler} "\n" . "\n"; if ($site_header && -f $site_header) { insert_file($site_header); } - print "
\n" . + print {$output_handler} "
\n" . $cgi->a({-href => esc_url($logo_url), -title => $logo_label}, qq()); - print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / "; + print {$output_handler} $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / "; if (defined $project) { - print $cgi->a({-href => href(action=>"summary")}, esc_html($project)); + print {$output_handler} $cgi->a({-href => href(action=>"summary")}, esc_html($project)); if (defined $action) { - print " / $action"; + print {$output_handler} " / $action"; } - print "\n"; + print {$output_handler} "\n"; } - print "
\n"; + print {$output_handler} "
\n"; my $have_search = gitweb_check_feature('search'); if (defined $project && $have_search) { @@ -3313,7 +3320,7 @@ EOF if ($use_pathinfo) { $action .= "/".esc_url($project); } - print $cgi->startform(-method => "get", -action => $action) . + print {$output_handler} $cgi->startform(-method => "get", -action => $action) . "
\n" . (!$use_pathinfo && $cgi->input({-name=>"p", -value=>$project, -type=>"hidden"}) . "\n") . @@ -3336,11 +3343,11 @@ EOF sub git_footer_html { my $feed_class = 'rss_logo'; - print "
\n"; + print {$output_handler} "
\n"; if (defined $project) { my $descr = git_get_project_description($project); if (defined $descr) { - print "\n"; + print {$output_handler} "\n"; } my %href_params = get_feed_info(); @@ -3351,22 +3358,22 @@ sub git_footer_html { foreach my $format qw(RSS Atom) { $href_params{'action'} = lc($format); - print $cgi->a({-href => href(%href_params), + print {$output_handler} $cgi->a({-href => href(%href_params), -title => "$href_params{'-title'} $format feed", -class => $feed_class}, $format)."\n"; } } else { - print $cgi->a({-href => href(project=>undef, action=>"opml"), + print {$output_handler} $cgi->a({-href => href(project=>undef, action=>"opml"), -class => $feed_class}, "OPML") . " "; - print $cgi->a({-href => href(project=>undef, action=>"project_index"), + print {$output_handler} $cgi->a({-href => href(project=>undef, action=>"project_index"), -class => $feed_class}, "TXT") . "\n"; } - print "
\n"; # class="page_footer" + print {$output_handler} "
\n"; # class="page_footer" if (defined $t0 && gitweb_check_feature('timed')) { - print "
\n"; - print 'This page took '. + print {$output_handler} "
\n"; + print {$output_handler} 'This page took '. ''. Time::HiRes::tv_interval($t0, [Time::HiRes::gettimeofday()]). ' seconds '. @@ -3375,26 +3382,26 @@ sub git_footer_html { $number_of_git_cmds. ' git commands '. " to generate.\n"; - print "
\n"; # class="page_footer" + print {$output_handler} "
\n"; # class="page_footer" } if (-f $site_footer) { insert_file($site_footer); } - print qq!\n!; + print {$output_handler} qq!\n!; if ($action eq 'blame_incremental') { - print qq!\n!; } elsif (gitweb_check_feature('javascript-actions')) { - print qq!\n!; } - print "\n" . + print {$output_handler} "\n" . ""; } @@ -3416,6 +3423,14 @@ sub die_error { my $error = shift || "Internal server error"; my $extra = shift; + # The output handlers for die_error need to be reset to STDOUT + # so that half the message isn't being output to random and + # half to STDOUT as expected. This is mainly for the benefit + # of using git_header_html() and git_footer_html() since those + # internaly use the indirect print handler. + $output_handler = *STDOUT; + $output_handler_bin = *STDOUT; + my %http_responses = ( 400 => '400 Bad Request', 403 => '403 Forbidden', @@ -3484,12 +3499,12 @@ sub git_print_page_nav { $arg{$label}{'_href'} = $link; } - print "
\n" . + print {$output_handler} "
\n" . (join " | ", map { $_ eq $current ? $_ : $cgi->a({-href => ($arg{$_}{_href} ? $arg{$_}{_href} : href(%{$arg{$_}}))}, "$_") } @navs); - print "
\n$extra
\n" . + print {$output_handler} "
\n$extra
\n" . "
\n"; } @@ -3530,14 +3545,14 @@ sub git_print_header_div { $args{'hash'} = $hash if $hash; $args{'hash_base'} = $hash_base if $hash_base; - print "
\n" . + print {$output_handler} "
\n" . $cgi->a({-href => href(%args), -class => "title"}, $title ? $title : $action) . "\n
\n"; } sub print_local_time { - print get_local_time(@_); + print {$output_handler} get_local_time(@_); } sub get_local_time { @@ -3562,11 +3577,11 @@ sub git_print_authorship { my $author = $co->{'author_name'}; my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'}); - print "<$tag class=\"author_date\">" . + print {$output_handler} "<$tag class=\"author_date\">" . format_search_author($author, "author", esc_html($author)) . " [$ad{'rfc2822'}"; - print_local_time(%ad) if ($opts{-localtime}); - print "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1) + print {$output_handler} get_local_time(%ad) if ($opts{-localtime}); + print {$output_handler} "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1) . "\n"; } @@ -3582,7 +3597,7 @@ sub git_print_authorship_rows { @people = ('author', 'committer') unless @people; foreach my $who (@people) { my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"}); - print "$who" . + print {$output_handler} "$who" . format_search_author($co->{"${who}_name"}, $who, esc_html($co->{"${who}_name"})) . " " . format_search_author($co->{"${who}_email"}, $who, @@ -3592,8 +3607,8 @@ sub git_print_authorship_rows { "\n" . "" . " $wd{'rfc2822'}"; - print_local_time(%wd); - print "" . + print {$output_handler} get_local_time(%wd); + print {$output_handler} "" . "\n"; } } @@ -3603,11 +3618,10 @@ sub git_print_page_path { my $type = shift; my $hb = shift; - - print "
"; - print $cgi->a({-href => href(action=>"tree", hash_base=>$hb), + print {$output_handler} "
"; + print {$output_handler} $cgi->a({-href => href(action=>"tree", hash_base=>$hb), -title => 'tree root'}, to_utf8("[$project]")); - print " / "; + print {$output_handler} " / "; if (defined $name) { my @dirname = split '/', $name; my $basename = pop @dirname; @@ -3615,25 +3629,25 @@ sub git_print_page_path { foreach my $dir (@dirname) { $fullname .= ($fullname ? '/' : '') . $dir; - print $cgi->a({-href => href(action=>"tree", file_name=>$fullname, + print {$output_handler} $cgi->a({-href => href(action=>"tree", file_name=>$fullname, hash_base=>$hb), -title => $fullname}, esc_path($dir)); - print " / "; + print {$output_handler} " / "; } if (defined $type && $type eq 'blob') { - print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name, + print {$output_handler} $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name, hash_base=>$hb), -title => $name}, esc_path($basename)); } elsif (defined $type && $type eq 'tree') { - print $cgi->a({-href => href(action=>"tree", file_name=>$file_name, + print {$output_handler} $cgi->a({-href => href(action=>"tree", file_name=>$file_name, hash_base=>$hb), -title => $name}, esc_path($basename)); - print " / "; + print {$output_handler} " / "; } else { - print esc_path($basename); + print {$output_handler} esc_path($basename); } } - print "
\n"; + print {$output_handler} "
\n"; } sub git_print_log { @@ -3657,7 +3671,7 @@ sub git_print_log { $signoff = 1; $empty = 0; if (! $opts{'-remove_signoff'}) { - print "" . esc_html($line) . "
\n"; + print {$output_handler} "" . esc_html($line) . "
\n"; next; } else { # remove signoff lines @@ -3676,12 +3690,12 @@ sub git_print_log { $empty = 0; } - print format_log_line_html($line) . "
\n"; + print {$output_handler} format_log_line_html($line) . "
\n"; } if ($opts{'-final_empty_line'}) { # end with single empty line - print "
\n" unless $empty; + print {$output_handler} "
\n" unless $empty; } } @@ -3754,12 +3768,12 @@ sub git_print_tree_entry { # the mode of the entry, list is the name of the entry, an href, # and link is the action links of the entry. - print "" . mode_str($t->{'mode'}) . "\n"; + print {$output_handler} "" . mode_str($t->{'mode'}) . "\n"; if (exists $t->{'size'}) { - print "$t->{'size'}\n"; + print {$output_handler} "$t->{'size'}\n"; } if ($t->{'type'} eq "blob") { - print "" . + print {$output_handler} "" . $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}", %base_key), -class => "list"}, esc_path($t->{'name'})); @@ -3768,71 +3782,71 @@ sub git_print_tree_entry { if ($link_target) { my $norm_target = normalize_link_target($link_target, $basedir); if (defined $norm_target) { - print " -> " . + print {$output_handler} " -> " . $cgi->a({-href => href(action=>"object", hash_base=>$hash_base, file_name=>$norm_target), -title => $norm_target}, esc_path($link_target)); } else { - print " -> " . esc_path($link_target); + print {$output_handler} " -> " . esc_path($link_target); } } } - print "\n"; - print ""; - print $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'}, + print {$output_handler} "\n"; + print {$output_handler} ""; + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}", %base_key)}, "blob"); if ($have_blame) { - print " | " . + print {$output_handler} " | " . $cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}", %base_key)}, "blame"); } if (defined $hash_base) { - print " | " . + print {$output_handler} " | " . $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}")}, "history"); } - print " | " . + print {$output_handler} " | " . $cgi->a({-href => href(action=>"blob_plain", hash_base=>$hash_base, file_name=>"$basedir$t->{'name'}")}, "raw"); - print "\n"; + print {$output_handler} "\n"; } elsif ($t->{'type'} eq "tree") { - print ""; - print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, + print {$output_handler} ""; + print {$output_handler} $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}", %base_key)}, esc_path($t->{'name'})); - print "\n"; - print ""; - print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, + print {$output_handler} "\n"; + print {$output_handler} ""; + print {$output_handler} $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}", %base_key)}, "tree"); if (defined $hash_base) { - print " | " . + print {$output_handler} " | " . $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, file_name=>"$basedir$t->{'name'}")}, "history"); } - print "\n"; + print {$output_handler} "\n"; } else { # unknown object: we can only present history for it # (this includes 'commit' object, i.e. submodule support) - print "" . + print {$output_handler} "" . esc_path($t->{'name'}) . "\n"; - print ""; + print {$output_handler} ""; if (defined $hash_base) { - print $cgi->a({-href => href(action=>"history", + print {$output_handler} $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, file_name=>"$basedir$t->{'name'}")}, "history"); } - print "\n"; + print {$output_handler} "\n"; } } @@ -3879,13 +3893,13 @@ sub git_difftree_body { my ($difftree, $hash, @parents) = @_; my ($parent) = $parents[0]; my $have_blame = gitweb_check_feature('blame'); - print "
\n"; + print {$output_handler} "
\n"; if ($#{$difftree} > 10) { - print(($#{$difftree} + 1) . " files changed:\n"); + print {$output_handler} (($#{$difftree} + 1) . " files changed:\n"); } - print "
\n"; + print {$output_handler} "
\n"; - print " 1 ? "combined " : "") . "diff_tree\">\n"; @@ -3893,11 +3907,11 @@ sub git_difftree_body { my $has_header = @$difftree && @parents > 1 && $action eq 'commitdiff'; if ($has_header) { # table header - print "\n" . + print {$output_handler} "\n" . "\n"; # filename, patchN link for (my $i = 0; $i < @parents; $i++) { my $par = $parents[$i]; - print "\n"; } - print "\n\n"; + print {$output_handler} "\n\n"; } my $alternate = 1; @@ -3914,9 +3928,9 @@ sub git_difftree_body { my $diff = parsed_difftree_line($line); if ($alternate) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } $alternate ^= 1; @@ -3927,14 +3941,14 @@ sub git_difftree_body { if (!is_deleted($diff)) { # file exists in the result (child) commit - print "\n"; } else { - print "\n"; } @@ -3942,7 +3956,7 @@ sub git_difftree_body { if ($action eq 'commitdiff') { # link to patch $patchno++; - print "\n"; @@ -3960,9 +3974,9 @@ sub git_difftree_body { $not_deleted ||= ($status ne 'D'); if ($status eq 'A') { - print "\n"; + print {$output_handler} "\n"; } elsif ($status eq 'D') { - print "\n"; } else { if ($diff->{'to_id'} eq $from_hash) { - print "\n"; + print {$output_handler} "\n"; - print "\n"; + print {$output_handler} "\n"; next; # instead of 'else' clause, to avoid extra indent } # else ordinary diff @@ -4030,51 +4044,51 @@ sub git_difftree_body { my $mode_chng = "[new $to_file_type"; $mode_chng .= " with mode: $to_mode_str" if $to_mode_str; $mode_chng .= "]"; - print "\n"; - print "\n"; - print "\n"; + print {$output_handler} "\n"; + print {$output_handler} "\n"; + print {$output_handler} "\n"; } elsif ($diff->{'status'} eq "D") { # deleted my $mode_chng = "[deleted $from_file_type]"; - print "\n"; - print "\n"; - print "\n"; + print {$output_handler} "\n"; + print {$output_handler} "\n"; + print {$output_handler} "\n"; } elsif ($diff->{'status'} eq "M" || $diff->{'status'} eq "T") { # modified, or type changed my $mode_chnge = ""; @@ -4092,39 +4106,39 @@ sub git_difftree_body { } $mode_chnge .= "]\n"; } - print "\n"; - print "\n"; - print "\n"; + print {$output_handler} "\n"; + print {$output_handler} "\n"; + print {$output_handler} "\n"; } elsif ($diff->{'status'} eq "R" || $diff->{'status'} eq "C") { # renamed or copied my %status_name = ('R' => 'moved', 'C' => 'copied'); @@ -4134,7 +4148,7 @@ sub git_difftree_body { # mode also for directories, so we cannot use $to_mode_str $mode_chng = sprintf(", mode: %04o", $to_mode_oct & 0777); } - print "\n" . @@ -4147,35 +4161,35 @@ sub git_difftree_body { if ($action eq 'commitdiff') { # link to patch $patchno++; - print $cgi->a({-href => "#patch$patchno"}, "patch") . + print {$output_handler} $cgi->a({-href => "#patch$patchno"}, "patch") . " | "; } elsif ($diff->{'to_id'} ne $diff->{'from_id'}) { # "commit" view and modified file (not only pure rename or copy) - print $cgi->a({-href => href(action=>"blobdiff", + print {$output_handler} $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 $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, hash_base=>$parent, file_name=>$diff->{'to_file'})}, "blob") . " | "; if ($have_blame) { - print $cgi->a({-href => href(action=>"blame", hash_base=>$hash, + print {$output_handler} $cgi->a({-href => href(action=>"blame", hash_base=>$hash, file_name=>$diff->{'to_file'})}, "blame") . " | "; } - print $cgi->a({-href => href(action=>"history", hash_base=>$hash, + print {$output_handler} $cgi->a({-href => href(action=>"history", hash_base=>$hash, file_name=>$diff->{'to_file'})}, "history"); - print "\n"; + print {$output_handler} "\n"; } # we should not encounter Unmerged (U) or Unknown (X) status - print "\n"; + print {$output_handler} "\n"; } - print "" if $has_header; - print "
" . + print {$output_handler} "" . $cgi->a({-href => href(action=>"commitdiff", hash=>$hash, hash_parent=>$par), -title => 'commitdiff to parent number ' . @@ -3905,7 +3919,7 @@ sub git_difftree_body { $i+1) . " 
" . + print {$output_handler} "" . $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, file_name=>$diff->{'to_file'}, hash_base=>$hash), -class => "list"}, esc_path($diff->{'to_file'})) . "" . + print {$output_handler} "" . esc_path($diff->{'to_file'}) . "" . + print {$output_handler} "" . $cgi->a({-href => "#patch$patchno"}, "patch") . " | " . " | | " . + print {$output_handler} "" . $cgi->a({-href => href(action=>"blob", hash_base=>$hash, hash=>$from_hash, @@ -3971,11 +3985,11 @@ sub git_difftree_body { " | "; + print {$output_handler} ""; } - print $cgi->a({-href => href(action=>"blobdiff", + print {$output_handler} $cgi->a({-href => href(action=>"blobdiff", hash=>$diff->{'to_id'}, hash_parent=>$from_hash, hash_base=>$hash, @@ -3987,24 +4001,24 @@ sub git_difftree_body { } } - print ""; + print {$output_handler} ""; if ($not_deleted) { - print $cgi->a({-href => href(action=>"blob", + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, file_name=>$diff->{'to_file'}, hash_base=>$hash)}, "blob"); - print " | " if ($has_history); + print {$output_handler} " | " if ($has_history); } if ($has_history) { - print $cgi->a({-href => href(action=>"history", + print {$output_handler} $cgi->a({-href => href(action=>"history", file_name=>$diff->{'to_file'}, hash_base=>$hash)}, "history"); } - print "
"; - print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + print {$output_handler} ""; + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, hash_base=>$hash, file_name=>$diff->{'file'}), -class => "list"}, esc_path($diff->{'file'})); - print "$mode_chng"; + print {$output_handler} "$mode_chng"; if ($action eq 'commitdiff') { # link to patch $patchno++; - print $cgi->a({-href => "#patch$patchno"}, "patch"); - print " | "; + print {$output_handler} $cgi->a({-href => "#patch$patchno"}, "patch"); + print {$output_handler} " | "; } - print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, hash_base=>$hash, file_name=>$diff->{'file'})}, "blob"); - print ""; - print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'}, + print {$output_handler} ""; + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'}, hash_base=>$parent, file_name=>$diff->{'file'}), -class => "list"}, esc_path($diff->{'file'})); - print "$mode_chng"; + print {$output_handler} "$mode_chng"; if ($action eq 'commitdiff') { # link to patch $patchno++; - print $cgi->a({-href => "#patch$patchno"}, "patch"); - print " | "; + print {$output_handler} $cgi->a({-href => "#patch$patchno"}, "patch"); + print {$output_handler} " | "; } - print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'}, + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'}, hash_base=>$parent, file_name=>$diff->{'file'})}, "blob") . " | "; if ($have_blame) { - print $cgi->a({-href => href(action=>"blame", hash_base=>$parent, + print {$output_handler} $cgi->a({-href => href(action=>"blame", hash_base=>$parent, file_name=>$diff->{'file'})}, "blame") . " | "; } - print $cgi->a({-href => href(action=>"history", hash_base=>$parent, + print {$output_handler} $cgi->a({-href => href(action=>"history", hash_base=>$parent, file_name=>$diff->{'file'})}, "history"); - print ""; - print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + print {$output_handler} ""; + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, hash_base=>$hash, file_name=>$diff->{'file'}), -class => "list"}, esc_path($diff->{'file'})); - print "$mode_chnge"; + print {$output_handler} "$mode_chnge"; if ($action eq 'commitdiff') { # link to patch $patchno++; - print $cgi->a({-href => "#patch$patchno"}, "patch") . + print {$output_handler} $cgi->a({-href => "#patch$patchno"}, "patch") . " | "; } elsif ($diff->{'to_id'} ne $diff->{'from_id'}) { # "commit" view and modified file (not onlu mode changed) - print $cgi->a({-href => href(action=>"blobdiff", + print {$output_handler} $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=>"blob", hash=>$diff->{'to_id'}, + print {$output_handler} $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, hash_base=>$hash, file_name=>$diff->{'file'})}, "blob") . " | "; if ($have_blame) { - print $cgi->a({-href => href(action=>"blame", hash_base=>$hash, + print {$output_handler} $cgi->a({-href => href(action=>"blame", hash_base=>$hash, file_name=>$diff->{'file'})}, "blame") . " | "; } - print $cgi->a({-href => href(action=>"history", hash_base=>$hash, + print {$output_handler} $cgi->a({-href => href(action=>"history", hash_base=>$hash, file_name=>$diff->{'file'})}, "history"); - print "" . + print {$output_handler} "" . $cgi->a({-href => href(action=>"blob", hash_base=>$hash, hash=>$diff->{'to_id'}, file_name=>$diff->{'to_file'}), -class => "list"}, esc_path($diff->{'to_file'})) . "
\n"; + print {$output_handler} "" if $has_header; + print {$output_handler} "\n"; } sub git_patchset_body { @@ -4190,7 +4204,7 @@ sub git_patchset_body { my $to_name; my (%from, %to); - print "
\n"; + print {$output_handler} "
\n"; # skip to first patch while ($patch_line = <$fd>) { @@ -4218,7 +4232,7 @@ sub git_patchset_body { # and parse raw git-diff line if needed if (is_patch_split($diffinfo, { 'to_file' => $to_name })) { # this is continuation of a split patch - print "
\n"; + print {$output_handler} "
\n"; } else { # advance raw git-diff output if needed $patch_idx++ if defined $diffinfo; @@ -4230,7 +4244,7 @@ sub git_patchset_body { # find which patch (using pathname of result) we are at now; if ($is_combined) { while ($to_name ne $diffinfo->{'to_file'}) { - print "
\n" . + print {$output_handler} "
\n" . format_diff_cc_simplified($diffinfo, @hash_parents) . "
\n"; # class="patch" @@ -4247,7 +4261,7 @@ sub git_patchset_body { # this is first patch for raw difftree line with $patch_idx index # we index @$difftree array from 0, but number patches from 1 - print "
\n"; + print {$output_handler} "
\n"; } # git diff header @@ -4255,25 +4269,25 @@ sub git_patchset_body { #assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed $patch_number++; # print "git diff" header - print format_git_diff_header_line($patch_line, $diffinfo, + print {$output_handler} format_git_diff_header_line($patch_line, $diffinfo, \%from, \%to); # print extended diff header - print "
\n"; + print {$output_handler} "
\n"; EXTENDED_HEADER: while ($patch_line = <$fd>) { chomp $patch_line; last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /); - print format_extended_diff_header_line($patch_line, $diffinfo, + print {$output_handler} format_extended_diff_header_line($patch_line, $diffinfo, \%from, \%to); } - print "
\n"; # class="diff extended_header" + print {$output_handler} "
\n"; # class="diff extended_header" # from-file/to-file diff header if (! $patch_line) { - print "
\n"; # class="patch" + print {$output_handler} "
\n"; # class="patch" last PATCH; } next PATCH if ($patch_line =~ m/^diff /); @@ -4284,7 +4298,7 @@ sub git_patchset_body { chomp $patch_line; #assert($patch_line =~ m/^\+\+\+/) if DEBUG; - print format_diff_from_to_header($last_patch_line, $patch_line, + print {$output_handler} format_diff_from_to_header($last_patch_line, $patch_line, $diffinfo, \%from, \%to, @hash_parents); @@ -4295,11 +4309,11 @@ sub git_patchset_body { next PATCH if ($patch_line =~ m/^diff /); - print format_diff_line($patch_line, \%from, \%to); + print {$output_handler} format_diff_line($patch_line, \%from, \%to); } } continue { - print "
\n"; # class="patch" + print {$output_handler} "
\n"; # class="patch" } # for compact combined (--cc) format, with chunk and patch simpliciaction @@ -4311,7 +4325,7 @@ sub git_patchset_body { $diffinfo = parsed_difftree_line($difftree->[$patch_idx]); # generate anchor for "patch" links in difftree / whatchanged part - print "
\n" . + print {$output_handler} "
\n" . format_diff_cc_simplified($diffinfo, @hash_parents) . "
\n"; # class="patch" @@ -4320,13 +4334,13 @@ sub git_patchset_body { if ($patch_number == 0) { if (@hash_parents > 1) { - print "
Trivial merge
\n"; + print {$output_handler} "
Trivial merge
\n"; } else { - print "
No differences found
\n"; + print {$output_handler} "
No differences found
\n"; } } - print "
\n"; # class="patchset" + print {$output_handler} "
\n"; # class="patchset" } # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @@ -4375,7 +4389,7 @@ sub fill_project_list_info { # print 'sort by' element, generating 'sort by $name' replay link # if that order is not selected sub print_sort_th { - print get_sort_th(@_); + print {$output_handler} get_sort_th(@_); } sub get_sort_th { @@ -4428,20 +4442,20 @@ sub git_project_list_body { } } my $cloud = git_populate_project_tagcloud(\%ctags); - print git_show_project_tagcloud($cloud, 64); + print {$output_handler} git_show_project_tagcloud($cloud, 64); } - print "\n"; + print {$output_handler} "
\n"; unless ($no_header) { - print "\n"; + print {$output_handler} "\n"; if ($check_forks) { - print "\n"; + print {$output_handler} "\n"; } - 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 "\n" . # for links + print {$output_handler} get_sort_th('project', $order, 'Project'); + print {$output_handler} get_sort_th('descr', $order, 'Description'); + print {$output_handler} get_sort_th('owner', $order, 'Owner'); + print {$output_handler} get_sort_th('age', $order, 'Last Change'); + print {$output_handler} "\n" . # for links "\n"; } my $alternate = 1; @@ -4461,26 +4475,26 @@ sub git_project_list_body { } if ($alternate) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } $alternate ^= 1; if ($check_forks) { - print "\n"; + print {$output_handler} "\n"; } - print "\n" . + print {$output_handler} "\n". "\n" . "\n"; - print "\n" . "\n"; } if (defined $extra) { - print "\n"; + print {$output_handler} "\n"; if ($check_forks) { - print "\n"; + print {$output_handler} "\n"; } - print "\n" . + print {$output_handler} "\n" . "\n"; } - print "
"; + print {$output_handler} ""; if ($pr->{'forks'}) { - print "\n"; - print $cgi->a({-href => href(project=>$pr->{'path'}, action=>"forks")}, "+"); + print {$output_handler} "\n"; + print {$output_handler} $cgi->a({-href => href(project=>$pr->{'path'}, action=>"forks")}, "+"); } - print "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), - -class => "list"}, esc_html($pr->{'path'})) . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), + -class => "list"}, esc_html($pr->{'path'})) ."" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), -class => "list", -title => $pr->{'descr_long'}}, esc_html($pr->{'descr'})) . "" . chop_and_escape_str($pr->{'owner'}, 15) . "{'age'}) . "\">" . + print {$output_handler} "{'age'}) . "\">" . (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " . @@ -4492,14 +4506,14 @@ sub git_project_list_body { "
$extra$extra
\n"; + print {$output_handler} "\n"; } sub git_log_body { @@ -4519,7 +4533,7 @@ sub git_log_body { "$co{'age_string'}" . esc_html($co{'title'}) . $ref, $commit); - print "
\n" . + print {$output_handler} "
\n" . "
\n" . $cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") . " | " . @@ -4529,16 +4543,16 @@ sub git_log_body { "
\n" . "
\n"; git_print_authorship(\%co, -tag => 'span'); - print "
\n
\n"; + print {$output_handler} "
\n
\n"; - print "
\n"; + print {$output_handler} "
\n"; git_print_log($co{'comment'}, -final_empty_line=> 1); - print "
\n"; + print {$output_handler} "
\n"; } if ($extra) { - print "
\n"; - print "$extra\n"; - print "
\n"; + print {$output_handler} "
\n"; + print {$output_handler} "$extra\n"; + print {$output_handler} "
\n"; } } @@ -4549,41 +4563,41 @@ sub git_shortlog_body { $from = 0 unless defined $from; $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to); - print "\n"; + print {$output_handler} "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my %co = %{$commitlist->[$i]}; my $commit = $co{'id'}; my $ref = format_ref_marker($refs, $commit); if ($alternate) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } $alternate ^= 1; # git_summary() used print "\n" . - print "\n" . + print {$output_handler} "\n" . format_author_html('td', \%co, 10) . "\n" . + print {$output_handler} "\n" . "\n" . + print {$output_handler} "\n" . "\n"; } if (defined $extra) { - print "\n" . + print {$output_handler} "\n" . "\n" . "\n"; } - print "
$co{'age_string'}$co{'age_string_date'}$co{'age_string_date'}"; - print format_subject_html($co{'title'}, $co{'title_short'}, + print {$output_handler} format_subject_html($co{'title'}, $co{'title_short'}, href(action=>"commit", hash=>$commit), $ref); - print "" . $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"); my $snapshot_links = format_snapshot_links($commit); if (defined $snapshot_links) { - print " | " . $snapshot_links; + print {$output_handler} " | " . $snapshot_links; } - print "
$extra
\n"; + print {$output_handler} "\n"; } sub git_history_body { @@ -4594,7 +4608,7 @@ sub git_history_body { $from = 0 unless defined $from; $to = $#{$commitlist} unless (defined $to && $to <= $#{$commitlist}); - print "\n"; + print {$output_handler} "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my %co = %{$commitlist->[$i]}; @@ -4606,18 +4620,18 @@ sub git_history_body { my $ref = format_ref_marker($refs, $commit); if ($alternate) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } $alternate ^= 1; - print "\n" . + print {$output_handler} "\n" . # shortlog: format_author_html('td', \%co, 10) format_author_html('td', \%co, 15, 3) . "\n" . + print {$output_handler} "\n" . "\n" . + print {$output_handler} "\n" . "\n"; } if (defined $extra) { - print "\n" . + print {$output_handler} "\n" . "\n" . "\n"; } - print "
$co{'age_string_date'}$co{'age_string_date'}"; # originally git_history used chop_str($co{'title'}, 50) - print format_subject_html($co{'title'}, $co{'title_short'}, + print {$output_handler} format_subject_html($co{'title'}, $co{'title_short'}, href(action=>"commit", hash=>$commit), $ref); - print "" . $cgi->a({-href => href(action=>$ftype, hash_base=>$commit, file_name=>$file_name)}, $ftype) . " | " . $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff"); @@ -4627,7 +4641,7 @@ sub git_history_body { my $blob_parent = git_get_hash_by_path($commit, $file_name); if (defined $blob_current && defined $blob_parent && $blob_current ne $blob_parent) { - print " | " . + print {$output_handler} " | " . $cgi->a({-href => href(action=>"blobdiff", hash=>$blob_current, hash_parent=>$blob_parent, hash_base=>$hash_base, hash_parent_base=>$commit, @@ -4635,15 +4649,15 @@ sub git_history_body { "diff to current"); } } - print "
$extra
\n"; + print {$output_handler} "\n"; } sub git_tags_body { @@ -4652,7 +4666,7 @@ sub git_tags_body { $from = 0 unless defined $from; $to = $#{$taglist} if (!defined $to || $#{$taglist} < $to); - print "\n"; + print {$output_handler} "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my $entry = $taglist->[$i]; @@ -4663,50 +4677,50 @@ sub git_tags_body { $comment_short = chop_str($comment, 30, 5); } if ($alternate) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } $alternate ^= 1; if (defined $tag{'age'}) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } - print "\n" . "\n" . + print {$output_handler} "\n" . "\n" . + print {$output_handler} "\n" . "\n" . + print {$output_handler} "\n" . ""; } if (defined $extra) { - print "\n" . + print {$output_handler} "\n" . "\n" . "\n"; } - print "
$tag{'age'}$tag{'age'}" . + print {$output_handler} "" . $cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'}), -class => "list name"}, esc_html($tag{'name'})) . ""; if (defined $comment) { - print format_subject_html($comment, $comment_short, + print {$output_handler} format_subject_html($comment, $comment_short, href(action=>"tag", hash=>$tag{'id'})); } - print ""; if ($tag{'type'} eq "tag") { - print $cgi->a({-href => href(action=>"tag", hash=>$tag{'id'})}, "tag"); + print {$output_handler} $cgi->a({-href => href(action=>"tag", hash=>$tag{'id'})}, "tag"); } else { - print " "; + print {$output_handler} " "; } - print "" . " | " . $cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'})}, $tag{'reftype'}); if ($tag{'reftype'} eq "commit") { - print " | " . $cgi->a({-href => href(action=>"shortlog", hash=>$tag{'fullname'})}, "shortlog") . + print {$output_handler} " | " . $cgi->a({-href => href(action=>"shortlog", hash=>$tag{'fullname'})}, "shortlog") . " | " . $cgi->a({-href => href(action=>"log", hash=>$tag{'fullname'})}, "log"); } elsif ($tag{'reftype'} eq "blob") { - print " | " . $cgi->a({-href => href(action=>"blob_plain", hash=>$tag{'refid'})}, "raw"); + print {$output_handler} " | " . $cgi->a({-href => href(action=>"blob_plain", hash=>$tag{'refid'})}, "raw"); } - print "
$extra
\n"; + print {$output_handler} "\n"; } sub git_heads_body { @@ -4715,19 +4729,19 @@ sub git_heads_body { $from = 0 unless defined $from; $to = $#{$headlist} if (!defined $to || $#{$headlist} < $to); - print "\n"; + print {$output_handler} "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my $entry = $headlist->[$i]; my %ref = %$entry; my $curr = $ref{'id'} eq $head; if ($alternate) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } $alternate ^= 1; - print "\n" . + print {$output_handler} "\n" . ($curr ? ""; } if (defined $extra) { - print "\n" . + print {$output_handler} "\n" . "\n" . "\n"; } - print "
$ref{'age'}$ref{'age'}" : "") . $cgi->a({-href => href(action=>"shortlog", hash=>$ref{'fullname'}), -class => "list name"},esc_html($ref{'name'})) . @@ -4740,11 +4754,11 @@ sub git_heads_body { "
$extra
\n"; + print {$output_handler} "\n"; } sub git_search_grep_body { @@ -4752,7 +4766,7 @@ sub git_search_grep_body { $from = 0 unless defined $from; $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to); - print "\n"; + print {$output_handler} "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my %co = %{$commitlist->[$i]}; @@ -4761,12 +4775,12 @@ sub git_search_grep_body { } my $commit = $co{'id'}; if ($alternate) { - print "\n"; + print {$output_handler} "\n"; } else { - print "\n"; + print {$output_handler} "\n"; } $alternate ^= 1; - print "\n" . + print {$output_handler} "\n" . format_author_html('td', \%co, 15, 5) . "\n" . + print {$output_handler} "\n" . "\n" . + print {$output_handler} "\n" . "\n"; } if (defined $extra) { - print "\n" . + print {$output_handler} "\n" . "\n" . "\n"; } - print "
$co{'age_string_date'}$co{'age_string_date'}" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), @@ -4786,25 +4800,25 @@ sub git_search_grep_body { $match = esc_html($match); $trail = esc_html($trail); - print "$lead$match$trail
"; + print {$output_handler} "$lead$match$trail
"; } } - print "
" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") . " | " . $cgi->a({-href => href(action=>"commitdiff", hash=>$co{'id'})}, "commitdiff") . " | " . $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree"); - print "
$extra
\n"; + print {$output_handler} "\n"; } ## ====================================================================== @@ -4824,11 +4838,11 @@ sub git_project_list { git_header_html(); if (-f $home_text) { - print "
\n"; + print {$output_handler} "
\n"; insert_file($home_text); - print "
\n"; + print {$output_handler} "
\n"; } - print $cgi->startform(-method => "get") . + print {$output_handler} $cgi->startform(-method => "get") . "

Search:\n" . $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . "

" . @@ -4858,7 +4872,7 @@ sub git_forks { sub git_project_index { my @projects = git_get_projects_list($project); - print $cgi->header( + print {$output_handler} $cgi->header( -type => 'text/plain', -charset => 'utf-8', -content_disposition => 'inline; filename="index.aux"'); @@ -4875,7 +4889,7 @@ sub git_project_index { $path =~ s/ /\+/g; $owner =~ s/ /\+/g; - print "$path $owner\n"; + print {$output_handler} "$path $owner\n"; } } @@ -4902,12 +4916,12 @@ sub git_summary { git_header_html(); git_print_page_nav('summary','', $head); - print "
 
\n"; - print "\n" . + print {$output_handler} "
 
\n"; + print {$output_handler} "
\n" . "\n" . "\n"; if (defined $cd{'rfc2822'}) { - print "\n"; + print {$output_handler} "\n"; } # use per project git URL list in $projectroot/$project/cloneurl @@ -4917,7 +4931,7 @@ sub git_summary { @url_list = map { "$_/$project" } @git_base_url_list unless @url_list; foreach my $git_url (@url_list) { next unless $git_url; - print "\n"; + print {$output_handler} "\n"; $url_tag = ""; } @@ -4926,23 +4940,23 @@ sub git_summary { if ($show_ctags) { my $ctags = git_get_project_ctags($project); my $cloud = git_populate_project_tagcloud($ctags); - print "\n\n"; + print {$output_handler} "\n\n"; } - print "
description" . esc_html($descr) . "
owner" . esc_html($owner) . "
last change$cd{'rfc2822'}
last change$cd{'rfc2822'}
Content tags:
"; - print "
" unless %$ctags; - print "
Add:
"; - print "
" if %$ctags; - print git_show_project_tagcloud($cloud, 48); - print "
Content tags:
"; + print {$output_handler} "
" unless %$ctags; + print {$output_handler} "
Add:
"; + print {$output_handler} "
" if %$ctags; + print {$output_handler} git_show_project_tagcloud($cloud, 48); + print {$output_handler} "
\n"; + print {$output_handler} "\n"; # If XSS prevention is on, we don't include README.html. # TODO: Allow a readme in some safe format. if (!$prevent_xss && -s "$projectroot/$project/README.html") { - print "
readme
\n" . + print {$output_handler} "
readme
\n" . "
\n"; insert_file("$projectroot/$project/README.html"); - print "\n
\n"; # class="readme" + print {$output_handler} "\n
\n"; # class="readme" } # we need to request one more than 16 (0..15) to check if @@ -4991,7 +5005,7 @@ sub git_tag { } git_print_header_div('commit', esc_html($tag{'name'}), $hash); - print "
\n" . + print {$output_handler} "
\n" . "\n" . "\n" . "\n" . @@ -5003,15 +5017,15 @@ sub git_tag { if (defined($tag{'author'})) { git_print_authorship_rows(\%tag, 'author'); } - print "
object
\n\n" . + print {$output_handler} "\n\n" . "
\n"; - print "
"; + print {$output_handler} "
"; my $comment = $tag{'comment'}; foreach my $line (@$comment) { chomp $line; - print esc_html($line, -nbsp=>1) . "
\n"; + print {$output_handler} esc_html($line, -nbsp=>1) . "
\n"; } - print "
\n"; + print {$output_handler} "
\n"; git_footer_html(); } @@ -5062,21 +5076,23 @@ sub git_blame_common { # incremental blame data returns early if ($format eq 'data') { - print $cgi->header( + print {$output_handler} $cgi->header( -type=>"text/plain", -charset => "utf-8", -status=> "200 OK"); local $| = 1; # output autoflush - print while <$fd>; + while (<$fd>) { + print {$output_handler} $_; + } close $fd - or print "ERROR $!\n"; + or die_error(500, "ERROR $!\n"); - print 'END'; + print {$output_handler} 'END'; if (defined $t0 && gitweb_check_feature('timed')) { - print ' '. + print {$output_handler} ' '. Time::HiRes::tv_interval($t0, [Time::HiRes::gettimeofday()]). ' '.$number_of_git_cmds; } - print "\n"; + print {$output_handler} "\n"; return; } @@ -5109,20 +5125,20 @@ sub git_blame_common { # page body if ($format eq 'incremental') { - print "