From: Junio C Hamano Date: Fri, 21 May 2010 11:02:21 +0000 (-0700) Subject: Merge branch 'jn/gitweb-caching-prep' X-Git-Tag: v1.7.2-rc0~111 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/921296d3dabcb0bfe0926a1590cc9f7be42ae3e9?ds=inline;hp=-c Merge branch 'jn/gitweb-caching-prep' * jn/gitweb-caching-prep: gitweb: Move generating page title to separate subroutine gitweb: Add custom error handler using die_error gitweb: Use nonlocal jump instead of 'exit' in die_error gitweb: href(..., -path_info => 0|1) Export more test-related variables when running external tests --- 921296d3dabcb0bfe0926a1590cc9f7be42ae3e9 diff --combined gitweb/gitweb.perl index 4e64fc86bd,7d75dc4c8c..934aacb614 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@@ -11,7 -11,7 +11,7 @@@ use strict use warnings; use CGI qw(:standard :escapeHTML -nosticky); use CGI::Util qw(unescape); - use CGI::Carp qw(fatalsToBrowser); + use CGI::Carp qw(fatalsToBrowser set_message); use Encode; use Fcntl ':mode'; use File::Find qw(); @@@ -952,6 -952,21 +952,21 @@@ if ($git_avatar eq 'gravatar') $git_avatar = ''; } + # custom error handler: 'die ' is Internal Server Error + sub handle_errors_html { + my $msg = shift; # it is already HTML escaped + + # to avoid infinite loop where error occurs in die_error, + # change handler to default handler, disabling handle_errors_html + set_message("Error occured when inside die_error:\n$msg"); + + # you cannot jump out of die_error when called as error handler; + # the subroutine set via CGI::Carp::set_message is called _after_ + # HTTP headers are already written, so it cannot write them itself + die_error(undef, undef, $msg, -error_handler => 1, -no_http_header => 1); + } + set_message(\&handle_errors_html); + # dispatch if (!defined $action) { if (defined $hash) { @@@ -972,11 -987,16 +987,16 @@@ if ($action !~ m/^(?:opml|project_list| die_error(400, "Project needed"); } $actions{$action}->(); - exit; + DONE_GITWEB: + 1; ## ====================================================================== ## action links + # possible values of extra options + # -full => 0|1 - use absolute/full URL ($my_uri/$my_url as base) + # -replay => 1 - start from a current view (replay with modifications) + # -path_info => 0|1 - don't use/use path_info URL (if possible) sub href { my %params = @_; # default is to use -absolute url() i.e. $my_uri @@@ -993,7 -1013,8 +1013,8 @@@ } my $use_pathinfo = gitweb_check_feature('pathinfo'); - if ($use_pathinfo and defined $params{'project'}) { + if (defined $params{'project'} && + (exists $params{-path_info} ? $params{-path_info} : $use_pathinfo)) { # try to put as many parameters as possible in PATH_INFO: # - project name # - action @@@ -2420,9 -2441,6 +2441,9 @@@ sub git_get_projects_list follow_skip => 2, # ignore duplicates dangling_symlinks => 0, # ignore dangling symlinks, silently wanted => sub { + # global variables + our $project_maxdepth; + our $projectroot; # skip project-list toplevel, if we get it. return if (m!^[/.]$!); # only directories can be git repositories @@@ -3161,23 -3179,30 +3182,30 @@@ sub blob_contenttype ## ====================================================================== ## functions printing HTML: header, footer, error page + sub get_page_title { + my $title = to_utf8($site_name); + + return $title unless (defined $project); + $title .= " - " . to_utf8($project); + + return $title unless (defined $action); + $title .= "/$action"; # $action is US-ASCII (7bit ASCII) + + return $title unless (defined $file_name); + $title .= " - " . esc_path($file_name); + if ($action eq "tree" && $file_name !~ m|/$|) { + $title .= "/"; + } + + return $title; + } + sub git_header_html { my $status = shift || "200 OK"; my $expires = shift; + my %opts = @_; - my $title = "$site_name"; - if (defined $project) { - $title .= " - " . to_utf8($project); - if (defined $action) { - $title .= "/$action"; - if (defined $file_name) { - $title .= " - " . esc_path($file_name); - if ($action eq "tree" && $file_name !~ m|/$|) { - $title .= "/"; - } - } - } - } + my $title = get_page_title(); my $content_type; # require explicit support from the UA if we are to send the page as # 'application/xhtml+xml', otherwise send it as plain old 'text/html'. @@@ -3191,7 -3216,8 +3219,8 @@@ $content_type = 'text/html'; } print $cgi->header(-type=>$content_type, -charset => 'utf-8', - -status=> $status, -expires => $expires); + -status=> $status, -expires => $expires) + unless ($opts{'-no_http_headers'}); my $mod_perl_version = $ENV{'MOD_PERL'} ? " $ENV{'MOD_PERL'}" : ''; print < @@@ -3408,6 -3434,7 +3437,7 @@@ sub die_error my $status = shift || 500; my $error = esc_html(shift) || "Internal Server Error"; my $extra = shift; + my %opts = @_; my %http_responses = ( 400 => '400 Bad Request', @@@ -3416,7 -3443,7 +3446,7 @@@ 500 => '500 Internal Server Error', 503 => '503 Service Unavailable', ); - git_header_html($http_responses{$status}); + git_header_html($http_responses{$status}, undef, %opts); print <

@@@ -3430,7 -3457,8 +3460,8 @@@ EO print "\n"; git_footer_html(); - exit; + goto DONE_GITWEB + unless ($opts{'-error_handler'}); } ## ---------------------------------------------------------------------- @@@ -6120,8 -6148,8 +6151,8 @@@ sub git_commitdiff } push @commit_spec, '--root', $hash; } - open $fd, "-|", git_cmd(), "format-patch", '--encoding=utf8', - '--stdout', @commit_spec + open $fd, "-|", git_cmd(), "format-patch", @diff_opts, + '--encoding=utf8', '--stdout', @commit_spec or die_error(500, "Open git-format-patch failed"); } else { die_error(400, "Unknown commitdiff format"); diff --combined t/test-lib.sh index 9bfa14be7f,6187328e93..454880ac7d --- a/t/test-lib.sh +++ b/t/test-lib.sh @@@ -2,18 -2,6 +2,18 @@@ # # Copyright (c) 2005 Junio C Hamano # +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/ . # if --tee was passed, write the output not only to the terminal, but # additionally to the file test-results/$BASENAME.out, too. @@@ -366,10 -354,8 +366,10 @@@ test_debug () } test_run_ () { + test_cleanup=: eval >&3 2>&4 "$1" - eval_ret="$?" + eval_ret=$? + eval >&3 2>&4 "$test_cleanup" return 0 } @@@ -473,6 -459,9 +473,9 @@@ test_external () # Announce the script to reduce confusion about the # test output that follows. say_color "" " run $test_count: $descr ($*)" + # Export TEST_DIRECTORY, TRASH_DIRECTORY and GIT_TEST_LONG + # to be able to use them in script + export TEST_DIRECTORY TRASH_DIRECTORY GIT_TEST_LONG # Run command; redirect its stderr to &4 as in # test_run_, but keep its stdout on our stdout even in # non-verbose mode. @@@ -530,22 -519,6 +533,22 @@@ test_must_fail () test $? -gt 0 -a $? -le 129 -o $? -gt 192 } +# Similar to test_must_fail, but tolerates success, too. This is +# meant to be used in contexts like: +# +# test_expect_success 'some command works without configuration' ' +# test_might_fail git config --unset all.configuration && +# do something +# ' +# +# Writing "git config --unset all.configuration || :" would be wrong, +# because we want to notice if it fails due to segv. + +test_might_fail () { + "$@" + test $? -ge 0 -a $? -le 129 -o $? -gt 192 +} + # test_cmp is a helper function to compare actual and expected output. # You can use it like: # @@@ -563,31 -536,6 +566,31 @@@ test_cmp() $GIT_TEST_CMP "$@" } +# This function can be used to schedule some commands to be run +# unconditionally at the end of the test to restore sanity: +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# test_when_finished "git config --unset core.capslock" && +# hello world +# ' +# +# That would be roughly equivalent to +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# hello world +# git config --unset core.capslock +# ' +# +# except that the greeting and config --unset must both succeed for +# the test to pass. + +test_when_finished () { + test_cleanup="{ $* + } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" +} + # Most tests can use the created repository, but some may need to create more. # Usage: test_create_repo test_create_repo () {