Browse Source

Merge branch 'jh/gitweb-caching' (early part)

* 'jh/gitweb-caching' (early part):
  gitweb: Add optional extra parameter to die_error, for extended explanation
  gitweb: add a "string" variant of print_sort_th
  gitweb: add a "string" variant of print_local_time
  gitweb: Check that $site_header etc. are defined before using them
  gitweb: Makefile improvements
  gitweb: Load checking
  gitweb: Make running t9501 test with '--debug' reliable and usable
maint
Junio C Hamano 15 years ago
parent
commit
484e669aa7
  1. 65
      Makefile
  2. 129
      gitweb/Makefile
  3. 7
      gitweb/README
  4. 92
      gitweb/gitweb.perl
  5. 1
      t/gitweb-lib.sh
  6. 30
      t/t9501-gitweb-standalone-http-status.sh

65
Makefile

@ -275,29 +275,6 @@ pathsep = : @@ -275,29 +275,6 @@ pathsep = :
# JavaScript minifier invocation that can function as filter
JSMIN =

# default configuration for gitweb
GITWEB_CONFIG = gitweb_config.perl
GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf
GITWEB_HOME_LINK_STR = projects
GITWEB_SITENAME =
GITWEB_PROJECTROOT = /pub/git
GITWEB_PROJECT_MAXDEPTH = 2007
GITWEB_EXPORT_OK =
GITWEB_STRICT_EXPORT =
GITWEB_BASE_URL =
GITWEB_LIST =
GITWEB_HOMETEXT = indextext.html
GITWEB_CSS = gitweb.css
GITWEB_LOGO = git-logo.png
GITWEB_FAVICON = git-favicon.png
ifdef JSMIN
GITWEB_JS = gitweb.min.js
else
GITWEB_JS = gitweb.js
endif
GITWEB_SITE_HEADER =
GITWEB_SITE_FOOTER =

export prefix bindir sharedir sysconfdir

CC = gcc
@ -1518,6 +1495,11 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl @@ -1518,6 +1495,11 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
chmod +x $@+ && \
mv $@+ $@


.PHONY: gitweb
gitweb:
$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all

ifdef JSMIN
OTHER_PROGRAMS += gitweb/gitweb.cgi gitweb/gitweb.min.js
gitweb/gitweb.cgi: gitweb/gitweb.perl gitweb/gitweb.min.js
@ -1525,30 +1507,13 @@ else @@ -1525,30 +1507,13 @@ else
OTHER_PROGRAMS += gitweb/gitweb.cgi
gitweb/gitweb.cgi: gitweb/gitweb.perl
endif
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
-e 's|++GIT_BINDIR++|$(bindir)|g' \
-e 's|++GITWEB_CONFIG++|$(GITWEB_CONFIG)|g' \
-e 's|++GITWEB_CONFIG_SYSTEM++|$(GITWEB_CONFIG_SYSTEM)|g' \
-e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \
-e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \
-e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \
-e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \
-e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \
-e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \
-e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \
-e 's|++GITWEB_LIST++|$(GITWEB_LIST)|g' \
-e 's|++GITWEB_HOMETEXT++|$(GITWEB_HOMETEXT)|g' \
-e 's|++GITWEB_CSS++|$(GITWEB_CSS)|g' \
-e 's|++GITWEB_LOGO++|$(GITWEB_LOGO)|g' \
-e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
-e 's|++GITWEB_JS++|$(GITWEB_JS)|g' \
-e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
-e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
$< >$@+ && \
chmod +x $@+ && \
mv $@+ $@
$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@)

ifdef JSMIN
gitweb/gitweb.min.js: gitweb/gitweb.js
$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@)
endif # JSMIN


git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css gitweb/gitweb.js
$(QUIET_GEN)$(RM) $@ $@+ && \
@ -1575,12 +1540,6 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh @@ -1575,12 +1540,6 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
mv $@+ $@
endif # NO_PERL


ifdef JSMIN
gitweb/gitweb.min.js: gitweb/gitweb.js
$(QUIET_GEN)$(JSMIN) <$< >$@
endif # JSMIN

ifndef NO_PYTHON
$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS
$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py

129
gitweb/Makefile

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
# The default target of this Makefile is...
all::

# Define V=1 to have a more verbose compile.
#
# Define JSMIN to point to JavaScript minifier that functions as
# a filter to have gitweb.js minified.
#

prefix ?= $(HOME)
bindir ?= $(prefix)/bin
RM ?= rm -f

# JavaScript minifier invocation that can function as filter
JSMIN ?=

# default configuration for gitweb
GITWEB_CONFIG = gitweb_config.perl
GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf
GITWEB_HOME_LINK_STR = projects
GITWEB_SITENAME =
GITWEB_PROJECTROOT = /pub/git
GITWEB_PROJECT_MAXDEPTH = 2007
GITWEB_EXPORT_OK =
GITWEB_STRICT_EXPORT =
GITWEB_BASE_URL =
GITWEB_LIST =
GITWEB_HOMETEXT = indextext.html
GITWEB_CSS = gitweb.css
GITWEB_LOGO = git-logo.png
GITWEB_FAVICON = git-favicon.png
ifdef JSMIN
GITWEB_JS = gitweb.min.js
else
GITWEB_JS = gitweb.js
endif
GITWEB_SITE_HEADER =
GITWEB_SITE_FOOTER =

# include user config
-include ../config.mak.autogen
-include ../config.mak

# determine version
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE

-include ../GIT-VERSION-FILE

### Build rules

SHELL_PATH ?= $(SHELL)
PERL_PATH ?= /usr/bin/perl

# Shell quote;
bindir_SQ = $(subst ','\'',$(bindir)) #'
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) #'
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) #'

# Quiet generation (unless V=1)
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
QUIET_SUBDIR1 =

ifneq ($(findstring $(MAKEFLAGS),w),w)
PRINT_DIR = --no-print-directory
else # "make -w"
NO_SUBDIR = :
endif

ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
QUIET = @
QUIET_GEN = $(QUIET)echo ' ' GEN $@;
QUIET_SUBDIR0 = +@subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
$(MAKE) $(PRINT_DIR) -C $$subdir
export V
export QUIET
export QUIET_GEN
export QUIET_SUBDIR0
export QUIET_SUBDIR1
endif
endif

all:: gitweb.cgi

ifdef JSMIN
FILES=gitweb.cgi gitweb.min.js
gitweb.cgi: gitweb.perl gitweb.min.js
else # !JSMIN
FILES=gitweb.cgi
gitweb.cgi: gitweb.perl
endif # JSMIN

gitweb.cgi:
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
-e 's|++GIT_BINDIR++|$(bindir)|g' \
-e 's|++GITWEB_CONFIG++|$(GITWEB_CONFIG)|g' \
-e 's|++GITWEB_CONFIG_SYSTEM++|$(GITWEB_CONFIG_SYSTEM)|g' \
-e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \
-e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \
-e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \
-e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \
-e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \
-e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \
-e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \
-e 's|++GITWEB_LIST++|$(GITWEB_LIST)|g' \
-e 's|++GITWEB_HOMETEXT++|$(GITWEB_HOMETEXT)|g' \
-e 's|++GITWEB_CSS++|$(GITWEB_CSS)|g' \
-e 's|++GITWEB_LOGO++|$(GITWEB_LOGO)|g' \
-e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
-e 's|++GITWEB_JS++|$(GITWEB_JS)|g' \
-e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
-e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
$< >$@+ && \
chmod +x $@+ && \
mv $@+ $@

ifdef JSMIN
gitweb.min.js: gitweb.js
$(QUIET_GEN)$(JSMIN) <$< >$@
endif # JSMIN

clean:
$(RM) $(FILES)

.PHONY: all clean .FORCE-GIT-VERSION-FILE

7
gitweb/README

@ -174,7 +174,7 @@ not include variables usually directly set during build): @@ -174,7 +174,7 @@ not include variables usually directly set during build):
Base URL for relative URLs in pages generated by gitweb,
(e.g. $logo, $favicon, @stylesheets if they are relative URLs),
needed and used only for URLs with nonempty PATH_INFO via
<base href="$base_url>. Usually gitweb sets its value correctly,
<base href="$base_url">. Usually gitweb sets its value correctly,
and there is no need to set this variable, e.g. to $my_uri or "/".
* $home_link
Target of the home link on top of all pages (the first part of view
@ -228,6 +228,11 @@ not include variables usually directly set during build): @@ -228,6 +228,11 @@ not include variables usually directly set during build):
repositories from launching cross-site scripting (XSS) attacks. Set this
to true if you don't trust the content of your repositories. The default
is false.
* $maxload
Used to set the maximum load that we will still respond to gitweb queries.
If server load exceed this value then return "503 Service Unavaliable" error.
Server load is taken to be 0 if gitweb cannot determine its value. Set it to
undefined value to turn it off. The default is 300.


Projects list file format

92
gitweb/gitweb.perl

@ -221,6 +221,12 @@ our %avatar_size = ( @@ -221,6 +221,12 @@ our %avatar_size = (
'double' => 32
);

# Used to set the maximum load that we will still respond to gitweb queries.
# If server load exceed this value then return "503 server busy" error.
# If gitweb cannot determined server load, it is taken to be 0.
# Leave it undefined (or set to 'undef') to turn off load checking.
our $maxload = 300;

# You define site-wide feature defaults here; override them with
# $GITWEB_CONFIG as necessary.
our %feature = (
@ -551,12 +557,38 @@ if (-e $GITWEB_CONFIG) { @@ -551,12 +557,38 @@ if (-e $GITWEB_CONFIG) {
do $GITWEB_CONFIG_SYSTEM if -e $GITWEB_CONFIG_SYSTEM;
}

# Get loadavg of system, to compare against $maxload.
# Currently it requires '/proc/loadavg' present to get loadavg;
# if it is not present it returns 0, which means no load checking.
sub get_loadavg {
if( -e '/proc/loadavg' ){
open my $fd, '<', '/proc/loadavg'
or return 0;
my @load = split(/\s+/, scalar <$fd>);
close $fd;

# The first three columns measure CPU and IO utilization of the last one,
# five, and 10 minute periods. The fourth column shows the number of
# currently running processes and the total number of processes in the m/n
# format. The last column displays the last process ID used.
return $load[0] || 0;
}
# additional checks for load average should go here for things that don't export
# /proc/loadavg

return 0;
}

# version of the core git binary
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
$number_of_git_cmds++;

$projects_list ||= $projectroot;

if (defined $maxload && get_loadavg() > $maxload) {
die_error(503, "The load average on the server is too high");
}

# ======================================================================
# input validation and dispatch

@ -3222,7 +3254,7 @@ EOF @@ -3222,7 +3254,7 @@ EOF
print "</head>\n" .
"<body>\n";

if (-f $site_header) {
if (defined $site_header && -f $site_header) {
insert_file($site_header);
}

@ -3323,12 +3355,13 @@ sub git_footer_html { @@ -3323,12 +3355,13 @@ sub git_footer_html {
print "</div>\n"; # class="page_footer"
}

if (-f $site_footer) {
if (defined $site_footer && -f $site_footer) {
insert_file($site_footer);
}

print qq!<script type="text/javascript" src="$javascript"></script>\n!;
if ($action eq 'blame_incremental') {
if (defined $action &&
$action eq 'blame_incremental') {
print qq!<script type="text/javascript">\n!.
qq!startBlame("!. href(action=>"blame_data", -replay=>1) .qq!",\n!.
qq! "!. href() .qq!");\n!.
@ -3354,22 +3387,33 @@ sub git_footer_html { @@ -3354,22 +3387,33 @@ sub git_footer_html {
# 500: The server isn't configured properly, or
# an internal error occurred (e.g. failed assertions caused by bugs), or
# an unknown error occurred (e.g. the git binary died unexpectedly).
# 503: The server is currently unavailable (because it is overloaded,
# or down for maintenance). Generally, this is a temporary state.
sub die_error {
my $status = shift || 500;
my $error = shift || "Internal server error";

my %http_responses = (400 => '400 Bad Request',
403 => '403 Forbidden',
404 => '404 Not Found',
500 => '500 Internal Server Error');
my $extra = shift;

my %http_responses = (
400 => '400 Bad Request',
403 => '403 Forbidden',
404 => '404 Not Found',
500 => '500 Internal Server Error',
503 => '503 Service Unavailable',
);
git_header_html($http_responses{$status});
print <<EOF;
<div class="page_body">
<br /><br />
$status - $error
<br />
</div>
EOF
if (defined $extra) {
print "<hr />\n" .
"$extra\n";
}
print "</div>\n";

git_footer_html();
exit;
}
@ -3471,14 +3515,21 @@ sub git_print_header_div { @@ -3471,14 +3515,21 @@ sub git_print_header_div {
}

sub print_local_time {
print format_local_time(@_);
}

sub format_local_time {
my $localtime = '';
my %date = @_;
if ($date{'hour_local'} < 6) {
printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
$localtime .= sprintf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
} else {
printf(" (%02d:%02d %s)",
$localtime .= sprintf(" (%02d:%02d %s)",
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
}

return $localtime;
}

# Outputs the author name and date in long form
@ -4302,17 +4353,24 @@ sub fill_project_list_info { @@ -4302,17 +4353,24 @@ sub fill_project_list_info {
# print 'sort by' <th> element, generating 'sort by $name' replay link
# if that order is not selected
sub print_sort_th {
print format_sort_th(@_);
}

sub format_sort_th {
my ($name, $order, $header) = @_;
my $sort_th = "";
$header ||= ucfirst($name);

if ($order eq $name) {
print "<th>$header</th>\n";
$sort_th .= "<th>$header</th>\n";
} else {
print "<th>" .
$cgi->a({-href => href(-replay=>1, order=>$name),
-class => "header"}, $header) .
"</th>\n";
$sort_th .= "<th>" .
$cgi->a({-href => href(-replay=>1, order=>$name),
-class => "header"}, $header) .
"</th>\n";
}

return $sort_th;
}

sub git_project_list_body {
@ -4743,7 +4801,7 @@ sub git_project_list { @@ -4743,7 +4801,7 @@ sub git_project_list {
}

git_header_html();
if (-f $home_text) {
if (defined $home_text && -f $home_text) {
print "<div class=\"index_include\">\n";
insert_file($home_text);
print "</div>\n";

1
t/gitweb-lib.sh

@ -25,6 +25,7 @@ our \$favicon = 'file:///$TEST_DIRECTORY/../gitweb/git-favicon.png'; @@ -25,6 +25,7 @@ our \$favicon = 'file:///$TEST_DIRECTORY/../gitweb/git-favicon.png';
our \$projects_list = '';
our \$export_ok = '';
our \$strict_export = '';
our \$maxload = undef;

EOF


30
t/t9501-gitweb-standalone-http-status.sh

@ -33,7 +33,6 @@ test_expect_success \ @@ -33,7 +33,6 @@ test_expect_success \
grep "403 - Snapshot format not allowed" gitweb.output &&
gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" &&
grep "403 - Unsupported snapshot format" gitweb.output'
test_debug 'cat gitweb.output'


cat >>gitweb_config.perl <<\EOF
@ -50,7 +49,6 @@ test_expect_success \ @@ -50,7 +49,6 @@ test_expect_success \
grep "403 - Snapshot format not allowed" gitweb.output &&
gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" &&
grep "Status: 200 OK" gitweb.output'
test_debug 'cat gitweb.output'


cat >>gitweb_config.perl <<\EOF
@ -72,7 +70,7 @@ test_expect_success \ @@ -72,7 +70,7 @@ test_expect_success \
'snapshots: tgz explicitly enabled' \
'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" &&
grep "Status: 200 OK" gitweb.output'
test_debug 'cat gitweb.output'
test_debug 'cat gitweb.headers'


# ----------------------------------------------------------------------
@ -82,7 +80,7 @@ test_expect_success 'snapshots: good tree-ish id' ' @@ -82,7 +80,7 @@ test_expect_success 'snapshots: good tree-ish id' '
gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" &&
grep "Status: 200 OK" gitweb.output
'
test_debug 'cat gitweb.output'
test_debug 'cat gitweb.headers'

test_expect_success 'snapshots: bad tree-ish id' '
gitweb_run "p=.git;a=snapshot;h=frizzumFrazzum;sf=tgz" &&
@ -105,7 +103,7 @@ test_expect_success 'snapshots: good object id' ' @@ -105,7 +103,7 @@ test_expect_success 'snapshots: good object id' '
gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" &&
grep "Status: 200 OK" gitweb.output
'
test_debug 'cat gitweb.output'
test_debug 'cat gitweb.headers'

test_expect_success 'snapshots: bad object id' '
gitweb_run "p=.git;a=snapshot;h=abcdef01234;sf=tgz" &&
@ -114,4 +112,26 @@ test_expect_success 'snapshots: bad object id' ' @@ -114,4 +112,26 @@ test_expect_success 'snapshots: bad object id' '
test_debug 'cat gitweb.output'


# ----------------------------------------------------------------------
# load checking

# always hit the load limit
cat >>gitweb_config.perl <<\EOF
our $maxload = 0;
EOF

test_expect_success 'load checking: load too high (default action)' '
gitweb_run "p=.git" &&
grep "Status: 503 Service Unavailable" gitweb.headers &&
grep "503 - The load average on the server is too high" gitweb.body
'
test_debug 'cat gitweb.log' # just in case
test_debug 'cat gitweb.headers'

# turn off load checking
cat >>gitweb_config.perl <<\EOF
our $maxload = undef;
EOF


test_done

Loading…
Cancel
Save