* [PATCH 0/7] Gitweb caching v4
@ 2010-01-13 9:34 John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 1/7] gitweb: Load checking John 'Warthog9' Hawley
2010-01-14 8:40 ` [PATCH 0/7] Gitweb caching v4 Junio C Hamano
0 siblings, 2 replies; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
Evening everyone,
This is the latest incarnation of gitweb w/ caching. This is
finally at the point where it should probably start either being
considered for inclusion or mainline, or I need to accept that this
will never get in and more perminantely fork (as is the case with
Fedora where this is going in as gitweb-caching as a parrallel rpm
package).
That said this brings the base up to mainline (again), it updates a
number of elements in the caching engine, and this is a much cleaner
break-out of the tree vs. what I am currently developing against.
v4:
- major re-working of the caching layer to use file handle
redirection instead of buffering output
- other minor improvements
v3:
- various minor re-works based on mailing list feedback,
this series was not sent to the mailing list.
v2:
- Better breakout
- You can actually disable the cache now
- John 'Warthog9' Hawley
John 'Warthog9' Hawley (7):
gitweb: Load checking
gitweb: Add option to force version match
gitweb: Makefile improvements
gitweb: Optionally add "git" links in project list page
gitweb: Convert output to using indirect file handle
gitweb: add a get function to compliment print_local_time
gitweb: File based caching layer (from git.kernel.org)
Makefile | 91 ++---
gitweb/Makefile | 129 +++++++
gitweb/README | 14 +-
gitweb/cache.pm | 283 +++++++++++++++
gitweb/gitweb.css | 6 +
gitweb/gitweb.perl | 1021 ++++++++++++++++++++++++++++++----------------------
6 files changed, 1052 insertions(+), 492 deletions(-)
create mode 100644 gitweb/Makefile
create mode 100644 gitweb/cache.pm
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/7] gitweb: Load checking
2010-01-13 9:34 [PATCH 0/7] Gitweb caching v4 John 'Warthog9' Hawley
@ 2010-01-13 9:34 ` John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 2/7] gitweb: Add option to force version match John 'Warthog9' Hawley
2010-01-14 8:40 ` [PATCH 0/7] Gitweb caching v4 Junio C Hamano
1 sibling, 1 reply; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
From: John 'Warthog9' Hawley <warthog9@kernel.org>
This changes slightly the behavior of gitweb, so that it verifies
that the box isn't inundated with before attempting to serve gitweb.
If the box is overloaded, it basically returns a 503 Server Unavailable
until the load falls below the defined threshold. This helps dramatically
if you have a box that's I/O bound, reaches a certain load and you
don't want gitweb, the I/O hog that it is, increasing the pain the
server is already undergoing.
This behavior is controlled by $maxload configuration variable.
Default is a load of 300, which for most cases should never be hit.
Unset it (set it to undefined value, i.e. undef) to turn off checking.
Currently it requires that '/proc/loadavg' file exists, otherwise the
load check is bypassed (load is taken to be 0). So platforms that do
not implement '/proc/loadavg' currently cannot use this feature.
(provisions are included for additional checks to be added by others)
v3 - warthog9: small additional adjustment to indicate where new load
checking should be added for future improvements
v2 - Jakub: switching to using
v1 - warthog9: Initial creation
Signed-off-by: John 'Warthog9' Hawley <warthog9@kernel.org>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/README | 7 ++++++-
gitweb/gitweb.perl | 45 +++++++++++++++++++++++++++++++++++++++++----
2 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/gitweb/README b/gitweb/README
index e34ee79..6c2c8e1 100644
--- a/gitweb/README
+++ b/gitweb/README
@@ -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):
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
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 7e477af..0a07d3a 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -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,6 +557,32 @@ 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;
+}
+
+if (defined $maxload && get_loadavg() > $maxload) {
+ die_error(503, "The load average on the server is too high");
+}
+
# version of the core git binary
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
$number_of_git_cmds++;
@@ -3354,14 +3386,19 @@ 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 %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">
--
1.6.5.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/7] gitweb: Add option to force version match
2010-01-13 9:34 ` [PATCH 1/7] gitweb: Load checking John 'Warthog9' Hawley
@ 2010-01-13 9:34 ` John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 3/7] gitweb: Makefile improvements John 'Warthog9' Hawley
0 siblings, 1 reply; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
From: John 'Warthog9' Hawley <warthog9@kernel.org>
This adds $git_versions_must_match variable, which is set to true
value checks that we are running on the same version of git that we
shipped with, and if not throw '500 Internal Server Error' error.
What is checked is the version of gitweb (embedded in building
gitweb.cgi), against version of runtime git binary used.
Gitweb can usually run with a mismatched git install. This is more
here to give an obvious warning as to whats going on vs. silently
failing.
By default this feature is turned off.
v3 - warthog9: adjust to use die_error instead of recreating it
v2 - Jakub: Changes to make non-default, and change naming
v1 - warthog9: Initial
Signed-off-by: John 'Warthog9' Hawley <warthog9@kernel.org>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/README | 3 +++
gitweb/gitweb.perl | 28 ++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/gitweb/README b/gitweb/README
index 6c2c8e1..608b0f8 100644
--- a/gitweb/README
+++ b/gitweb/README
@@ -233,6 +233,9 @@ not include variables usually directly set during build):
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.
+ * $git_versions_must_match
+ If set, gitweb fails with 500 Internal Server Error if the version of gitweb
+ doesn't match version of git binary. The default is false.
Projects list file format
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 0a07d3a..f17593f 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -221,6 +221,9 @@ our %avatar_size = (
'double' => 32
);
+# If it is true, exit if gitweb version and git binary version don't match
+our $git_versions_must_match = 0;
+
# 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.
@@ -587,6 +590,31 @@ if (defined $maxload && get_loadavg() > $maxload) {
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
$number_of_git_cmds++;
+# Throw an error if git versions does not match, if $git_versions_must_match is true.
+if ($git_versions_must_match &&
+ $git_version ne $version) {
+ my $admin_contact =
+ defined $ENV{'SERVER_ADMIN'} ? ", $ENV{'SERVER_ADMIN'}," : '';
+ my $err_msg = <<EOT;
+Internal Server Error
+<br />
+</div>
+<hr />
+<div class="readme">
+<h1 align="center">*** Warning ***</h1>
+<p>
+This version of gitweb was compiled for <b>@{[esc_html($version)]}</b>,
+however git version <b>@{[esc_html($git_version)]}</b> was found on server,
+and administrator requested strict version checking.
+</p>
+<p>
+Please contact the server administrator${admin_contact} to either configure
+gitweb to allow mismatched versions, or update git or gitweb installation.
+</p>
+EOT
+ die_error(500, $err_msg);
+}
+
$projects_list ||= $projectroot;
# ======================================================================
--
1.6.5.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/7] gitweb: Makefile improvements
2010-01-13 9:34 ` [PATCH 2/7] gitweb: Add option to force version match John 'Warthog9' Hawley
@ 2010-01-13 9:34 ` John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 4/7] gitweb: Optionally add "git" links in project list page John 'Warthog9' Hawley
0 siblings, 1 reply; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
From: John 'Warthog9' Hawley <warthog9@kernel.org>
This commit adjust the main Makefile so you can simply run
make gitweb
which in turn calls gitweb/Makefile. This means that in order to
generate gitweb, you can simply run 'make' from gitweb subdirectory:
cd gitweb
make
Targets gitweb/gitweb.cgi and (dependent on JSMIN being defined)
gitweb/gitweb.min.js in main Makefile are preserved for backward
compatibility.
Signed-off-by: John 'Warthog9' Hawley <warthog9@kernel.org>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Makefile | 91 +++++++++++++++++----------------------
gitweb/Makefile | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+), 51 deletions(-)
create mode 100644 gitweb/Makefile
diff --git a/Makefile b/Makefile
index 4a1e5bc..ffef979 100644
--- a/Makefile
+++ b/Makefile
@@ -280,29 +280,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
@@ -1509,6 +1486,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
@@ -1516,30 +1498,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) $@ $@+ && \
@@ -1566,10 +1531,34 @@ $(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
+ $(QUIET_GEN)$(RM) $@ $@+ && \
+ INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C git_remote_helpers -s \
+ --no-print-directory prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' \
+ instlibdir` && \
+ sed -e '1{' \
+ -e ' s|#!.*python|#!$(PYTHON_PATH_SQ)|' \
+ -e '}' \
+ -e 's|^import sys.*|&; \\\
+ import os; \\\
+ sys.path[0] = os.environ.has_key("GITPYTHONLIB") and \\\
+ os.environ["GITPYTHONLIB"] or \\\
+ "@@INSTLIBDIR@@"|' \
+ -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
+ $@.py >$@+ && \
+ chmod +x $@+ && \
+ mv $@+ $@
+else # NO_PYTHON
+$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : unimplemented.sh
+ $(QUIET_GEN)$(RM) $@ $@+ && \
+ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
+ -e 's|@@REASON@@|NO_PYTHON=$(NO_PYTHON)|g' \
+ unimplemented.sh >$@+ && \
+ chmod +x $@+ && \
+ mv $@+ $@
+endif # NO_PYTHON
configure: configure.ac
$(QUIET_GEN)$(RM) $@ $<+ && \
diff --git a/gitweb/Makefile b/gitweb/Makefile
new file mode 100644
index 0000000..c9eb1ee
--- /dev/null
+++ b/gitweb/Makefile
@@ -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
--
1.6.5.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/7] gitweb: Optionally add "git" links in project list page
2010-01-13 9:34 ` [PATCH 3/7] gitweb: Makefile improvements John 'Warthog9' Hawley
@ 2010-01-13 9:34 ` John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 5/7] gitweb: Convert output to using indirect file handle John 'Warthog9' Hawley
0 siblings, 1 reply; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
From: John 'Warthog9' Hawley <warthog9@kernel.org>
This adds a "git" link for each project in the project list page,
should a common $gitlinkurl_project be defined and not empty. The full
URL of each link is composed of $git_base_url_list[0] and project name.
It is intended for git:// links or that something can reference the git
repository using a smart protocol directly.
This does make the assumption that the git repositories share a common
path, which is no different than the assumption @git_base_url_list makes.
Nothing to date is known to actually make use of introduced link.
Created "git" link follows rel=vcs-* microformat specification:
http://kitenet.net/~joey/rfc/rel-vcs/
Signed-off-by: John 'Warthog9' Hawley <warthog9@kernel.org>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/README | 4 ++++
gitweb/gitweb.perl | 9 +++++++++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/gitweb/README b/gitweb/README
index 608b0f8..2ec66e7 100644
--- a/gitweb/README
+++ b/gitweb/README
@@ -71,6 +71,7 @@ You can specify the following configuration variables when building GIT:
* GITWEB_BASE_URL
Git base URLs used for URL to where fetch project from, i.e. full
URL is "$git_base_url/$project". Shown on projects summary page.
+ If it begins with "git://" it is also used for $gitlinkurl_base, see below.
Repository URL for project can be also configured per repository; this
takes precedence over URLs composed from base URL and a project name.
Note that you can setup multiple base URLs (for example one for
@@ -204,6 +205,9 @@ not include variables usually directly set during build):
access, and one for http:// "dumb" protocol access). Note that per
repository configuration in 'cloneurl' file, or as values of gitweb.url
project config.
+ * $gitlinkurl_project
+ Boolean (if it is defined and not empty) to add "git" link in
+ projects list, for each project. Full URL is "$git_base_url_list[0]/$project".
* $default_blob_plain_mimetype
Default mimetype for blob_plain (raw) view, if mimetype checking
doesn't result in some other type; by default 'text/plain'.
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index f17593f..b8f2a67 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -224,6 +224,11 @@ our %avatar_size = (
# If it is true, exit if gitweb version and git binary version don't match
our $git_versions_must_match = 0;
+# This is a boolean on/off switch to add a "git" link for each project in
+# project list. It uses the first element of @git_base_url_list as the
+# base of the URL. Full URL is "$git_base_url_list[0]/$project".
+our $gitlinkurl_project = '';
+
# 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.
@@ -4473,6 +4478,10 @@ sub git_project_list_body {
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"log")}, "log") . " | " .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"tree")}, "tree") .
($pr->{'forks'} ? " | " . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"forks")}, "forks") : '') .
+ ($gitlinkurl_project && $git_base_url_list[0] ?
+ " | " . $cgi->a({-href=> $git_base_url_list[0] ."/$pr->{'path'}",
+ -rel=>"vcs-git"}, "git")
+ : '') .
"</td>\n" .
"</tr>\n";
}
--
1.6.5.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/7] gitweb: Convert output to using indirect file handle
2010-01-13 9:34 ` [PATCH 4/7] gitweb: Optionally add "git" links in project list page John 'Warthog9' Hawley
@ 2010-01-13 9:34 ` John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 6/7] gitweb: add a get function to compliment print_local_time John 'Warthog9' Hawley
0 siblings, 1 reply; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
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 | 876 ++++++++++++++++++++++++++--------------------------
1 files changed, 442 insertions(+), 434 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index b8f2a67..3b6bc06 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -455,6 +455,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};
@@ -3091,7 +3098,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;
}
@@ -3208,10 +3215,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 <<EOF;
+ print {$output_handler} <<EOF;
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
@@ -3226,16 +3233,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 "<base href=\"".esc_url($base_url)."\" />\n";
+ print {$output_handler} "<base href=\"".esc_url($base_url)."\" />\n";
}
# print out each stylesheet that exist, providing backwards capability
# for those people who defined $stylesheet in a config file
if (defined $stylesheet) {
- print '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n";
+ print {$output_handler} '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n";
} else {
foreach my $stylesheet (@stylesheets) {
next unless $stylesheet;
- print '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n";
+ print {$output_handler} '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n";
}
}
if (defined $project) {
@@ -3254,7 +3261,7 @@ EOF
$href_params{'action'} = $type;
$link_attr{'-href'} = href(%href_params);
- print "<link ".
+ print {$output_handler} "<link ".
"rel=\"$link_attr{'-rel'}\" ".
"title=\"$link_attr{'-title'}\" ".
"href=\"$link_attr{'-href'}\" ".
@@ -3264,7 +3271,7 @@ EOF
$href_params{'extra_options'} = '--no-merges';
$link_attr{'-href'} = href(%href_params);
$link_attr{'-title'} .= ' (no merges)';
- print "<link ".
+ print {$output_handler} "<link ".
"rel=\"$link_attr{'-rel'}\" ".
"title=\"$link_attr{'-title'}\" ".
"href=\"$link_attr{'-href'}\" ".
@@ -3273,37 +3280,37 @@ EOF
}
} else {
- printf('<link rel="alternate" title="%s projects list" '.
+ printf( {$output_handler} '<link rel="alternate" title="%s projects list" '.
'href="%s" type="text/plain; charset=utf-8" />'."\n",
$site_name, href(project=>undef, action=>"project_index"));
- printf('<link rel="alternate" title="%s projects feeds" '.
+ printf( {$output_handler} '<link rel="alternate" title="%s projects feeds" '.
'href="%s" type="text/x-opml" />'."\n",
$site_name, href(project=>undef, action=>"opml"));
}
if (defined $favicon) {
- print qq(<link rel="shortcut icon" href="$favicon" type="image/png" />\n);
+ print {$output_handler} qq(<link rel="shortcut icon" href="$favicon" type="image/png" />\n);
}
- print "</head>\n" .
+ print {$output_handler} "</head>\n" .
"<body>\n";
if (-f $site_header) {
insert_file($site_header);
}
- print "<div class=\"page_header\">\n" .
+ print {$output_handler} "<div class=\"page_header\">\n" .
$cgi->a({-href => esc_url($logo_url),
-title => $logo_label},
qq(<img src="$logo" width="72" height="27" alt="git" class="logo"/>));
- 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 "</div>\n";
+ print {$output_handler} "</div>\n";
my $have_search = gitweb_check_feature('search');
if (defined $project && $have_search) {
@@ -3323,7 +3330,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) .
"<div class=\"search\">\n" .
(!$use_pathinfo &&
$cgi->input({-name=>"p", -value=>$project, -type=>"hidden"}) . "\n") .
@@ -3346,11 +3353,11 @@ EOF
sub git_footer_html {
my $feed_class = 'rss_logo';
- print "<div class=\"page_footer\">\n";
+ print {$output_handler} "<div class=\"page_footer\">\n";
if (defined $project) {
my $descr = git_get_project_description($project);
if (defined $descr) {
- print "<div class=\"page_footer_text\">" . esc_html($descr) . "</div>\n";
+ print {$output_handler} "<div class=\"page_footer_text\">" . esc_html($descr) . "</div>\n";
}
my %href_params = get_feed_info();
@@ -3361,22 +3368,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 "</div>\n"; # class="page_footer"
+ print {$output_handler} "</div>\n"; # class="page_footer"
if (defined $t0 && gitweb_check_feature('timed')) {
- print "<div id=\"generating_info\">\n";
- print 'This page took '.
+ print {$output_handler} "<div id=\"generating_info\">\n";
+ print {$output_handler} 'This page took '.
'<span id="generating_time" class="time_span">'.
Time::HiRes::tv_interval($t0, [Time::HiRes::gettimeofday()]).
' seconds </span>'.
@@ -3385,26 +3392,26 @@ sub git_footer_html {
$number_of_git_cmds.
'</span> git commands '.
" to generate.\n";
- print "</div>\n"; # class="page_footer"
+ print {$output_handler} "</div>\n"; # class="page_footer"
}
if (-f $site_footer) {
insert_file($site_footer);
}
- print qq!<script type="text/javascript" src="$javascript"></script>\n!;
+ print {$output_handler} qq!<script type="text/javascript" src="$javascript"></script>\n!;
if ($action eq 'blame_incremental') {
- print qq!<script type="text/javascript">\n!.
+ print {$output_handler} qq!<script type="text/javascript">\n!.
qq!startBlame("!. href(action=>"blame_data", -replay=>1) .qq!",\n!.
qq! "!. href() .qq!");\n!.
qq!</script>\n!;
} elsif (gitweb_check_feature('javascript-actions')) {
- print qq!<script type="text/javascript">\n!.
+ print {$output_handler} qq!<script type="text/javascript">\n!.
qq!window.onload = fixLinks;\n!.
qq!</script>\n!;
}
- print "</body>\n" .
+ print {$output_handler} "</body>\n" .
"</html>";
}
@@ -3488,12 +3495,12 @@ sub git_print_page_nav {
$arg{$label}{'_href'} = $link;
}
- print "<div class=\"page_nav\">\n" .
+ print {$output_handler} "<div class=\"page_nav\">\n" .
(join " | ",
map { $_ eq $current ?
$_ : $cgi->a({-href => ($arg{$_}{_href} ? $arg{$_}{_href} : href(%{$arg{$_}}))}, "$_")
} @navs);
- print "<br/>\n$extra<br/>\n" .
+ print {$output_handler} "<br/>\n$extra<br/>\n" .
"</div>\n";
}
@@ -3534,7 +3541,7 @@ sub git_print_header_div {
$args{'hash'} = $hash if $hash;
$args{'hash_base'} = $hash_base if $hash_base;
- print "<div class=\"header\">\n" .
+ print {$output_handler} "<div class=\"header\">\n" .
$cgi->a({-href => href(%args), -class => "title"},
$title ? $title : $action) .
"\n</div>\n";
@@ -3543,10 +3550,10 @@ sub git_print_header_div {
sub print_local_time {
my %date = @_;
if ($date{'hour_local'} < 6) {
- printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
+ printf({$output_handler} " (<span class=\"atnight\">%02d:%02d</span> %s)",
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
} else {
- printf(" (%02d:%02d %s)",
+ printf({$output_handler} " (%02d:%02d %s)",
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
}
}
@@ -3559,11 +3566,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)
. "</$tag>\n";
}
@@ -3579,7 +3586,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 "<tr><td>$who</td><td>" .
+ print {$output_handler} "<tr><td>$who</td><td>" .
format_search_author($co->{"${who}_name"}, $who,
esc_html($co->{"${who}_name"})) . " " .
format_search_author($co->{"${who}_email"}, $who,
@@ -3589,8 +3596,8 @@ sub git_print_authorship_rows {
"</td></tr>\n" .
"<tr>" .
"<td></td><td> $wd{'rfc2822'}";
- print_local_time(%wd);
- print "</td>" .
+ print {$output_handler} get_local_time(%wd);
+ print {$output_handler} "</td>" .
"</tr>\n";
}
}
@@ -3600,11 +3607,10 @@ sub git_print_page_path {
my $type = shift;
my $hb = shift;
-
- print "<div class=\"page_path\">";
- print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
+ print {$output_handler} "<div class=\"page_path\">";
+ 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;
@@ -3612,25 +3618,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 "<br/></div>\n";
+ print {$output_handler} "<br/></div>\n";
}
sub git_print_log {
@@ -3654,7 +3660,7 @@ sub git_print_log {
$signoff = 1;
$empty = 0;
if (! $opts{'-remove_signoff'}) {
- print "<span class=\"signoff\">" . esc_html($line) . "</span><br/>\n";
+ print {$output_handler} "<span class=\"signoff\">" . esc_html($line) . "</span><br/>\n";
next;
} else {
# remove signoff lines
@@ -3673,12 +3679,12 @@ sub git_print_log {
$empty = 0;
}
- print format_log_line_html($line) . "<br/>\n";
+ print {$output_handler} format_log_line_html($line) . "<br/>\n";
}
if ($opts{'-final_empty_line'}) {
# end with single empty line
- print "<br/>\n" unless $empty;
+ print {$output_handler} "<br/>\n" unless $empty;
}
}
@@ -3751,12 +3757,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 "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n";
+ print {$output_handler} "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n";
if (exists $t->{'size'}) {
- print "<td class=\"size\">$t->{'size'}</td>\n";
+ print {$output_handler} "<td class=\"size\">$t->{'size'}</td>\n";
}
if ($t->{'type'} eq "blob") {
- print "<td class=\"list\">" .
+ print {$output_handler} "<td class=\"list\">" .
$cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
file_name=>"$basedir$t->{'name'}", %base_key),
-class => "list"}, esc_path($t->{'name'}));
@@ -3765,71 +3771,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 "</td>\n";
- print "<td class=\"link\">";
- print $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
+ print {$output_handler} "</td>\n";
+ print {$output_handler} "<td class=\"link\">";
+ 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 "</td>\n";
+ print {$output_handler} "</td>\n";
} elsif ($t->{'type'} eq "tree") {
- print "<td class=\"list\">";
- print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
+ print {$output_handler} "<td class=\"list\">";
+ print {$output_handler} $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
file_name=>"$basedir$t->{'name'}",
%base_key)},
esc_path($t->{'name'}));
- print "</td>\n";
- print "<td class=\"link\">";
- print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
+ print {$output_handler} "</td>\n";
+ print {$output_handler} "<td class=\"link\">";
+ 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 "</td>\n";
+ print {$output_handler} "</td>\n";
} else {
# unknown object: we can only present history for it
# (this includes 'commit' object, i.e. submodule support)
- print "<td class=\"list\">" .
+ print {$output_handler} "<td class=\"list\">" .
esc_path($t->{'name'}) .
"</td>\n";
- print "<td class=\"link\">";
+ print {$output_handler} "<td class=\"link\">";
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 "</td>\n";
+ print {$output_handler} "</td>\n";
}
}
@@ -3876,13 +3882,13 @@ sub git_difftree_body {
my ($difftree, $hash, @parents) = @_;
my ($parent) = $parents[0];
my $have_blame = gitweb_check_feature('blame');
- print "<div class=\"list_head\">\n";
+ print {$output_handler} "<div class=\"list_head\">\n";
if ($#{$difftree} > 10) {
- print(($#{$difftree} + 1) . " files changed:\n");
+ print {$output_handler} (($#{$difftree} + 1) . " files changed:\n");
}
- print "</div>\n";
+ print {$output_handler} "</div>\n";
- print "<table class=\"" .
+ print {$output_handler} "<table class=\"" .
(@parents > 1 ? "combined " : "") .
"diff_tree\">\n";
@@ -3890,11 +3896,11 @@ sub git_difftree_body {
my $has_header = @$difftree && @parents > 1 && $action eq 'commitdiff';
if ($has_header) {
# table header
- print "<thead><tr>\n" .
+ print {$output_handler} "<thead><tr>\n" .
"<th></th><th></th>\n"; # filename, patchN link
for (my $i = 0; $i < @parents; $i++) {
my $par = $parents[$i];
- print "<th>" .
+ print {$output_handler} "<th>" .
$cgi->a({-href => href(action=>"commitdiff",
hash=>$hash, hash_parent=>$par),
-title => 'commitdiff to parent number ' .
@@ -3902,7 +3908,7 @@ sub git_difftree_body {
$i+1) .
" </th>\n";
}
- print "</tr></thead>\n<tbody>\n";
+ print {$output_handler} "</tr></thead>\n<tbody>\n";
}
my $alternate = 1;
@@ -3911,9 +3917,9 @@ sub git_difftree_body {
my $diff = parsed_difftree_line($line);
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
@@ -3924,14 +3930,14 @@ sub git_difftree_body {
if (!is_deleted($diff)) {
# file exists in the result (child) commit
- print "<td>" .
+ print {$output_handler} "<td>" .
$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'})) .
"</td>\n";
} else {
- print "<td>" .
+ print {$output_handler} "<td>" .
esc_path($diff->{'to_file'}) .
"</td>\n";
}
@@ -3939,7 +3945,7 @@ sub git_difftree_body {
if ($action eq 'commitdiff') {
# link to patch
$patchno++;
- print "<td class=\"link\">" .
+ print {$output_handler} "<td class=\"link\">" .
$cgi->a({-href => "#patch$patchno"}, "patch") .
" | " .
"</td>\n";
@@ -3957,9 +3963,9 @@ sub git_difftree_body {
$not_deleted ||= ($status ne 'D');
if ($status eq 'A') {
- print "<td class=\"link\" align=\"right\"> | </td>\n";
+ print {$output_handler} "<td class=\"link\" align=\"right\"> | </td>\n";
} elsif ($status eq 'D') {
- print "<td class=\"link\">" .
+ print {$output_handler} "<td class=\"link\">" .
$cgi->a({-href => href(action=>"blob",
hash_base=>$hash,
hash=>$from_hash,
@@ -3968,11 +3974,11 @@ sub git_difftree_body {
" | </td>\n";
} else {
if ($diff->{'to_id'} eq $from_hash) {
- print "<td class=\"link nochange\">";
+ print {$output_handler} "<td class=\"link nochange\">";
} else {
- print "<td class=\"link\">";
+ print {$output_handler} "<td class=\"link\">";
}
- 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,
@@ -3984,24 +3990,24 @@ sub git_difftree_body {
}
}
- print "<td class=\"link\">";
+ print {$output_handler} "<td class=\"link\">";
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 "</td>\n";
+ print {$output_handler} "</td>\n";
- print "</tr>\n";
+ print {$output_handler} "</tr>\n";
next; # instead of 'else' clause, to avoid extra indent
}
# else ordinary diff
@@ -4027,51 +4033,51 @@ sub git_difftree_body {
my $mode_chng = "<span class=\"file_status new\">[new $to_file_type";
$mode_chng .= " with mode: $to_mode_str" if $to_mode_str;
$mode_chng .= "]</span>";
- print "<td>";
- print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
+ print {$output_handler} "<td>";
+ 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 "</td>\n";
- print "<td>$mode_chng</td>\n";
- print "<td class=\"link\">";
+ print {$output_handler} "</td>\n";
+ print {$output_handler} "<td>$mode_chng</td>\n";
+ print {$output_handler} "<td class=\"link\">";
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 "</td>\n";
+ print {$output_handler} "</td>\n";
} elsif ($diff->{'status'} eq "D") { # deleted
my $mode_chng = "<span class=\"file_status deleted\">[deleted $from_file_type]</span>";
- print "<td>";
- print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'},
+ print {$output_handler} "<td>";
+ 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 "</td>\n";
- print "<td>$mode_chng</td>\n";
- print "<td class=\"link\">";
+ print {$output_handler} "</td>\n";
+ print {$output_handler} "<td>$mode_chng</td>\n";
+ print {$output_handler} "<td class=\"link\">";
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 "</td>\n";
+ print {$output_handler} "</td>\n";
} elsif ($diff->{'status'} eq "M" || $diff->{'status'} eq "T") { # modified, or type changed
my $mode_chnge = "";
@@ -4089,39 +4095,39 @@ sub git_difftree_body {
}
$mode_chnge .= "]</span>\n";
}
- print "<td>";
- print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
+ print {$output_handler} "<td>";
+ 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 "</td>\n";
- print "<td>$mode_chnge</td>\n";
- print "<td class=\"link\">";
+ print {$output_handler} "</td>\n";
+ print {$output_handler} "<td>$mode_chnge</td>\n";
+ print {$output_handler} "<td class=\"link\">";
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 "</td>\n";
+ print {$output_handler} "</td>\n";
} elsif ($diff->{'status'} eq "R" || $diff->{'status'} eq "C") { # renamed or copied
my %status_name = ('R' => 'moved', 'C' => 'copied');
@@ -4131,7 +4137,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 "<td>" .
+ print {$output_handler} "<td>" .
$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'})) . "</td>\n" .
@@ -4144,35 +4150,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 "</td>\n";
+ print {$output_handler} "</td>\n";
} # we should not encounter Unmerged (U) or Unknown (X) status
- print "</tr>\n";
+ print {$output_handler} "</tr>\n";
}
- print "</tbody>" if $has_header;
- print "</table>\n";
+ print {$output_handler} "</tbody>" if $has_header;
+ print {$output_handler} "</table>\n";
}
sub git_patchset_body {
@@ -4187,7 +4193,7 @@ sub git_patchset_body {
my $to_name;
my (%from, %to);
- print "<div class=\"patchset\">\n";
+ print {$output_handler} "<div class=\"patchset\">\n";
# skip to first patch
while ($patch_line = <$fd>) {
@@ -4215,7 +4221,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 "<div class=\"patch cont\">\n";
+ print {$output_handler} "<div class=\"patch cont\">\n";
} else {
# advance raw git-diff output if needed
$patch_idx++ if defined $diffinfo;
@@ -4227,7 +4233,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 "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
+ print {$output_handler} "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
format_diff_cc_simplified($diffinfo, @hash_parents) .
"</div>\n"; # class="patch"
@@ -4244,7 +4250,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 "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n";
+ print {$output_handler} "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n";
}
# git diff header
@@ -4252,25 +4258,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 "<div class=\"diff extended_header\">\n";
+ print {$output_handler} "<div class=\"diff extended_header\">\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 "</div>\n"; # class="diff extended_header"
+ print {$output_handler} "</div>\n"; # class="diff extended_header"
# from-file/to-file diff header
if (! $patch_line) {
- print "</div>\n"; # class="patch"
+ print {$output_handler} "</div>\n"; # class="patch"
last PATCH;
}
next PATCH if ($patch_line =~ m/^diff /);
@@ -4281,7 +4287,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);
@@ -4292,11 +4298,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 "</div>\n"; # class="patch"
+ print {$output_handler} "</div>\n"; # class="patch"
}
# for compact combined (--cc) format, with chunk and patch simpliciaction
@@ -4308,7 +4314,7 @@ sub git_patchset_body {
$diffinfo = parsed_difftree_line($difftree->[$patch_idx]);
# generate anchor for "patch" links in difftree / whatchanged part
- print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
+ print {$output_handler} "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
format_diff_cc_simplified($diffinfo, @hash_parents) .
"</div>\n"; # class="patch"
@@ -4317,13 +4323,13 @@ sub git_patchset_body {
if ($patch_number == 0) {
if (@hash_parents > 1) {
- print "<div class=\"diff nodifferences\">Trivial merge</div>\n";
+ print {$output_handler} "<div class=\"diff nodifferences\">Trivial merge</div>\n";
} else {
- print "<div class=\"diff nodifferences\">No differences found</div>\n";
+ print {$output_handler} "<div class=\"diff nodifferences\">No differences found</div>\n";
}
}
- print "</div>\n"; # class="patchset"
+ print {$output_handler} "</div>\n"; # class="patchset"
}
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
@@ -4376,9 +4382,9 @@ sub print_sort_th {
$header ||= ucfirst($name);
if ($order eq $name) {
- print "<th>$header</th>\n";
+ print {$output_handler} "<th>$header</th>\n";
} else {
- print "<th>" .
+ print {$output_handler} "<th>" .
$cgi->a({-href => href(-replay=>1, order=>$name),
-class => "header"}, $header) .
"</th>\n";
@@ -4418,20 +4424,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 "<table class=\"project_list\">\n";
+ print {$output_handler} "<table class=\"project_list\">\n";
unless ($no_header) {
- print "<tr>\n";
+ print {$output_handler} "<tr>\n";
if ($check_forks) {
- print "<th></th>\n";
+ print {$output_handler} "<th></th>\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 "<th></th>\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} "<th></th>\n" . # for links
"</tr>\n";
}
my $alternate = 1;
@@ -4451,26 +4457,26 @@ sub git_project_list_body {
}
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
if ($check_forks) {
- print "<td>";
+ print {$output_handler} "<td>";
if ($pr->{'forks'}) {
- print "<!-- $pr->{'forks'} -->\n";
- print $cgi->a({-href => href(project=>$pr->{'path'}, action=>"forks")}, "+");
+ print {$output_handler} "<!-- $pr->{'forks'} -->\n";
+ print {$output_handler} $cgi->a({-href => href(project=>$pr->{'path'}, action=>"forks")}, "+");
}
- print "</td>\n";
+ print {$output_handler} "</td>\n";
}
- print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
- -class => "list"}, esc_html($pr->{'path'})) . "</td>\n" .
+ print {$output_handler} "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
+ -class => "list"}, esc_html($pr->{'path'})) ."</td>\n".
"<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
-class => "list", -title => $pr->{'descr_long'}},
esc_html($pr->{'descr'})) . "</td>\n" .
"<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
- print "<td class=\"". age_class($pr->{'age'}) . "\">" .
+ print {$output_handler} "<td class=\"". age_class($pr->{'age'}) . "\">" .
(defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " .
@@ -4486,14 +4492,14 @@ sub git_project_list_body {
"</tr>\n";
}
if (defined $extra) {
- print "<tr>\n";
+ print {$output_handler} "<tr>\n";
if ($check_forks) {
- print "<td></td>\n";
+ print {$output_handler} "<td></td>\n";
}
- print "<td colspan=\"5\">$extra</td>\n" .
+ print {$output_handler} "<td colspan=\"5\">$extra</td>\n" .
"</tr>\n";
}
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
sub git_log_body {
@@ -4513,7 +4519,7 @@ sub git_log_body {
"<span class=\"age\">$co{'age_string'}</span>" .
esc_html($co{'title'}) . $ref,
$commit);
- print "<div class=\"title_text\">\n" .
+ print {$output_handler} "<div class=\"title_text\">\n" .
"<div class=\"log_link\">\n" .
$cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") .
" | " .
@@ -4523,16 +4529,16 @@ sub git_log_body {
"<br/>\n" .
"</div>\n";
git_print_authorship(\%co, -tag => 'span');
- print "<br/>\n</div>\n";
+ print {$output_handler} "<br/>\n</div>\n";
- print "<div class=\"log_body\">\n";
+ print {$output_handler} "<div class=\"log_body\">\n";
git_print_log($co{'comment'}, -final_empty_line=> 1);
- print "</div>\n";
+ print {$output_handler} "</div>\n";
}
if ($extra) {
- print "<div class=\"page_nav\">\n";
- print "$extra\n";
- print "</div>\n";
+ print {$output_handler} "<div class=\"page_nav\">\n";
+ print {$output_handler} "$extra\n";
+ print {$output_handler} "</div>\n";
}
}
@@ -4543,41 +4549,41 @@ sub git_shortlog_body {
$from = 0 unless defined $from;
$to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to);
- print "<table class=\"shortlog\">\n";
+ print {$output_handler} "<table class=\"shortlog\">\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 "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
# git_summary() used print "<td><i>$co{'age_string'}</i></td>\n" .
- print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+ print {$output_handler} "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
format_author_html('td', \%co, 10) . "<td>";
- 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 "</td>\n" .
+ print {$output_handler} "</td>\n" .
"<td class=\"link\">" .
$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 "</td>\n" .
+ print {$output_handler} "</td>\n" .
"</tr>\n";
}
if (defined $extra) {
- print "<tr>\n" .
+ print {$output_handler} "<tr>\n" .
"<td colspan=\"4\">$extra</td>\n" .
"</tr>\n";
}
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
sub git_history_body {
@@ -4588,7 +4594,7 @@ sub git_history_body {
$from = 0 unless defined $from;
$to = $#{$commitlist} unless (defined $to && $to <= $#{$commitlist});
- print "<table class=\"history\">\n";
+ print {$output_handler} "<table class=\"history\">\n";
my $alternate = 1;
for (my $i = $from; $i <= $to; $i++) {
my %co = %{$commitlist->[$i]};
@@ -4600,18 +4606,18 @@ sub git_history_body {
my $ref = format_ref_marker($refs, $commit);
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+ print {$output_handler} "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
# shortlog: format_author_html('td', \%co, 10)
format_author_html('td', \%co, 15, 3) . "<td>";
# 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 "</td>\n" .
+ print {$output_handler} "</td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => href(action=>$ftype, hash_base=>$commit, file_name=>$file_name)}, $ftype) . " | " .
$cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff");
@@ -4621,7 +4627,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,
@@ -4629,15 +4635,15 @@ sub git_history_body {
"diff to current");
}
}
- print "</td>\n" .
+ print {$output_handler} "</td>\n" .
"</tr>\n";
}
if (defined $extra) {
- print "<tr>\n" .
+ print {$output_handler} "<tr>\n" .
"<td colspan=\"4\">$extra</td>\n" .
"</tr>\n";
}
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
sub git_tags_body {
@@ -4646,7 +4652,7 @@ sub git_tags_body {
$from = 0 unless defined $from;
$to = $#{$taglist} if (!defined $to || $#{$taglist} < $to);
- print "<table class=\"tags\">\n";
+ print {$output_handler} "<table class=\"tags\">\n";
my $alternate = 1;
for (my $i = $from; $i <= $to; $i++) {
my $entry = $taglist->[$i];
@@ -4657,50 +4663,50 @@ sub git_tags_body {
$comment_short = chop_str($comment, 30, 5);
}
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
if (defined $tag{'age'}) {
- print "<td><i>$tag{'age'}</i></td>\n";
+ print {$output_handler} "<td><i>$tag{'age'}</i></td>\n";
} else {
- print "<td></td>\n";
+ print {$output_handler} "<td></td>\n";
}
- print "<td>" .
+ print {$output_handler} "<td>" .
$cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'}),
-class => "list name"}, esc_html($tag{'name'})) .
"</td>\n" .
"<td>";
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 "</td>\n" .
+ print {$output_handler} "</td>\n" .
"<td class=\"selflink\">";
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 "</td>\n" .
+ print {$output_handler} "</td>\n" .
"<td class=\"link\">" . " | " .
$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 "</td>\n" .
+ print {$output_handler} "</td>\n" .
"</tr>";
}
if (defined $extra) {
- print "<tr>\n" .
+ print {$output_handler} "<tr>\n" .
"<td colspan=\"5\">$extra</td>\n" .
"</tr>\n";
}
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
sub git_heads_body {
@@ -4709,19 +4715,19 @@ sub git_heads_body {
$from = 0 unless defined $from;
$to = $#{$headlist} if (!defined $to || $#{$headlist} < $to);
- print "<table class=\"heads\">\n";
+ print {$output_handler} "<table class=\"heads\">\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 "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td><i>$ref{'age'}</i></td>\n" .
+ print {$output_handler} "<td><i>$ref{'age'}</i></td>\n" .
($curr ? "<td class=\"current_head\">" : "<td>") .
$cgi->a({-href => href(action=>"shortlog", hash=>$ref{'fullname'}),
-class => "list name"},esc_html($ref{'name'})) .
@@ -4734,11 +4740,11 @@ sub git_heads_body {
"</tr>";
}
if (defined $extra) {
- print "<tr>\n" .
+ print {$output_handler} "<tr>\n" .
"<td colspan=\"3\">$extra</td>\n" .
"</tr>\n";
}
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
sub git_search_grep_body {
@@ -4746,7 +4752,7 @@ sub git_search_grep_body {
$from = 0 unless defined $from;
$to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to);
- print "<table class=\"commit_search\">\n";
+ print {$output_handler} "<table class=\"commit_search\">\n";
my $alternate = 1;
for (my $i = $from; $i <= $to; $i++) {
my %co = %{$commitlist->[$i]};
@@ -4755,12 +4761,12 @@ sub git_search_grep_body {
}
my $commit = $co{'id'};
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+ print {$output_handler} "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
format_author_html('td', \%co, 15, 5) .
"<td>" .
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
@@ -4780,25 +4786,25 @@ sub git_search_grep_body {
$match = esc_html($match);
$trail = esc_html($trail);
- print "$lead<span class=\"match\">$match</span>$trail<br />";
+ print {$output_handler} "$lead<span class=\"match\">$match</span>$trail<br />";
}
}
- print "</td>\n" .
+ print {$output_handler} "</td>\n" .
"<td class=\"link\">" .
$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 "</td>\n" .
+ print {$output_handler} "</td>\n" .
"</tr>\n";
}
if (defined $extra) {
- print "<tr>\n" .
+ print {$output_handler} "<tr>\n" .
"<td colspan=\"3\">$extra</td>\n" .
"</tr>\n";
}
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
## ======================================================================
@@ -4818,11 +4824,11 @@ sub git_project_list {
git_header_html();
if (-f $home_text) {
- print "<div class=\"index_include\">\n";
+ print {$output_handler} "<div class=\"index_include\">\n";
insert_file($home_text);
- print "</div>\n";
+ print {$output_handler} "</div>\n";
}
- print $cgi->startform(-method => "get") .
+ print {$output_handler} $cgi->startform(-method => "get") .
"<p class=\"projsearch\">Search:\n" .
$cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
"</p>" .
@@ -4852,7 +4858,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"');
@@ -4869,7 +4875,7 @@ sub git_project_index {
$path =~ s/ /\+/g;
$owner =~ s/ /\+/g;
- print "$path $owner\n";
+ print {$output_handler} "$path $owner\n";
}
}
@@ -4896,12 +4902,12 @@ sub git_summary {
git_header_html();
git_print_page_nav('summary','', $head);
- print "<div class=\"title\"> </div>\n";
- print "<table class=\"projects_list\">\n" .
+ print {$output_handler} "<div class=\"title\"> </div>\n";
+ print {$output_handler} "<table class=\"projects_list\">\n" .
"<tr id=\"metadata_desc\"><td>description</td><td>" . esc_html($descr) . "</td></tr>\n" .
"<tr id=\"metadata_owner\"><td>owner</td><td>" . esc_html($owner) . "</td></tr>\n";
if (defined $cd{'rfc2822'}) {
- print "<tr id=\"metadata_lchange\"><td>last change</td><td>$cd{'rfc2822'}</td></tr>\n";
+ print {$output_handler} "<tr id=\"metadata_lchange\"><td>last change</td><td>$cd{'rfc2822'}</td></tr>\n";
}
# use per project git URL list in $projectroot/$project/cloneurl
@@ -4911,7 +4917,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 "<tr class=\"metadata_url\"><td>$url_tag</td><td>$git_url</td></tr>\n";
+ print {$output_handler} "<tr class=\"metadata_url\"><td>$url_tag</td><td>$git_url</td></tr>\n";
$url_tag = "";
}
@@ -4920,23 +4926,23 @@ sub git_summary {
if ($show_ctags) {
my $ctags = git_get_project_ctags($project);
my $cloud = git_populate_project_tagcloud($ctags);
- print "<tr id=\"metadata_ctags\"><td>Content tags:<br />";
- print "</td>\n<td>" unless %$ctags;
- print "<form action=\"$show_ctags\" method=\"post\"><input type=\"hidden\" name=\"p\" value=\"$project\" />Add: <input type=\"text\" name=\"t\" size=\"8\" /></form>";
- print "</td>\n<td>" if %$ctags;
- print git_show_project_tagcloud($cloud, 48);
- print "</td></tr>";
+ print {$output_handler} "<tr id=\"metadata_ctags\"><td>Content tags:<br />";
+ print {$output_handler} "</td>\n<td>" unless %$ctags;
+ print {$output_handler} "<form action=\"$show_ctags\" method=\"post\"><input type=\"hidden\" name=\"p\" value=\"$project\" />Add: <input type=\"text\" name=\"t\" size=\"8\" /></form>";
+ print {$output_handler} "</td>\n<td>" if %$ctags;
+ print {$output_handler} git_show_project_tagcloud($cloud, 48);
+ print {$output_handler} "</td></tr>";
}
- print "</table>\n";
+ print {$output_handler} "</table>\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 "<div class=\"title\">readme</div>\n" .
+ print {$output_handler} "<div class=\"title\">readme</div>\n" .
"<div class=\"readme\">\n";
insert_file("$projectroot/$project/README.html");
- print "\n</div>\n"; # class="readme"
+ print {$output_handler} "\n</div>\n"; # class="readme"
}
# we need to request one more than 16 (0..15) to check if
@@ -4985,7 +4991,7 @@ sub git_tag {
}
git_print_header_div('commit', esc_html($tag{'name'}), $hash);
- print "<div class=\"title_text\">\n" .
+ print {$output_handler} "<div class=\"title_text\">\n" .
"<table class=\"object_header\">\n" .
"<tr>\n" .
"<td>object</td>\n" .
@@ -4997,15 +5003,15 @@ sub git_tag {
if (defined($tag{'author'})) {
git_print_authorship_rows(\%tag, 'author');
}
- print "</table>\n\n" .
+ print {$output_handler} "</table>\n\n" .
"</div>\n";
- print "<div class=\"page_body\">";
+ print {$output_handler} "<div class=\"page_body\">";
my $comment = $tag{'comment'};
foreach my $line (@$comment) {
chomp $line;
- print esc_html($line, -nbsp=>1) . "<br/>\n";
+ print {$output_handler} esc_html($line, -nbsp=>1) . "<br/>\n";
}
- print "</div>\n";
+ print {$output_handler} "</div>\n";
git_footer_html();
}
@@ -5056,21 +5062,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;
}
@@ -5103,20 +5111,20 @@ sub git_blame_common {
# page body
if ($format eq 'incremental') {
- print "<noscript>\n<div class=\"error\"><center><b>\n".
+ print {$output_handler} "<noscript>\n<div class=\"error\"><center><b>\n".
"This page requires JavaScript to run.\n Use ".
$cgi->a({-href => href(action=>'blame',javascript=>0,-replay=>1)},
'this page').
" instead.\n".
"</b></center></div>\n</noscript>\n";
- print qq!<div id="progress_bar" style="width: 100%; background-color: yellow"></div>\n!;
+ print {$output_handler} qq!<div id="progress_bar" style="width: 100%; background-color: yellow"></div>\n!;
}
- print qq!<div class="page_body">\n!;
- print qq!<div id="progress_info">... / ...</div>\n!
+ print {$output_handler} qq!<div class="page_body">\n!;
+ print {$output_handler} qq!<div id="progress_info">... / ...</div>\n!
if ($format eq 'incremental');
- print qq!<table id="blame_table" class="blame" width="100%">\n!.
+ print {$output_handler} qq!<table id="blame_table" class="blame" width="100%">\n!.
#qq!<col width="5.5em" /><col width="2.5em" /><col width="*" />\n!.
qq!<thead>\n!.
qq!<tr><th>Commit</th><th>Line</th><th>Data</th></tr>\n!.
@@ -5137,12 +5145,12 @@ sub git_blame_common {
chomp $line;
$linenr++;
- print qq!<tr id="l$linenr" class="$color_class">!.
+ print {$output_handler} qq!<tr id="l$linenr" class="$color_class">!.
qq!<td class="sha1"><a href=""> </a></td>!.
qq!<td class="linenr">!.
qq!<a class="linenr" href="">$linenr</a></td>!;
- print qq!<td class="pre">! . esc_html($line) . "</td>\n";
- print qq!</tr>\n!;
+ print {$output_handler} qq!<td class="pre">! . esc_html($line) . "</td>\n";
+ print {$output_handler} qq!</tr>\n!;
}
} else { # porcelain, i.e. ordinary blame
@@ -5183,25 +5191,25 @@ sub git_blame_common {
$tr_class .= ' boundary' if (exists $meta->{'boundary'});
$tr_class .= ' no-previous' if ($meta->{'nprevious'} == 0);
$tr_class .= ' multiple-previous' if ($meta->{'nprevious'} > 1);
- print "<tr id=\"l$lineno\" class=\"$tr_class\">\n";
+ print {$output_handler} "<tr id=\"l$lineno\" class=\"$tr_class\">\n";
if ($group_size) {
- print "<td class=\"sha1\"";
- print " title=\"". esc_html($author) . ", $date\"";
- print " rowspan=\"$group_size\"" if ($group_size > 1);
- print ">";
- print $cgi->a({-href => href(action=>"commit",
+ print {$output_handler} "<td class=\"sha1\"";
+ print {$output_handler} " title=\"". esc_html($author) . ", $date\"";
+ print {$output_handler} " rowspan=\"$group_size\"" if ($group_size > 1);
+ print {$output_handler} ">";
+ print {$output_handler} $cgi->a({-href => href(action=>"commit",
hash=>$full_rev,
file_name=>$file_name)},
esc_html($short_rev));
if ($group_size >= 2) {
my @author_initials = ($author =~ /\b([[:upper:]])\B/g);
if (@author_initials) {
- print "<br />" .
+ print {$output_handler} "<br />" .
esc_html(join('', @author_initials));
# or join('.', ...)
}
}
- print "</td>\n";
+ print {$output_handler} "</td>\n";
}
# 'previous' <sha1 of parent commit> <filename at commit>
if (exists $meta->{'previous'} &&
@@ -5218,23 +5226,23 @@ sub git_blame_common {
my $blamed = href(action => 'blame',
file_name => $linenr_filename,
hash_base => $linenr_commit);
- print "<td class=\"linenr\">";
- print $cgi->a({ -href => "$blamed#l$orig_lineno",
+ print {$output_handler} "<td class=\"linenr\">";
+ print {$output_handler} $cgi->a({ -href => "$blamed#l$orig_lineno",
-class => "linenr" },
esc_html($lineno));
- print "</td>";
- print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
- print "</tr>\n";
+ print {$output_handler} "</td>";
+ print {$output_handler} "<td class=\"pre\">" . esc_html($data) . "</td>\n";
+ print {$output_handler} "</tr>\n";
} # end while
}
# footer
- print "</tbody>\n".
+ print {$output_handler} "</tbody>\n".
"</table>\n"; # class="blame"
- print "</div>\n"; # class="blame_body"
+ print {$output_handler} "</div>\n"; # class="blame_body"
close $fd
- or print "Reading blob failed\n";
+ or print {$output_handler} "Reading blob failed\n";
git_footer_html();
}
@@ -5317,16 +5325,17 @@ sub git_blob_plain {
my $sandbox = $prevent_xss &&
$type !~ m!^(?:text/plain|image/(?:gif|png|jpeg))$!;
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => $type,
-expires => $expires,
-content_disposition =>
($sandbox ? 'attachment' : 'inline')
. '; filename="' . $save_as . '"');
local $/ = undef;
- binmode STDOUT, ':raw';
- print <$fd>;
- binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
+
+ binmode $output_handler_bin, ':raw';
+ print {$output_handler_bin} <$fd>;
+ binmode $output_handler_bin, ':utf8'; # as set at the beginning of gitweb.cgi
close $fd;
}
@@ -5385,18 +5394,18 @@ sub git_blob {
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
} else {
- print "<div class=\"page_nav\">\n" .
+ print {$output_handler} "<div class=\"page_nav\">\n" .
"<br/><br/></div>\n" .
"<div class=\"title\">$hash</div>\n";
}
git_print_page_path($file_name, "blob", $hash_base);
- print "<div class=\"page_body\">\n";
+ print {$output_handler} "<div class=\"page_body\">\n";
if ($mimetype =~ m!^image/!) {
- print qq!<img type="$mimetype"!;
+ print {$output_handler} qq!<img type="$mimetype"!;
if ($file_name) {
- print qq! alt="$file_name" title="$file_name"!;
+ print {$output_handler} qq! alt="$file_name" title="$file_name"!;
}
- print qq! src="! .
+ print {$output_handler} qq! src="! .
href(action=>"blob_plain", hash=>$hash,
hash_base=>$hash_base, file_name=>$file_name) .
qq!" />\n!;
@@ -5406,14 +5415,14 @@ sub git_blob {
chomp $line;
$nr++;
$line = untabify($line);
- printf "<div class=\"pre\"><a id=\"l%i\" href=\"" . href(-replay => 1)
+ printf {$output_handler} "<div class=\"pre\"><a id=\"l%i\" href=\"" . href(-replay => 1)
. "#l%i\" class=\"linenr\">%4i</a> %s</div>\n",
$nr, $nr, $nr, esc_html($line, -nbsp=>1);
}
}
close $fd
- or print "Reading blob failed.\n";
- print "</div>";
+ or print {$output_handler} "Reading blob failed.\n";
+ print {$output_handler} "</div>";
git_footer_html();
}
@@ -5468,9 +5477,9 @@ sub git_tree {
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
} else {
undef $hash_base;
- print "<div class=\"page_nav\">\n";
- print "<br/><br/></div>\n";
- print "<div class=\"title\">$hash</div>\n";
+ print {$output_handler} "<div class=\"page_nav\">\n";
+ print {$output_handler} "<br/><br/></div>\n";
+ print {$output_handler} "<div class=\"title\">$hash</div>\n";
}
if (defined $file_name) {
$basedir = $file_name;
@@ -5479,16 +5488,16 @@ sub git_tree {
}
git_print_page_path($file_name, 'tree', $hash_base);
}
- print "<div class=\"page_body\">\n";
- print "<table class=\"tree\">\n";
+ print {$output_handler} "<div class=\"page_body\">\n";
+ print {$output_handler} "<table class=\"tree\">\n";
my $alternate = 1;
# '..' (top directory) link if possible
if (defined $hash_base &&
defined $file_name && $file_name =~ m![^/]+$!) {
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
@@ -5496,33 +5505,33 @@ sub git_tree {
$up =~ s!/?[^/]+$!!;
undef $up unless $up;
# based on git_print_tree_entry
- print '<td class="mode">' . mode_str('040000') . "</td>\n";
- print '<td class="size"> </td>'."\n" if $show_sizes;
- print '<td class="list">';
- print $cgi->a({-href => href(action=>"tree",
+ print {$output_handler} '<td class="mode">' . mode_str('040000') . "</td>\n";
+ print {$output_handler} '<td class="size"> </td>'."\n" if $show_sizes;
+ print {$output_handler} '<td class="list">';
+ print {$output_handler} $cgi->a({-href => href(action=>"tree",
hash_base=>$hash_base,
file_name=>$up)},
"..");
- print "</td>\n";
- print "<td class=\"link\"></td>\n";
+ print {$output_handler} "</td>\n";
+ print {$output_handler} "<td class=\"link\"></td>\n";
- print "</tr>\n";
+ print {$output_handler} "</tr>\n";
}
foreach my $line (@entries) {
my %t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
git_print_tree_entry(\%t, $basedir, $hash_base, $have_blame);
- print "</tr>\n";
+ print {$output_handler} "</tr>\n";
}
- print "</table>\n" .
+ print {$output_handler} "</table>\n" .
"</div>";
git_footer_html();
}
@@ -5599,16 +5608,16 @@ sub git_snapshot {
}
$filename =~ s/(["\\])/\\$1/g;
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => $known_snapshot_formats{$format}{'type'},
-content_disposition => 'inline; filename="' . $filename . '"',
-status => '200 OK');
open my $fd, "-|", $cmd
or die_error(500, "Execute git-archive failed");
- binmode STDOUT, ':raw';
- print <$fd>;
- binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
+ binmode $output_handler_bin, ':raw';
+ print {$output_handler_bin} <$fd>;
+ binmode $output_handler_bin, ':utf8'; # as set at the beginning of gitweb.cgi
close $fd;
}
@@ -5759,11 +5768,11 @@ sub git_commit {
} else {
git_print_header_div('tree', esc_html($co{'title'}) . $ref, $co{'tree'}, $hash);
}
- print "<div class=\"title_text\">\n" .
+ print {$output_handler} "<div class=\"title_text\">\n" .
"<table class=\"object_header\">\n";
git_print_authorship_rows(\%co);
- print "<tr><td>commit</td><td class=\"sha1\">$co{'id'}</td></tr>\n";
- print "<tr>" .
+ print {$output_handler} "<tr><td>commit</td><td class=\"sha1\">$co{'id'}</td></tr>\n";
+ print {$output_handler} "<tr>" .
"<td>tree</td>" .
"<td class=\"sha1\">" .
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash),
@@ -5774,13 +5783,13 @@ sub git_commit {
"tree");
my $snapshot_links = format_snapshot_links($hash);
if (defined $snapshot_links) {
- print " | " . $snapshot_links;
+ print {$output_handler} " | " . $snapshot_links;
}
- print "</td>" .
+ print {$output_handler} "</td>" .
"</tr>\n";
foreach my $par (@$parents) {
- print "<tr>" .
+ print {$output_handler} "<tr>" .
"<td>parent</td>" .
"<td class=\"sha1\">" .
$cgi->a({-href => href(action=>"commit", hash=>$par),
@@ -5793,12 +5802,12 @@ sub git_commit {
"</td>" .
"</tr>\n";
}
- print "</table>".
+ print {$output_handler} "</table>".
"</div>\n";
- print "<div class=\"page_body\">\n";
+ print {$output_handler} "<div class=\"page_body\">\n";
git_print_log($co{'comment'});
- print "</div>\n";
+ print {$output_handler} "</div>\n";
git_difftree_body(\@difftree, $hash, @$parents);
@@ -5846,7 +5855,7 @@ sub git_object {
die_error(400, "Not enough information to find object");
}
- print $cgi->redirect(-uri => href(action=>$type, -full=>1,
+ print {$output_handler} $cgi->redirect(-uri => href(action=>$type, -full=>1,
hash=>$hash, hash_base=>$hash_base,
file_name=>$file_name),
-status => '302 Found');
@@ -5937,23 +5946,23 @@ sub git_blobdiff {
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
} else {
- print "<div class=\"page_nav\"><br/>$formats_nav<br/></div>\n";
- print "<div class=\"title\">$hash vs $hash_parent</div>\n";
+ print {$output_handler} "<div class=\"page_nav\"><br/>$formats_nav<br/></div>\n";
+ print {$output_handler} "<div class=\"title\">$hash vs $hash_parent</div>\n";
}
if (defined $file_name) {
git_print_page_path($file_name, "blob", $hash_base);
} else {
- print "<div class=\"page_path\"></div>\n";
+ print {$output_handler} "<div class=\"page_path\"></div>\n";
}
} elsif ($format eq 'plain') {
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => 'text/plain',
-charset => 'utf-8',
-expires => $expires,
-content_disposition => 'inline; filename="' . "$file_name" . '.patch"');
- print "X-Git-Url: " . $cgi->self_url() . "\n\n";
+ print {$output_handler} "X-Git-Url: " . $cgi->self_url() . "\n\n";
} else {
die_error(400, "Unknown blobdiff format");
@@ -5961,12 +5970,12 @@ sub git_blobdiff {
# patch
if ($format eq 'html') {
- print "<div class=\"page_body\">\n";
+ print {$output_handler} "<div class=\"page_body\">\n";
git_patchset_body($fd, [ \%diffinfo ], $hash_base, $hash_parent_base);
close $fd;
- print "</div>\n"; # class="page_body"
+ print {$output_handler} "</div>\n"; # class="page_body"
git_footer_html();
} else {
@@ -5974,12 +5983,12 @@ sub git_blobdiff {
$line =~ s!a/($hash|$hash_parent)!'a/'.esc_path($diffinfo{'from_file'})!eg;
$line =~ s!b/($hash|$hash_parent)!'b/'.esc_path($diffinfo{'to_file'})!eg;
- print $line;
+ print {$output_handler} $line;
last if $line =~ m!^\+\+\+!;
}
local $/ = undef;
- print <$fd>;
+ print {$output_handler} <$fd>;
close $fd;
}
}
@@ -6142,16 +6151,16 @@ sub git_commitdiff {
git_header_html(undef, $expires);
git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash);
- print "<div class=\"title_text\">\n" .
+ print {$output_handler} "<div class=\"title_text\">\n" .
"<table class=\"object_header\">\n";
git_print_authorship_rows(\%co);
- print "</table>".
+ print {$output_handler} "</table>".
"</div>\n";
- print "<div class=\"page_body\">\n";
+ print {$output_handler} "<div class=\"page_body\">\n";
if (@{$co{'comment'}} > 1) {
- print "<div class=\"log\">\n";
+ print {$output_handler} "<div class=\"log\">\n";
git_print_log($co{'comment'}, -final_empty_line=> 1, -remove_title => 1);
- print "</div>\n"; # class="log"
+ print {$output_handler} "</div>\n"; # class="log"
}
} elsif ($format eq 'plain') {
@@ -6159,27 +6168,27 @@ sub git_commitdiff {
my $tagname = git_get_rev_name_tags($hash);
my $filename = basename($project) . "-$hash.patch";
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => 'text/plain',
-charset => 'utf-8',
-expires => $expires,
-content_disposition => 'inline; filename="' . "$filename" . '"');
my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
- print "From: " . to_utf8($co{'author'}) . "\n";
- print "Date: $ad{'rfc2822'} ($ad{'tz_local'})\n";
- print "Subject: " . to_utf8($co{'title'}) . "\n";
+ print {$output_handler} "From: " . to_utf8($co{'author'}) . "\n";
+ print {$output_handler} "Date: $ad{'rfc2822'} ($ad{'tz_local'})\n";
+ print {$output_handler} "Subject: " . to_utf8($co{'title'}) . "\n";
- print "X-Git-Tag: $tagname\n" if $tagname;
- print "X-Git-Url: " . $cgi->self_url() . "\n\n";
+ print {$output_handler} "X-Git-Tag: $tagname\n" if $tagname;
+ print {$output_handler} "X-Git-Url: " . $cgi->self_url() . "\n\n";
foreach my $line (@{$co{'comment'}}) {
- print to_utf8($line) . "\n";
+ print {$output_handler} to_utf8($line) . "\n";
}
- print "---\n\n";
+ print {$output_handler} "---\n\n";
} elsif ($format eq 'patch') {
my $filename = basename($project) . "-$hash.patch";
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => 'text/plain',
-charset => 'utf-8',
-expires => $expires,
@@ -6192,24 +6201,24 @@ sub git_commitdiff {
$hash_parent eq '-c' || $hash_parent eq '--cc';
git_difftree_body(\@difftree, $hash,
$use_parents ? @{$co{'parents'}} : $hash_parent);
- print "<br/>\n";
+ print {$output_handler} "<br/>\n";
git_patchset_body($fd, \@difftree, $hash,
$use_parents ? @{$co{'parents'}} : $hash_parent);
close $fd;
- print "</div>\n"; # class="page_body"
+ print {$output_handler} "</div>\n"; # class="page_body"
git_footer_html();
} elsif ($format eq 'plain') {
local $/ = undef;
- print <$fd>;
+ print {$output_handler} <$fd>;
close $fd
- or print "Reading git-diff-tree failed\n";
+ or print {$output_handler} "Reading git-diff-tree failed\n";
} elsif ($format eq 'patch') {
local $/ = undef;
- print <$fd>;
+ print {$output_handler} <$fd>;
close $fd
- or print "Reading git-format-patch failed\n";
+ or print {$output_handler} "Reading git-format-patch failed\n";
}
}
@@ -6312,7 +6321,7 @@ sub git_search {
git_print_page_nav('','', $hash,$co{'tree'},$hash);
git_print_header_div('commit', esc_html($co{'title'}), $hash);
- print "<table class=\"pickaxe search\">\n";
+ print {$output_handler} "<table class=\"pickaxe search\">\n";
my $alternate = 1;
local $/ = "\n";
open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts,
@@ -6328,24 +6337,24 @@ sub git_search {
if (defined $set{'commit'}) {
# finish previous commit
if (%co) {
- print "</td>\n" .
+ print {$output_handler} "</td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
" | " .
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
- print "</td>\n" .
+ print {$output_handler} "</td>\n" .
"</tr>\n";
}
if ($alternate) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
$alternate ^= 1;
%co = parse_commit($set{'commit'});
my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
- print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+ print {$output_handler} "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
"<td><i>$author</i></td>\n" .
"<td>" .
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
@@ -6354,7 +6363,7 @@ sub git_search {
} elsif (defined $set{'to_id'}) {
next if ($set{'to_id'} =~ m/^0{40}$/);
- print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
+ print {$output_handler} $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
hash=>$set{'to_id'}, file_name=>$set{'to_file'}),
-class => "list"},
"<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
@@ -6365,23 +6374,23 @@ sub git_search {
# finish last commit (warning: repetition!)
if (%co) {
- print "</td>\n" .
+ print {$output_handler} "</td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
" | " .
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
- print "</td>\n" .
+ print {$output_handler} "</td>\n" .
"</tr>\n";
}
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
if ($searchtype eq 'grep') {
git_print_page_nav('','', $hash,$co{'tree'},$hash);
git_print_header_div('commit', esc_html($co{'title'}), $hash);
- print "<table class=\"grep_search\">\n";
+ print {$output_handler} "<table class=\"grep_search\">\n";
my $alternate = 1;
my $matches = 0;
local $/ = "\n";
@@ -6400,21 +6409,21 @@ sub git_search {
(undef, $file, $lno, $ltext) = split(/:/, $line, 4);
}
if ($file ne $lastfile) {
- $lastfile and print "</td></tr>\n";
+ $lastfile and print {$output_handler} "</td></tr>\n";
if ($alternate++) {
- print "<tr class=\"dark\">\n";
+ print {$output_handler} "<tr class=\"dark\">\n";
} else {
- print "<tr class=\"light\">\n";
+ print {$output_handler} "<tr class=\"light\">\n";
}
- print "<td class=\"list\">".
+ print {$output_handler} "<td class=\"list\">".
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
file_name=>"$file"),
-class => "list"}, esc_path($file));
- print "</td><td>\n";
+ print {$output_handler} "</td><td>\n";
$lastfile = $file;
}
if ($binary) {
- print "<div class=\"binary\">Binary file</div>\n";
+ print {$output_handler} "<div class=\"binary\">Binary file</div>\n";
} else {
$ltext = untabify($ltext);
if ($ltext =~ m/^(.*)($search_regexp)(.*)$/i) {
@@ -6426,7 +6435,7 @@ sub git_search {
} else {
$ltext = esc_html($ltext, -nbsp=>1);
}
- print "<div class=\"pre\">" .
+ print {$output_handler} "<div class=\"pre\">" .
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
file_name=>"$file").'#l'.$lno,
-class => "linenr"}, sprintf('%4i', $lno))
@@ -6434,16 +6443,16 @@ sub git_search {
}
}
if ($lastfile) {
- print "</td></tr>\n";
+ print {$output_handler} "</td></tr>\n";
if ($matches > 1000) {
- print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
+ print {$output_handler} "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
}
} else {
- print "<div class=\"diff nodifferences\">No matches found</div>\n";
+ print {$output_handler} "<div class=\"diff nodifferences\">No matches found</div>\n";
}
close $fd;
- print "</table>\n";
+ print {$output_handler} "</table>\n";
}
git_footer_html();
}
@@ -6451,7 +6460,7 @@ sub git_search {
sub git_search_help {
git_header_html();
git_print_page_nav('','', $hash,$hash,$hash);
- print <<EOT;
+ print {$output_handler} <<EOT;
<p><strong>Pattern</strong> is by default a normal string that is matched precisely (but without
regard to case, except in the case of pickaxe). However, when you check the <em>re</em> checkbox,
the pattern entered is recognized as the POSIX extended
@@ -6463,7 +6472,7 @@ insensitive).</p>
EOT
my $have_grep = gitweb_check_feature('grep');
if ($have_grep) {
- print <<EOT;
+ print {$output_handler} <<EOT;
<dt><b>grep</b></dt>
<dd>All files in the currently selected tree (HEAD unless you are explicitly browsing
a different one) are searched for the given pattern. On large trees, this search can take
@@ -6472,7 +6481,7 @@ due to git-grep peculiarity, currently if regexp mode is turned off, the matches
case-sensitive.</dd>
EOT
}
- print <<EOT;
+ print {$output_handler} <<EOT;
<dt><b>author</b></dt>
<dd>Name and e-mail of the change author and date of birth of the patch will be scanned for the given pattern.</dd>
<dt><b>committer</b></dt>
@@ -6480,7 +6489,7 @@ EOT
EOT
my $have_pickaxe = gitweb_check_feature('pickaxe');
if ($have_pickaxe) {
- print <<EOT;
+ print {$output_handler} <<EOT;
<dt><b>pickaxe</b></dt>
<dd>All commits that caused the string to appear or disappear from any file (changes that
added, removed or "modified" the string) will be listed. This search can take a while and
@@ -6488,7 +6497,7 @@ takes a lot of strain on the server, so please use it wisely. Note that since yo
interested even in changes just changing the case as well, this search is case sensitive.</dd>
EOT
}
- print "</dl>\n";
+ print {$output_handler} "</dl>\n";
git_footer_html();
}
@@ -6535,7 +6544,7 @@ sub git_feed {
$since = Time::ParseDate::parsedate($if_modified, GMT => 1);
}
if (defined $since && $latest_epoch <= $since) {
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => $content_type,
-charset => 'utf-8',
-last_modified => $latest_date{'rfc2822'},
@@ -6543,12 +6552,12 @@ sub git_feed {
return;
}
}
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => $content_type,
-charset => 'utf-8',
-last_modified => $latest_date{'rfc2822'});
} else {
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => $content_type,
-charset => 'utf-8');
}
@@ -6592,13 +6601,13 @@ sub git_feed {
} else {
$alt_url = href(-full=>1, action=>"summary");
}
- print qq!<?xml version="1.0" encoding="utf-8"?>\n!;
+ print {$output_handler} qq!<?xml version="1.0" encoding="utf-8"?>\n!;
if ($format eq 'rss') {
- print <<XML;
+ print {$output_handler} <<XML;
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
XML
- print "<title>$title</title>\n" .
+ print {$output_handler} "<title>$title</title>\n" .
"<link>$alt_url</link>\n" .
"<description>$descr</description>\n" .
"<language>en</language>\n" .
@@ -6608,22 +6617,22 @@ XML
# prefer the logo to the favicon, since RSS
# doesn't allow both
my $img = esc_url($logo || $favicon);
- print "<image>\n" .
+ print {$output_handler} "<image>\n" .
"<url>$img</url>\n" .
"<title>$title</title>\n" .
"<link>$alt_url</link>\n" .
"</image>\n";
}
if (%latest_date) {
- print "<pubDate>$latest_date{'rfc2822'}</pubDate>\n";
- print "<lastBuildDate>$latest_date{'rfc2822'}</lastBuildDate>\n";
+ print {$output_handler} "<pubDate>$latest_date{'rfc2822'}</pubDate>\n";
+ print {$output_handler} "<lastBuildDate>$latest_date{'rfc2822'}</lastBuildDate>\n";
}
- print "<generator>gitweb v.$version/$git_version</generator>\n";
+ print {$output_handler} "<generator>gitweb v.$version/$git_version</generator>\n";
} elsif ($format eq 'atom') {
- print <<XML;
+ print {$output_handler} <<XML;
<feed xmlns="http://www.w3.org/2005/Atom">
XML
- print "<title>$title</title>\n" .
+ print {$output_handler} "<title>$title</title>\n" .
"<subtitle>$descr</subtitle>\n" .
'<link rel="alternate" type="text/html" href="' .
$alt_url . '" />' . "\n" .
@@ -6633,19 +6642,19 @@ XML
# use project owner for feed author
"<author><name>$owner</name></author>\n";
if (defined $favicon) {
- print "<icon>" . esc_url($favicon) . "</icon>\n";
+ print {$output_handler} "<icon>" . esc_url($favicon) . "</icon>\n";
}
if (defined $logo_url) {
# not twice as wide as tall: 72 x 27 pixels
- print "<logo>" . esc_url($logo) . "</logo>\n";
+ print {$output_handler} "<logo>" . esc_url($logo) . "</logo>\n";
}
if (! %latest_date) {
# dummy date to keep the feed valid until commits trickle in:
- print "<updated>1970-01-01T00:00:00Z</updated>\n";
+ print {$output_handler} "<updated>1970-01-01T00:00:00Z</updated>\n";
} else {
- print "<updated>$latest_date{'iso-8601'}</updated>\n";
+ print {$output_handler} "<updated>$latest_date{'iso-8601'}</updated>\n";
}
- print "<generator version='$version/$git_version'>gitweb</generator>\n";
+ print {$output_handler} "<generator version='$version/$git_version'>gitweb</generator>\n";
}
# contents
@@ -6670,7 +6679,7 @@ XML
# print element (entry, item)
my $co_url = href(-full=>1, action=>"commitdiff", hash=>$commit);
if ($format eq 'rss') {
- print "<item>\n" .
+ print {$output_handler} "<item>\n" .
"<title>" . esc_html($co{'title'}) . "</title>\n" .
"<author>" . esc_html($co{'author'}) . "</author>\n" .
"<pubDate>$cd{'rfc2822'}</pubDate>\n" .
@@ -6680,22 +6689,22 @@ XML
"<content:encoded>" .
"<![CDATA[\n";
} elsif ($format eq 'atom') {
- print "<entry>\n" .
+ print {$output_handler} "<entry>\n" .
"<title type=\"html\">" . esc_html($co{'title'}) . "</title>\n" .
"<updated>$cd{'iso-8601'}</updated>\n" .
"<author>\n" .
" <name>" . esc_html($co{'author_name'}) . "</name>\n";
if ($co{'author_email'}) {
- print " <email>" . esc_html($co{'author_email'}) . "</email>\n";
+ print {$output_handler} " <email>" . esc_html($co{'author_email'}) . "</email>\n";
}
- print "</author>\n" .
+ print {$output_handler} "</author>\n" .
# use committer for contributor
"<contributor>\n" .
" <name>" . esc_html($co{'committer_name'}) . "</name>\n";
if ($co{'committer_email'}) {
- print " <email>" . esc_html($co{'committer_email'}) . "</email>\n";
+ print {$output_handler} " <email>" . esc_html($co{'committer_email'}) . "</email>\n";
}
- print "</contributor>\n" .
+ print {$output_handler} "</contributor>\n" .
"<published>$cd{'iso-8601'}</published>\n" .
"<link rel=\"alternate\" type=\"text/html\" href=\"$co_url\" />\n" .
"<id>$co_url</id>\n" .
@@ -6703,19 +6712,19 @@ XML
"<div xmlns=\"http://www.w3.org/1999/xhtml\">\n";
}
my $comment = $co{'comment'};
- print "<pre>\n";
+ print {$output_handler} "<pre>\n";
foreach my $line (@$comment) {
$line = esc_html($line);
- print "$line\n";
+ print {$output_handler} "$line\n";
}
- print "</pre><ul>\n";
+ print {$output_handler} "</pre><ul>\n";
foreach my $difftree_line (@difftree) {
my %difftree = parse_difftree_raw_line($difftree_line);
next if !$difftree{'from_id'};
my $file = $difftree{'file'} || $difftree{'to_file'};
- print "<li>" .
+ print {$output_handler} "<li>" .
"[" .
$cgi->a({-href => href(-full=>1, action=>"blobdiff",
hash=>$difftree{'to_id'}, hash_parent=>$difftree{'from_id'},
@@ -6723,26 +6732,26 @@ XML
file_name=>$file, file_parent=>$difftree{'from_file'}),
-title => "diff"}, 'D');
if ($have_blame) {
- print $cgi->a({-href => href(-full=>1, action=>"blame",
+ print {$output_handler} $cgi->a({-href => href(-full=>1, action=>"blame",
file_name=>$file, hash_base=>$commit),
-title => "blame"}, 'B');
}
# if this is not a feed of a file history
if (!defined $file_name || $file_name ne $file) {
- print $cgi->a({-href => href(-full=>1, action=>"history",
+ print {$output_handler} $cgi->a({-href => href(-full=>1, action=>"history",
file_name=>$file, hash=>$commit),
-title => "history"}, 'H');
}
$file = esc_path($file);
- print "] ".
+ print {$output_handler} "] ".
"$file</li>\n";
}
if ($format eq 'rss') {
- print "</ul>]]>\n" .
+ print {$output_handler} "</ul>]]>\n" .
"</content:encoded>\n" .
"</item>\n";
} elsif ($format eq 'atom') {
- print "</ul>\n</div>\n" .
+ print {$output_handler} "</ul>\n</div>\n" .
"</content>\n" .
"</entry>\n";
}
@@ -6750,9 +6759,9 @@ XML
# end of feed
if ($format eq 'rss') {
- print "</channel>\n</rss>\n";
+ print {$output_handler} "</channel>\n</rss>\n";
} elsif ($format eq 'atom') {
- print "</feed>\n";
+ print {$output_handler} "</feed>\n";
}
}
@@ -6766,13 +6775,12 @@ sub git_atom {
sub git_opml {
my @list = git_get_projects_list();
-
- print $cgi->header(
+ print {$output_handler} $cgi->header(
-type => 'text/xml',
-charset => 'utf-8',
-content_disposition => 'inline; filename="opml.xml"');
- print <<XML;
+ print {$output_handler} <<XML;
<?xml version="1.0" encoding="utf-8"?>
<opml version="1.0">
<head>
@@ -6797,9 +6805,9 @@ XML
my $path = esc_html(chop_str($proj{'path'}, 25, 5));
my $rss = href('project' => $proj{'path'}, 'action' => 'rss', -full => 1);
my $html = href('project' => $proj{'path'}, 'action' => 'summary', -full => 1);
- print "<outline type=\"rss\" text=\"$path\" title=\"$path\" xmlUrl=\"$rss\" htmlUrl=\"$html\"/>\n";
+ print {$output_handler} "<outline type=\"rss\" text=\"$path\" title=\"$path\" xmlUrl=\"$rss\" htmlUrl=\"$html\"/>\n";
}
- print <<XML;
+ print {$output_handler} <<XML;
</outline>
</body>
</opml>
--
1.6.5.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/7] gitweb: add a get function to compliment print_local_time
2010-01-13 9:34 ` [PATCH 5/7] gitweb: Convert output to using indirect file handle John 'Warthog9' Hawley
@ 2010-01-13 9:34 ` John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 7/7] gitweb: File based caching layer (from git.kernel.org) John 'Warthog9' Hawley
0 siblings, 1 reply; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
This adds a get function for print_local_time so that the basic
function can be used outside of their straight printing operation.
---
gitweb/gitweb.perl | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 3b6bc06..3010fe3 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -3548,14 +3548,21 @@ sub git_print_header_div {
}
sub print_local_time {
+ print {$output_handler} get_local_time(@_);
+}
+
+sub get_local_time {
+ my $localtime = "";
my %date = @_;
if ($date{'hour_local'} < 6) {
- printf({$output_handler} " (<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({$output_handler} " (%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
--
1.6.5.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/7] gitweb: File based caching layer (from git.kernel.org)
2010-01-13 9:34 ` [PATCH 6/7] gitweb: add a get function to compliment print_local_time John 'Warthog9' Hawley
@ 2010-01-13 9:34 ` John 'Warthog9' Hawley
0 siblings, 0 replies; 11+ messages in thread
From: John 'Warthog9' Hawley @ 2010-01-13 9:34 UTC (permalink / raw)
To: git
This is a very large patch that implements the file based
caching layer that is used on such large sites as kernel.org and
soon git.fedoraproject.org. This provides a simple, and straight
forward caching mechanism that scales dramatically better than
Gitweb by itself.
The caching layer basically buffers the output that Gitweb would
normally return, and saves that output to a cache file on the local
disk. When the file is requested it attempts to gain a shared lock
on the cache file and cat it out to the client. Should an exclusive
lock be on a file (it's being updated) the code has a choice to either
update in the background and go ahead and show the stale page while
update is being performed, or stall the client(s) until the page
is generated.
There are two forms of stalling involved here, background building
and non-background building, both of which are discussed in the
configuration page.
There are still a few known "issues" with respect to this:
- Code needs to be added to be "browser" aware so
that clients like wget that are trying to get a
binary blob don't obtain a "Generating..." page
- There is an intermittent flushing issue that has yet
to be tracked down
Caching is disabled by default with the $cache_enable variable,
setting this to 1 will enable file based caching. It is expected
that this will be extended to include additional types of caching
(like memcached) in the future and should not be exclusively
considered a binary value.
v4 - warthog9: refactoring to use modified and indirect print
statements as opposed to passing the output around
in memory. This means without caching enabled you
should get exactly the same behavior as if you
never had the caching code at all.
---
gitweb/cache.pm | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++
gitweb/gitweb.css | 6 +
gitweb/gitweb.perl | 56 ++++++++++-
3 files changed, 343 insertions(+), 2 deletions(-)
create mode 100644 gitweb/cache.pm
diff --git a/gitweb/cache.pm b/gitweb/cache.pm
new file mode 100644
index 0000000..89fa577
--- /dev/null
+++ b/gitweb/cache.pm
@@ -0,0 +1,283 @@
+# gitweb - simple web interface to track changes in git repositories
+#
+# (C) 2006, John 'Warthog9' Hawley <warthog19@eaglescrag.net>
+#
+# This program is licensed under the GPLv2
+
+#
+# Gitweb caching engine
+#
+
+use File::Path qw(make_path remove_tree);
+use Digest::MD5 qw(md5 md5_hex md5_base64);
+use Fcntl ':flock';
+
+sub cache_fetch {
+ my ($action) = @_;
+ my $cacheTime = 0;
+
+ # Deal with cache being disabled
+ if( $cache_enable == 0 ){
+ $output_handler = *STDOUT;
+ $output_handler_bin = *STDOUT;
+ $actions{$action}->();
+ return;
+ }elsif( $cache_enable == 1 ){
+ #obviously we are using file based caching
+
+ if(! -d $cachedir){
+ print "*** Warning ***: Caching enabled but cache directory does not exsist. ($cachedir)\n";
+ mkdir ("cache", 0665) || die "Cannot create cache dir - you will need to manually create";
+ print "Cache directory created successfully\n";
+ }
+
+ our $full_url = "$my_url?". $ENV{'QUERY_STRING'};
+ our $urlhash = md5_hex($full_url);
+ our $fullhashdir = "$cachedir/". substr( $urlhash, 0, 2) ."/";
+
+ my $numdirs = make_path( $fullhashdir, { mode => 0777, error => \my $mkdirerr, } );
+ if( @$mkdirerr ){
+ my $mkdirerrmsg = "";
+ for my $diag (@$mkdirerr) {
+ my ($file, $message) = %$diag;
+ if($file eq '' ){
+ $mkdirerrmsg .= "general error: $message\n";
+ }else{
+ $mkdirerrmsg .= "problem unlinking $file: $message\n";
+ }
+ }
+ die_error(500, "Could not create cache directory | $mkdirerrmsg");
+ }
+ $fullhashpath = "$fullhashdir/". substr( $urlhash, 2 );
+ $fullhashbinpath = "$fullhashpath.bin";
+ } # done dealing with cache enabled / disabled
+
+ if(! -e "$fullhashpath" ){
+ if(! defined(my $childPid = fork()) ){
+ cacheUpdate($action,0);
+ cacheDisplay($action);
+ } elsif ( $childPid == 0 ){
+ #run the updater
+ cacheUpdate($action,1);
+ }else{
+ cacheWaitForUpdate($action);
+ }
+ }else{
+ #if cache is out dated, update
+ #else displayCache();
+ open(cacheFile, '<', "$fullhashpath");
+ stat(cacheFile);
+ close(cacheFile);
+ $cacheTime = get_loadavg() * 60;
+ if( $cacheTime > $maxCacheTime ){
+ $cacheTime = $maxCacheTime;
+ }
+ if( $cacheTime < $minCacheTime ){
+ $cacheTime = $minCacheTime;
+ }
+ if( (stat(_))[9] < (time - $cacheTime) ){
+ if( ! defined(my $childPid = fork()) ){
+ cacheUpdate($action,0);
+ cacheDisplay($action);
+ } elsif ( $childPid == 0 ){
+ #run the updater
+ #print "Running updater\n";
+ cacheUpdate($action,1);
+ }else{
+ #print "Waiting for update\n";
+ cacheWaitForUpdate($action);
+ }
+ } else {
+ cacheDisplay($action);
+ }
+
+
+ }
+
+ #
+ # If all of the caching failes - lets go ahead and press on without it and fall back to 'default'
+ # non-caching behavior. This is the softest of the failure conditions.
+ #
+ #$actions{$action}->();
+}
+
+sub cacheUpdate {
+ my ($action,$areForked) = @_;
+ my $lockingStatus;
+ my $fileData = "";
+
+ if($backgroundCache){
+ open(cacheFileBG, '>:utf8', "$fullhashpath.bg");
+ my $lockStatBG = flock(cacheFileBG,LOCK_EX|LOCK_NB);
+
+ $lockStatus = $lockStatBG;
+ }else{
+ open(cacheFile, '>:utf8', "$fullhashpath");
+ my $lockStat = flock(cacheFile,LOCK_EX|LOCK_NB);
+
+ $lockStatus = $lockStat;
+ }
+ #print "lock status: $lockStat\n";
+
+
+ if (! $lockStatus ){
+ if ( $areForked ){
+ exit(0);
+ }else{
+ return;
+ }
+ }
+
+ if(
+ $action eq "snapshot"
+ ||
+ $action eq "blob_plain"
+ ){
+ open cacheFileBin, '>', $fullhashbinpath or die_error(500, "Could not open bin dump file");
+ $output_handler_bin = *cacheFileBin;
+ }
+
+ $output_handler = *cacheFile;
+
+ if($backgroundCache){
+ open(cacheFile, '>:utf8', "$fullhashpath");
+ $lockStat = flock(cacheFile,LOCK_EX);
+
+ if (! $lockStat ){
+ if ( $areForked ){
+ exit(0);
+ }else{
+ return;
+ }
+ }
+ }
+
+ $actions{$action}->();
+
+ if(
+ $action eq "snapshot"
+ ||
+ $action eq "blob_plain"
+ ){
+ close(cacheFileBin);
+ }
+
+ flock(cacheFile,LOCK_UN);
+ close(cacheFile);
+
+ if($backgroundCache){
+ flock(cacheFileBG,LOCK_UN);
+ close(cacheFileBG);
+ }
+
+ if ( $areForked ){
+ exit(0);
+ } else {
+ return;
+ }
+}
+
+
+sub cacheWaitForUpdate {
+ my ($action) = @_;
+ my $x = 0;
+ my $max = 10;
+ my $lockStat = 0;
+
+ if( $backgroundCache ){
+ if( -e "$fullhashpath" ){
+ open(cacheFile, '<:utf8', "$fullhashpath");
+ $lockStat = flock(cacheFile,LOCK_SH|LOCK_NB);
+ stat(cacheFile);
+ close(cacheFile);
+
+ if( $lockStat && ( (stat(_))[9] > (time - $maxCacheLife) ) ){
+ cacheDisplay($action);
+ return;
+ }
+ }
+ }
+
+ if(
+ $action eq "atom"
+ ||
+ $action eq "rss"
+ ||
+ $action eq "opml"
+ ){
+ do {
+ sleep 2 if $x > 0;
+ open(cacheFile, '<:utf8', "$fullhashpath");
+ $lockStat = flock(cacheFile,LOCK_SH|LOCK_NB);
+ close(cacheFile);
+ $x++;
+ $combinedLockStat = $lockStat;
+ } while ((! $combinedLockStat) && ($x < $max));
+
+ if( $x != $max ){
+ cacheDisplay($action);
+ }
+ return;
+ }
+
+ $| = 1;
+
+ print $::cgi->header(-type=>'text/html', -charset => 'utf-8',
+ -status=> 200, -expires => 'never');
+
+ print <<EOF;
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www/w3.porg/TR/html4/strict.dtd">
+<!-- git web w/caching interface version $version, (C) 2006-2010, John 'Warthog9' Hawley <warthog9\@kernel.org> -->
+<!-- git core binaries version $git_version -->
+<head>
+<meta http-equiv="content-type" content="$content_type; charset=utf-8"/>
+<meta name="generator" content="gitweb/$version git/$git_version"/>
+<meta name="robots" content="index, nofollow"/>
+<meta http-equiv="refresh" content="0"/>
+<title>$title</title>
+</head>
+<body>
+EOF
+
+ print "Generating..";
+ do {
+ print ".";
+ sleep 2 if $x > 0;
+ open(cacheFile, '<:utf8', "$fullhashpath");
+ $lockStat = flock(cacheFile,LOCK_SH|LOCK_NB);
+ close(cacheFile);
+ $x++;
+ $combinedLockStat = $lockStat;
+ } while ((! $combinedLockStat) && ($x < $max));
+ print <<EOF;
+</body>
+</html>
+EOF
+ return;
+}
+
+sub cacheDisplay {
+ my ($action) = @_;
+ open(cacheFile, '<:utf8', "$fullhashpath");
+ $lockStat = flock(cacheFile,LOCK_SH|LOCK_NB);
+ if (! $lockStat ){
+ close(cacheFile);
+ cacheWaitForUpdate($action);
+ }
+
+ while( <cacheFile> ){
+ print $_;
+ }
+ if(
+ $action eq "snapshot"
+ ||
+ $action eq "blob_plain"
+ ){
+ open(cacheFileBin, '<', "$fullhashbinpath");
+ binmode STDOUT, ':raw';
+ print <cacheFileBin>;
+ binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
+ close(cacheFileBin);
+ }
+ close(cacheFile);
+}
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index 50067f2..f809f16 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -67,6 +67,12 @@ div.page_path {
border-width: 0px 0px 1px;
}
+div.cachetime {
+ float: left;
+ margin-right: 10px;
+ color: #555555;
+}
+
div.page_footer {
height: 17px;
padding: 4px 8px;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 3010fe3..3e0fa45 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -235,6 +235,50 @@ our $gitlinkurl_project = '';
# Leave it undefined (or set to 'undef') to turn off load checking.
our $maxload = 300;
+# This enables/disables the caching layer in gitweb. This currently only supports the
+# 'dumb' file based caching layer, primarily used on git.kernel.org. this is reasonably
+# effective but it has the downside of requiring a huge amount of disk space if there
+# are a number of repositories involved. It is not uncommon for git.kernel.org to have
+# on the order of 80G - 120G accumulate over the course of a few months. It is recommended
+# that the cache directory be periodically completely deleted, and this is safe to perform.
+# Suggested mechanism
+# mv $cacheidr $cachedir.flush;mkdir $cachedir;rm -rf $cachedir.flush
+# Value is binary. 0 = disabled (default), 1 = enabled.
+#
+# Values of caching:
+# 1 = 'dumb' file based caching used on git.kernel.org
+our $cache_enable = 0;
+
+# Used to set the minimum cache timeout for the dynamic caching algorithm. Basically
+# if we calculate the cache to be under this number of seconds we set the cache timeout
+# to this minimum.
+# Value is in seconds. 1 = 1 seconds, 60 = 1 minute, 600 = 10 minutes, 3600 = 1 hour
+our $minCacheTime = 20;
+
+# Used to set the maximum cache timeout for the dynamic caching algorithm. Basically
+# if we calculate the cache to exceed this number of seconds we set the cache timeout
+# to this maximum.
+# Value is in seconds. 1 = 1 seconds, 60 = 1 minute, 600 = 10 minutes, 3600 = 1 hour
+our $maxCacheTime = 1200;
+
+# If you need to change the location of the caching directory, override this
+# otherwise this will probably do fine for you
+our $cachedir = 'cache';
+
+# If this is set (to 1) cache will do it's best to always display something instead
+# of making someone wait for the cache to update. This will launch the cacheUpdate
+# into the background and it will lock a <file>.bg file and will only lock the
+# actual cache file when it needs to write into it. In theory this will make
+# gitweb seem more responsive at the price of possibly stale data.
+our $backgroundCache = 1;
+
+# Used to set the maximum cache file life. If a cache files last modify time exceeds
+# this value, it will assume that the data is just too old, and HAS to be regenerated
+# instead of trying to display the existing cache data.
+# Value is in seconds. 1 = 1 seconds, 60 = 1 minute, 600 = 10 minutes, 3600 = 1 hour
+# 18000 = 5 hours
+our $maxCacheLife = 18000;
+
# You define site-wide feature defaults here; override them with
# $GITWEB_CONFIG as necessary.
our %feature = (
@@ -598,6 +642,11 @@ if (defined $maxload && get_loadavg() > $maxload) {
die_error(503, "The load average on the server is too high");
}
+#
+# Includes
+#
+do 'cache.pm';
+
# version of the core git binary
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
$number_of_git_cmds++;
@@ -1004,7 +1053,7 @@ if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
!$project) {
die_error(400, "Project needed");
}
-$actions{$action}->();
+cache_fetch($action);
exit;
## ======================================================================
@@ -3210,7 +3259,9 @@ sub git_header_html {
# support xhtml+xml but choking when it gets what it asked for.
if (defined $cgi->http('HTTP_ACCEPT') &&
$cgi->http('HTTP_ACCEPT') =~ m/(,|;|\s|^)application\/xhtml\+xml(,|;|\s|$)/ &&
- $cgi->Accept('application/xhtml+xml') != 0) {
+ $cgi->Accept('application/xhtml+xml') != 0
+ &&
+ $cache_enable == 0) {
$content_type = 'application/xhtml+xml';
} else {
$content_type = 'text/html';
@@ -3354,6 +3405,7 @@ sub git_footer_html {
my $feed_class = 'rss_logo';
print {$output_handler} "<div class=\"page_footer\">\n";
+ print {$output_handler} "<div class=\"cachetime\">Cache Last Updated: ". gmtime( time ) ." GMT</div>\n";
if (defined $project) {
my $descr = git_get_project_description($project);
if (defined $descr) {
--
1.6.5.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 0/7] Gitweb caching v4
2010-01-13 9:34 [PATCH 0/7] Gitweb caching v4 John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 1/7] gitweb: Load checking John 'Warthog9' Hawley
@ 2010-01-14 8:40 ` Junio C Hamano
2010-01-14 8:47 ` J.H.
1 sibling, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2010-01-14 8:40 UTC (permalink / raw)
To: John 'Warthog9' Hawley; +Cc: git
Will replace what was queued on 'pu'.
For [3/7], I had to resolve conflicts in Makefile as it seemt to have been
based on a bit older one. When I push the result out, please verify.
The result merged to 'pu' seems to break t9500 but I didn't look very
carefully.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/7] Gitweb caching v4
2010-01-14 8:40 ` [PATCH 0/7] Gitweb caching v4 Junio C Hamano
@ 2010-01-14 8:47 ` J.H.
2010-01-14 8:54 ` Junio C Hamano
0 siblings, 1 reply; 11+ messages in thread
From: J.H. @ 2010-01-14 8:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Junio,
I'd suggest using v5 vs. v4 as there was a couple of issues I discovered
with v4 today.
- John 'Warthog9' Hawley
On 01/14/2010 12:40 AM, Junio C Hamano wrote:
> Will replace what was queued on 'pu'.
>
> For [3/7], I had to resolve conflicts in Makefile as it seemt to have been
> based on a bit older one. When I push the result out, please verify.
>
> The result merged to 'pu' seems to break t9500 but I didn't look very
> carefully.
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/7] Gitweb caching v4
2010-01-14 8:47 ` J.H.
@ 2010-01-14 8:54 ` Junio C Hamano
0 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2010-01-14 8:54 UTC (permalink / raw)
To: J.H.; +Cc: Junio C Hamano, git
"J.H." <warthog9@eaglescrag.net> writes:
> Junio,
>
> I'd suggest using v5 vs. v4 as there was a couple of issues I discovered
> with v4 today.
Yeah, I just noticed. I was away from the keyboard for the better part of
evening.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2010-01-14 8:54 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-13 9:34 [PATCH 0/7] Gitweb caching v4 John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 1/7] gitweb: Load checking John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 2/7] gitweb: Add option to force version match John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 3/7] gitweb: Makefile improvements John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 4/7] gitweb: Optionally add "git" links in project list page John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 5/7] gitweb: Convert output to using indirect file handle John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 6/7] gitweb: add a get function to compliment print_local_time John 'Warthog9' Hawley
2010-01-13 9:34 ` [PATCH 7/7] gitweb: File based caching layer (from git.kernel.org) John 'Warthog9' Hawley
2010-01-14 8:40 ` [PATCH 0/7] Gitweb caching v4 Junio C Hamano
2010-01-14 8:47 ` J.H.
2010-01-14 8:54 ` Junio C Hamano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox