2005-08-07 17:49:46 +00:00
|
|
|
#!/usr/bin/perl
|
|
|
|
|
2005-08-07 18:27:18 +00:00
|
|
|
# gitweb - simple web interface to track changes in git repositories
|
2005-08-07 17:56:59 +00:00
|
|
|
#
|
2006-05-22 12:30:47 +00:00
|
|
|
# (C) 2005-2006, Kay Sievers <kay.sievers@vrfy.org>
|
|
|
|
# (C) 2005, Christian Gierke
|
2005-08-07 17:57:58 +00:00
|
|
|
#
|
2005-10-03 23:12:47 +00:00
|
|
|
# This program is licensed under the GPLv2
|
2005-08-07 17:49:46 +00:00
|
|
|
|
2010-09-24 20:00:52 +00:00
|
|
|
use 5.008;
|
2005-08-07 17:49:46 +00:00
|
|
|
use strict;
|
|
|
|
use warnings;
|
2005-08-07 18:26:27 +00:00
|
|
|
use CGI qw(:standard :escapeHTML -nosticky);
|
2005-08-07 18:23:49 +00:00
|
|
|
use CGI::Util qw(unescape);
|
2010-04-24 14:00:04 +00:00
|
|
|
use CGI::Carp qw(fatalsToBrowser set_message);
|
replace invalid utf8 sequences by UTF-8 REPLACEMENT CHARACTER (efbfbd)
I still strongly disagree with the git maintainers not to hint people,
to use the only sane default encoding for a distributed project,
which is utf8. I'm tired of hearing filesystem development arguments.
Git is a software offered to merge forth and back across the world
and not to provide a content neutral filesystem.
Btw: I have nothing against the ability to run git in a closed environment,
with a different encoding, that's fine, sure. But that is obviously not
the case for the projects on kernel.org. It's about sane defaults,
nothing else.
You have to make decisions guy, as always in life. The problems to
allow random encoded garbage in commit messages _without_ storing
the encoding, just makes zero sense. Eighter you introduce a per-commit
encoding field, if you insist on this craziness, or you define a default
encoding. Everything else is just lazy and does not solve any problem,
besides that you can claim now, that you are not responsible for the mess
in the repository.
Gitweb shows several commits at once, you allow various encodings committed
to the same repository, without any hint what that garbage from the
individual commits is encoded with. No idea why you don't get
the problem - it's unsolvable. If you merge different peoples work, you
have to speak a common language!
Kay Sievers <kay.sievers@vrfy.org>
2005-11-19 16:41:29 +00:00
|
|
|
use Encode;
|
2005-08-07 18:21:04 +00:00
|
|
|
use Fcntl ':mode';
|
2006-08-01 02:18:34 +00:00
|
|
|
use File::Find qw();
|
2006-08-17 15:29:46 +00:00
|
|
|
use File::Basename qw(basename);
|
2010-11-09 18:27:54 +00:00
|
|
|
use Time::HiRes qw(gettimeofday tv_interval);
|
2005-11-23 03:26:40 +00:00
|
|
|
binmode STDOUT, ':utf8';
|
2005-08-07 17:49:46 +00:00
|
|
|
|
2010-11-09 18:27:54 +00:00
|
|
|
our $t0 = [ gettimeofday() ];
|
2009-09-01 11:39:16 +00:00
|
|
|
our $number_of_git_cmds = 0;
|
|
|
|
|
2006-12-27 23:00:52 +00:00
|
|
|
BEGIN {
|
2007-04-01 20:22:21 +00:00
|
|
|
CGI->compile() if $ENV{'MOD_PERL'};
|
2006-12-27 23:00:52 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 20:50:20 +00:00
|
|
|
our $version = "++GIT_VERSION++";
|
2005-08-07 18:05:15 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our ($my_url, $my_uri, $base_url, $path_info, $home_link);
|
|
|
|
sub evaluate_uri {
|
|
|
|
our $cgi;
|
2009-02-15 09:18:36 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $my_url = $cgi->url();
|
|
|
|
our $my_uri = $cgi->url(-absolute => 1);
|
|
|
|
|
|
|
|
# Base URL for relative URLs in gitweb ($logo, $favicon, ...),
|
|
|
|
# needed and used only for URLs with nonempty PATH_INFO
|
|
|
|
our $base_url = $my_url;
|
|
|
|
|
|
|
|
# When the script is used as DirectoryIndex, the URL does not contain the name
|
|
|
|
# of the script file itself, and $cgi->url() fails to strip PATH_INFO, so we
|
|
|
|
# have to do it ourselves. We make $path_info global because it's also used
|
|
|
|
# later on.
|
|
|
|
#
|
|
|
|
# Another issue with the script being the DirectoryIndex is that the resulting
|
|
|
|
# $my_url data is not the full script URL: this is good, because we want
|
|
|
|
# generated links to keep implying the script name if it wasn't explicitly
|
|
|
|
# indicated in the URL we're handling, but it means that $my_url cannot be used
|
|
|
|
# as base URL.
|
|
|
|
# Therefore, if we needed to strip PATH_INFO, then we know that we have
|
|
|
|
# to build the base URL ourselves:
|
|
|
|
our $path_info = $ENV{"PATH_INFO"};
|
|
|
|
if ($path_info) {
|
|
|
|
if ($my_url =~ s,\Q$path_info\E$,, &&
|
|
|
|
$my_uri =~ s,\Q$path_info\E$,, &&
|
|
|
|
defined $ENV{'SCRIPT_NAME'}) {
|
|
|
|
$base_url = $cgi->url(-base => 1) . $ENV{'SCRIPT_NAME'};
|
|
|
|
}
|
2009-02-15 09:18:36 +00:00
|
|
|
}
|
2010-05-07 12:54:04 +00:00
|
|
|
|
|
|
|
# target of the home link on top of all pages
|
|
|
|
our $home_link = $my_uri || "/";
|
2008-09-29 13:07:42 +00:00
|
|
|
}
|
|
|
|
|
2006-07-12 22:55:10 +00:00
|
|
|
# core git executable to use
|
|
|
|
# this can just be "git" if your webserver has a sensible PATH
|
2006-08-02 20:50:20 +00:00
|
|
|
our $GIT = "++GIT_BINDIR++/git";
|
2006-06-21 07:48:04 +00:00
|
|
|
|
2005-08-07 18:21:04 +00:00
|
|
|
# absolute fs-path which will be prepended to the project path
|
2006-06-21 13:07:08 +00:00
|
|
|
#our $projectroot = "/pub/scm";
|
2006-08-02 20:50:20 +00:00
|
|
|
our $projectroot = "++GITWEB_PROJECTROOT++";
|
2005-08-07 18:21:04 +00:00
|
|
|
|
2007-10-17 03:45:25 +00:00
|
|
|
# fs traversing limit for getting project list
|
|
|
|
# the number is relative to the projectroot
|
|
|
|
our $project_maxdepth = "++GITWEB_PROJECT_MAXDEPTH++";
|
|
|
|
|
2006-08-14 22:50:49 +00:00
|
|
|
# string of the home link on top of all pages
|
|
|
|
our $home_link_str = "++GITWEB_HOME_LINK_STR++";
|
|
|
|
|
2006-07-11 20:10:26 +00:00
|
|
|
# name of your site or organization to appear in page titles
|
|
|
|
# replace this with something more descriptive for clearer bookmarks
|
2006-10-24 03:18:39 +00:00
|
|
|
our $site_name = "++GITWEB_SITENAME++"
|
|
|
|
|| ($ENV{'SERVER_NAME'} || "Untitled") . " Git";
|
2006-07-11 20:10:26 +00:00
|
|
|
|
2006-10-03 12:49:03 +00:00
|
|
|
# filename of html text to include at top of each page
|
|
|
|
our $site_header = "++GITWEB_SITE_HEADER++";
|
2005-08-07 18:22:53 +00:00
|
|
|
# html text to include at home page
|
2006-08-02 20:50:20 +00:00
|
|
|
our $home_text = "++GITWEB_HOMETEXT++";
|
2006-10-03 12:49:03 +00:00
|
|
|
# filename of html text to include at bottom of each page
|
|
|
|
our $site_footer = "++GITWEB_SITE_FOOTER++";
|
|
|
|
|
|
|
|
# URI of stylesheets
|
|
|
|
our @stylesheets = ("++GITWEB_CSS++");
|
2006-10-26 12:41:25 +00:00
|
|
|
# URI of a single stylesheet, which can be overridden in GITWEB_CONFIG.
|
|
|
|
our $stylesheet = undef;
|
2006-10-06 10:31:05 +00:00
|
|
|
# URI of GIT logo (72x27 size)
|
2006-08-02 20:50:20 +00:00
|
|
|
our $logo = "++GITWEB_LOGO++";
|
2006-09-04 18:32:13 +00:00
|
|
|
# URI of GIT favicon, assumed to be image/png type
|
|
|
|
our $favicon = "++GITWEB_FAVICON++";
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
# URI of gitweb.js (JavaScript code for gitweb)
|
|
|
|
our $javascript = "++GITWEB_JS++";
|
2006-06-17 09:23:56 +00:00
|
|
|
|
2006-10-06 10:31:05 +00:00
|
|
|
# URI and label (title) of GIT logo link
|
|
|
|
#our $logo_url = "http://www.kernel.org/pub/software/scm/git/docs/";
|
|
|
|
#our $logo_label = "git documentation";
|
2009-07-12 12:31:28 +00:00
|
|
|
our $logo_url = "http://git-scm.com/";
|
2006-10-06 10:31:05 +00:00
|
|
|
our $logo_label = "git homepage";
|
2006-09-23 19:36:01 +00:00
|
|
|
|
2005-08-07 18:21:23 +00:00
|
|
|
# source of projects list
|
2006-08-02 20:50:20 +00:00
|
|
|
our $projects_list = "++GITWEB_LIST++";
|
2005-08-07 18:21:04 +00:00
|
|
|
|
2007-07-05 00:36:48 +00:00
|
|
|
# the width (in characters) of the projects list "Description" column
|
|
|
|
our $projects_list_description_width = 25;
|
|
|
|
|
2007-04-06 21:58:24 +00:00
|
|
|
# default order of projects list
|
|
|
|
# valid values are none, project, descr, owner, and age
|
|
|
|
our $default_projects_order = "project";
|
|
|
|
|
2006-09-16 22:31:01 +00:00
|
|
|
# show repository only if this file exists
|
|
|
|
# (only effective if this variable evaluates to true)
|
|
|
|
our $export_ok = "++GITWEB_EXPORT_OK++";
|
|
|
|
|
2008-11-05 22:36:23 +00:00
|
|
|
# show repository only if this subroutine returns true
|
|
|
|
# when given the path to the project, for example:
|
|
|
|
# sub { return -e "$_[0]/git-daemon-export-ok"; }
|
|
|
|
our $export_auth_hook = undef;
|
|
|
|
|
2006-09-16 22:31:01 +00:00
|
|
|
# only allow viewing of repositories also shown on the overview page
|
|
|
|
our $strict_export = "++GITWEB_STRICT_EXPORT++";
|
|
|
|
|
2006-08-15 21:03:17 +00:00
|
|
|
# list of git base URLs used for URL to where fetch project from,
|
|
|
|
# i.e. full URL is "$git_base_url/$project"
|
2006-10-26 10:26:44 +00:00
|
|
|
our @git_base_url_list = grep { $_ ne '' } ("++GITWEB_BASE_URL++");
|
2006-08-15 21:03:17 +00:00
|
|
|
|
2006-06-17 11:32:15 +00:00
|
|
|
# default blob_plain mimetype and default charset for text/plain blob
|
2006-06-21 13:07:08 +00:00
|
|
|
our $default_blob_plain_mimetype = 'text/plain';
|
|
|
|
our $default_text_plain_charset = undef;
|
2006-06-17 11:32:15 +00:00
|
|
|
|
2006-06-17 22:01:06 +00:00
|
|
|
# file to use for guessing MIME types before trying /etc/mime.types
|
|
|
|
# (relative to the current git repository)
|
2006-06-21 13:07:08 +00:00
|
|
|
our $mimetypes_file = undef;
|
2006-06-17 22:01:06 +00:00
|
|
|
|
2007-06-03 15:42:44 +00:00
|
|
|
# assume this charset if line contains non-UTF-8 characters;
|
|
|
|
# it should be valid encoding (see Encoding::Supported(3pm) for list),
|
|
|
|
# for which encoding all byte sequences are valid, for example
|
|
|
|
# 'iso-8859-1' aka 'latin1' (it is decoded without checking, so it
|
|
|
|
# could be even 'utf-8' for the old behavior)
|
|
|
|
our $fallback_encoding = 'latin1';
|
|
|
|
|
2007-07-20 00:15:09 +00:00
|
|
|
# rename detection options for git-diff and git-diff-tree
|
|
|
|
# - default is '-M', with the cost proportional to
|
|
|
|
# (number of removed files) * (number of new files).
|
|
|
|
# - more costly is '-C' (which implies '-M'), with the cost proportional to
|
|
|
|
# (number of changed files + number of removed files) * (number of new files)
|
|
|
|
# - even more costly is '-C', '--find-copies-harder' with cost
|
|
|
|
# (number of files in the original tree) * (number of new files)
|
|
|
|
# - one might want to include '-B' option, e.g. '-B', '-M'
|
|
|
|
our @diff_opts = ('-M'); # taken from git_commit
|
|
|
|
|
2009-02-08 00:00:09 +00:00
|
|
|
# Disables features that would allow repository owners to inject script into
|
|
|
|
# the gitweb domain.
|
|
|
|
our $prevent_xss = 0;
|
|
|
|
|
2010-09-21 07:25:19 +00:00
|
|
|
# Path to the highlight executable to use (must be the one from
|
|
|
|
# http://www.andre-simon.de due to assumptions about parameters and output).
|
|
|
|
# Useful if highlight is not installed on your webserver's PATH.
|
|
|
|
# [Default: highlight]
|
|
|
|
our $highlight_bin = "++HIGHLIGHT_BIN++";
|
|
|
|
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
# information about snapshot formats that gitweb is capable of serving
|
|
|
|
our %known_snapshot_formats = (
|
|
|
|
# name => {
|
|
|
|
# 'display' => display name,
|
|
|
|
# 'type' => mime type,
|
|
|
|
# 'suffix' => filename suffix,
|
|
|
|
# 'format' => --format for git-archive,
|
|
|
|
# 'compressor' => [compressor command and arguments]
|
2009-08-06 14:25:39 +00:00
|
|
|
# (array reference, optional)
|
|
|
|
# 'disabled' => boolean (optional)}
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
#
|
|
|
|
'tgz' => {
|
|
|
|
'display' => 'tar.gz',
|
|
|
|
'type' => 'application/x-gzip',
|
|
|
|
'suffix' => '.tar.gz',
|
|
|
|
'format' => 'tar',
|
|
|
|
'compressor' => ['gzip']},
|
|
|
|
|
|
|
|
'tbz2' => {
|
|
|
|
'display' => 'tar.bz2',
|
|
|
|
'type' => 'application/x-bzip2',
|
|
|
|
'suffix' => '.tar.bz2',
|
|
|
|
'format' => 'tar',
|
|
|
|
'compressor' => ['bzip2']},
|
|
|
|
|
gitweb: add support for XZ compressed snapshots
The XZ compression format uses the LZMA2 compression algorithm, which
often yields higher compression ratios than both GZip and BZip2 at the
cost of using more CPU time and RAM. XZ is the slowest for compression,
but still much faster than BZip2 for decompression, almost comparable
to GZip (see benchmarks below).
Some simple benchmarks show the pros and cons of using XZ compression;
starting with an already tarball'd archive of the repos listed below.
Memory usage seemed to be consistent for any given algorithm at their
respective default compression levels.
CPU: AMD Sempron 3400+ (1 core @ 1.8GHz with 256K L2 cache)
Virtual Memory Usage
GZip: 4152K BZip2: 13352K XZ: 102M
Linux 2.6 series (f5886c7f96f2542382d3a983c5f13e03d7fc5259) 349M
gzip 23.70s user 0.47s system 99% cpu 24.227 total 76M
gunzip 3.74s user 0.74s system 94% cpu 4.741 total
bzip2 130.96s user 0.53s system 99% cpu 2:11.97 total 59M
bunzip2 31.05s user 1.02s system 99% cpu 32.355 total
xz 448.78s user 0.91s system 99% cpu 7:31.28 total 51M
unxz 7.67s user 0.80s system 98% cpu 8.607 total
Git (0a53e9ddeaddad63ad106860237bbf53411d11a7) 11M
gzip 0.77s user 0.03s system 99% cpu 0.792 total 2.5M
gunzip 0.12s user 0.02s system 98% cpu 0.142 total
bzip2 3.42s user 0.02s system 99% cpu 3.454 total 2.1M
bunzip2 0.95s user 0.03s system 99% cpu 0.984 total
xz 12.88s user 0.14s system 98% cpu 13.239 total 1.9M
unxz 0.27s user 0.03s system 99% cpu 0.298 total
XZ (669413bb2db954bbfde3c4542fddbbab53891eb4) 1.8M
gzip 0.12s user 0.00s system 95% cpu 0.132 total 442K
gunzip 0.02s user 0.00s system 97% cpu 0.027 total
bzip2 1.28s user 0.01s system 99% cpu 1.298 total 363K
bunzip2 0.15s user 0.01s system 100% cpu 0.157 total
xz 1.62s user 0.03s system 99% cpu 1.652 total 347K
unxz 0.05s user 0.00s system 99% cpu 0.058 total
From a time and memory perspective, nothing compares to GZip, but if
given an average upload speed of 20KB/s, it would take ~400 seconds
longer to transfer the BZip2'd kernel snapshot than the XZ snapshot;
the transfer time difference is even greater between GZip and XZ. The
real time savings are relatively the same for all test cases, but less
dramatic for smaller repositories.
XZ decompresses ~1.8-2 times slower than GZip, and ~2.7-3.75 times
faster than BZip2; XZ gets relatively faster as snapshots get larger.
However, XZ takes relatively longer to compress as snapshots get larger.
The downside for XZ'd snapshots is the large CPU and memory load put on
the server to generate the compressed snapshot, though XZ will
eventually
have threading support, and the real clock time for making XZ'd
snapshots
would decrease if the server had a beefy multi-core CPU.
XZ compression is disabled by default to allow upgrades to take place
without any surprises, as the CPU and memory requirements will be an
issue for high load or lightweight servers. Also, the XZ format is still
new (format declared stable ~6 months ago), and there have been no
"stable" releases of the utils yet.
Signed-off-by: Mark Rada <marada@uwaterloo.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-08-06 14:28:25 +00:00
|
|
|
'txz' => {
|
|
|
|
'display' => 'tar.xz',
|
|
|
|
'type' => 'application/x-xz',
|
|
|
|
'suffix' => '.tar.xz',
|
|
|
|
'format' => 'tar',
|
|
|
|
'compressor' => ['xz'],
|
|
|
|
'disabled' => 1},
|
|
|
|
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
'zip' => {
|
|
|
|
'display' => 'zip',
|
|
|
|
'type' => 'application/x-zip',
|
|
|
|
'suffix' => '.zip',
|
|
|
|
'format' => 'zip'},
|
|
|
|
);
|
|
|
|
|
|
|
|
# Aliases so we understand old gitweb.snapshot values in repository
|
|
|
|
# configuration.
|
|
|
|
our %known_snapshot_format_aliases = (
|
|
|
|
'gzip' => 'tgz',
|
|
|
|
'bzip2' => 'tbz2',
|
gitweb: add support for XZ compressed snapshots
The XZ compression format uses the LZMA2 compression algorithm, which
often yields higher compression ratios than both GZip and BZip2 at the
cost of using more CPU time and RAM. XZ is the slowest for compression,
but still much faster than BZip2 for decompression, almost comparable
to GZip (see benchmarks below).
Some simple benchmarks show the pros and cons of using XZ compression;
starting with an already tarball'd archive of the repos listed below.
Memory usage seemed to be consistent for any given algorithm at their
respective default compression levels.
CPU: AMD Sempron 3400+ (1 core @ 1.8GHz with 256K L2 cache)
Virtual Memory Usage
GZip: 4152K BZip2: 13352K XZ: 102M
Linux 2.6 series (f5886c7f96f2542382d3a983c5f13e03d7fc5259) 349M
gzip 23.70s user 0.47s system 99% cpu 24.227 total 76M
gunzip 3.74s user 0.74s system 94% cpu 4.741 total
bzip2 130.96s user 0.53s system 99% cpu 2:11.97 total 59M
bunzip2 31.05s user 1.02s system 99% cpu 32.355 total
xz 448.78s user 0.91s system 99% cpu 7:31.28 total 51M
unxz 7.67s user 0.80s system 98% cpu 8.607 total
Git (0a53e9ddeaddad63ad106860237bbf53411d11a7) 11M
gzip 0.77s user 0.03s system 99% cpu 0.792 total 2.5M
gunzip 0.12s user 0.02s system 98% cpu 0.142 total
bzip2 3.42s user 0.02s system 99% cpu 3.454 total 2.1M
bunzip2 0.95s user 0.03s system 99% cpu 0.984 total
xz 12.88s user 0.14s system 98% cpu 13.239 total 1.9M
unxz 0.27s user 0.03s system 99% cpu 0.298 total
XZ (669413bb2db954bbfde3c4542fddbbab53891eb4) 1.8M
gzip 0.12s user 0.00s system 95% cpu 0.132 total 442K
gunzip 0.02s user 0.00s system 97% cpu 0.027 total
bzip2 1.28s user 0.01s system 99% cpu 1.298 total 363K
bunzip2 0.15s user 0.01s system 100% cpu 0.157 total
xz 1.62s user 0.03s system 99% cpu 1.652 total 347K
unxz 0.05s user 0.00s system 99% cpu 0.058 total
From a time and memory perspective, nothing compares to GZip, but if
given an average upload speed of 20KB/s, it would take ~400 seconds
longer to transfer the BZip2'd kernel snapshot than the XZ snapshot;
the transfer time difference is even greater between GZip and XZ. The
real time savings are relatively the same for all test cases, but less
dramatic for smaller repositories.
XZ decompresses ~1.8-2 times slower than GZip, and ~2.7-3.75 times
faster than BZip2; XZ gets relatively faster as snapshots get larger.
However, XZ takes relatively longer to compress as snapshots get larger.
The downside for XZ'd snapshots is the large CPU and memory load put on
the server to generate the compressed snapshot, though XZ will
eventually
have threading support, and the real clock time for making XZ'd
snapshots
would decrease if the server had a beefy multi-core CPU.
XZ compression is disabled by default to allow upgrades to take place
without any surprises, as the CPU and memory requirements will be an
issue for high load or lightweight servers. Also, the XZ format is still
new (format declared stable ~6 months ago), and there have been no
"stable" releases of the utils yet.
Signed-off-by: Mark Rada <marada@uwaterloo.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-08-06 14:28:25 +00:00
|
|
|
'xz' => 'txz',
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
|
|
|
|
# backward compatibility: legacy gitweb config support
|
|
|
|
'x-gzip' => undef, 'gz' => undef,
|
|
|
|
'x-bzip2' => undef, 'bz2' => undef,
|
|
|
|
'x-zip' => undef, '' => undef,
|
|
|
|
);
|
|
|
|
|
2009-06-29 22:00:51 +00:00
|
|
|
# Pixel sizes for icons and avatars. If the default font sizes or lineheights
|
|
|
|
# are changed, it may be appropriate to change these values too via
|
|
|
|
# $GITWEB_CONFIG.
|
|
|
|
our %avatar_size = (
|
|
|
|
'default' => 16,
|
|
|
|
'double' => 32
|
|
|
|
);
|
|
|
|
|
2010-01-30 22:30:39 +00:00
|
|
|
# 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;
|
|
|
|
|
2010-07-28 18:40:53 +00:00
|
|
|
# configuration for 'highlight' (http://www.andre-simon.de/)
|
|
|
|
# match by basename
|
|
|
|
our %highlight_basename = (
|
|
|
|
#'Program' => 'py',
|
|
|
|
#'Library' => 'py',
|
|
|
|
'SConstruct' => 'py', # SCons equivalent of Makefile
|
|
|
|
'Makefile' => 'make',
|
|
|
|
);
|
|
|
|
# match by extension
|
|
|
|
our %highlight_ext = (
|
|
|
|
# main extensions, defining name of syntax;
|
|
|
|
# see files in /usr/share/highlight/langDefs/ directory
|
|
|
|
map { $_ => $_ }
|
2010-12-30 21:20:28 +00:00
|
|
|
qw(py c cpp rb java css php sh pl js tex bib xml awk bat ini spec tcl sql make),
|
2010-07-28 18:40:53 +00:00
|
|
|
# alternate extensions, see /etc/highlight/filetypes.conf
|
|
|
|
'h' => 'c',
|
2010-12-30 21:20:28 +00:00
|
|
|
map { $_ => 'sh' } qw(bash zsh ksh),
|
2010-07-28 18:40:53 +00:00
|
|
|
map { $_ => 'cpp' } qw(cxx c++ cc),
|
2010-12-30 21:20:28 +00:00
|
|
|
map { $_ => 'php' } qw(php3 php4 php5 phps),
|
2010-07-28 18:40:53 +00:00
|
|
|
map { $_ => 'pl' } qw(perl pm), # perhaps also 'cgi'
|
2010-12-30 21:20:28 +00:00
|
|
|
map { $_ => 'make'} qw(mak mk),
|
2010-07-28 18:40:53 +00:00
|
|
|
map { $_ => 'xml' } qw(xhtml html htm),
|
|
|
|
);
|
|
|
|
|
2006-08-20 06:23:04 +00:00
|
|
|
# You define site-wide feature defaults here; override them with
|
|
|
|
# $GITWEB_CONFIG as necessary.
|
2006-08-22 14:52:50 +00:00
|
|
|
our %feature = (
|
2006-08-26 17:14:22 +00:00
|
|
|
# feature => {
|
|
|
|
# 'sub' => feature-sub (subroutine),
|
|
|
|
# 'override' => allow-override (boolean),
|
|
|
|
# 'default' => [ default options...] (array reference)}
|
|
|
|
#
|
2007-05-14 23:55:44 +00:00
|
|
|
# if feature is overridable (it means that allow-override has true value),
|
2006-08-26 17:14:22 +00:00
|
|
|
# then feature-sub will be called with default options as parameters;
|
|
|
|
# return value of feature-sub indicates if to enable specified feature
|
|
|
|
#
|
2007-05-14 23:55:44 +00:00
|
|
|
# if there is no 'sub' key (no feature-sub), then feature cannot be
|
2010-08-22 11:12:12 +00:00
|
|
|
# overridden
|
2007-05-14 23:55:44 +00:00
|
|
|
#
|
2008-12-02 22:57:28 +00:00
|
|
|
# use gitweb_get_feature(<feature>) to retrieve the <feature> value
|
|
|
|
# (an array) or gitweb_check_feature(<feature>) to check if <feature>
|
|
|
|
# is enabled
|
2006-08-22 14:52:50 +00:00
|
|
|
|
2006-10-07 13:17:47 +00:00
|
|
|
# Enable the 'blame' blob view, showing the last commit that modified
|
|
|
|
# each line in the file. This can be very CPU-intensive.
|
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'blame'}{'default'} = [1];
|
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
|
|
|
# $feature{'blame'}{'override'} = 1;
|
|
|
|
# and in project config gitweb.blame = 0|1;
|
2006-08-22 14:52:50 +00:00
|
|
|
'blame' => {
|
2008-12-16 06:16:19 +00:00
|
|
|
'sub' => sub { feature_bool('blame', @_) },
|
2006-08-22 14:52:50 +00:00
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
|
|
|
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
# Enable the 'snapshot' link, providing a compressed archive of any
|
2006-10-07 13:17:47 +00:00
|
|
|
# tree. This can potentially generate high traffic if you have large
|
|
|
|
# project.
|
|
|
|
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
# Value is a list of formats defined in %known_snapshot_formats that
|
|
|
|
# you wish to offer.
|
2006-10-07 13:17:47 +00:00
|
|
|
# To disable system wide have in $GITWEB_CONFIG
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
# $feature{'snapshot'}{'default'} = [];
|
2006-10-07 13:17:47 +00:00
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
2006-12-08 11:44:31 +00:00
|
|
|
# $feature{'snapshot'}{'override'} = 1;
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
# and in project config, a comma-separated list of formats or "none"
|
|
|
|
# to disable. Example: gitweb.snapshot = tbz2,zip;
|
2006-08-22 14:52:50 +00:00
|
|
|
'snapshot' => {
|
|
|
|
'sub' => \&feature_snapshot,
|
|
|
|
'override' => 0,
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
'default' => ['tgz']},
|
2006-09-10 22:29:27 +00:00
|
|
|
|
2006-12-23 03:35:16 +00:00
|
|
|
# Enable text search, which will list the commits which match author,
|
|
|
|
# committer or commit text to a given string. Enabled by default.
|
2007-05-14 23:55:44 +00:00
|
|
|
# Project specific override is not supported.
|
2006-12-23 03:35:16 +00:00
|
|
|
'search' => {
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [1]},
|
|
|
|
|
2007-05-17 02:31:12 +00:00
|
|
|
# Enable grep search, which will list the files in currently selected
|
|
|
|
# tree containing the given string. Enabled by default. This can be
|
|
|
|
# potentially CPU-intensive, of course.
|
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'grep'}{'default'} = [1];
|
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
|
|
|
# $feature{'grep'}{'override'} = 1;
|
|
|
|
# and in project config gitweb.grep = 0|1;
|
|
|
|
'grep' => {
|
2008-12-16 06:16:19 +00:00
|
|
|
'sub' => sub { feature_bool('grep', @_) },
|
2007-05-17 02:31:12 +00:00
|
|
|
'override' => 0,
|
|
|
|
'default' => [1]},
|
|
|
|
|
2006-10-07 13:17:47 +00:00
|
|
|
# Enable the pickaxe search, which will list the commits that modified
|
|
|
|
# a given string in a file. This can be practical and quite faster
|
|
|
|
# alternative to 'blame', but still potentially CPU-intensive.
|
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'pickaxe'}{'default'} = [1];
|
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
|
|
|
# $feature{'pickaxe'}{'override'} = 1;
|
|
|
|
# and in project config gitweb.pickaxe = 0|1;
|
2006-09-10 22:29:27 +00:00
|
|
|
'pickaxe' => {
|
2008-12-16 06:16:19 +00:00
|
|
|
'sub' => sub { feature_bool('pickaxe', @_) },
|
2006-09-10 22:29:27 +00:00
|
|
|
'override' => 0,
|
|
|
|
'default' => [1]},
|
2006-10-01 21:57:48 +00:00
|
|
|
|
2009-09-07 12:40:00 +00:00
|
|
|
# Enable showing size of blobs in a 'tree' view, in a separate
|
|
|
|
# column, similar to what 'ls -l' does. This cost a bit of IO.
|
|
|
|
|
|
|
|
# To disable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'show-sizes'}{'default'} = [0];
|
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
|
|
|
# $feature{'show-sizes'}{'override'} = 1;
|
|
|
|
# and in project config gitweb.showsizes = 0|1;
|
|
|
|
'show-sizes' => {
|
|
|
|
'sub' => sub { feature_bool('showsizes', @_) },
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [1]},
|
|
|
|
|
2006-10-07 13:17:47 +00:00
|
|
|
# Make gitweb use an alternative format of the URLs which can be
|
|
|
|
# more readable and natural-looking: project name is embedded
|
|
|
|
# directly in the path and the query string contains other
|
|
|
|
# auxiliary information. All gitweb installations recognize
|
|
|
|
# URL in either format; this configures in which formats gitweb
|
|
|
|
# generates links.
|
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'pathinfo'}{'default'} = [1];
|
|
|
|
# Project specific override is not supported.
|
|
|
|
|
|
|
|
# Note that you will need to change the default location of CSS,
|
|
|
|
# favicon, logo and possibly other files to an absolute URL. Also,
|
|
|
|
# if gitweb.cgi serves as your indexfile, you will need to force
|
|
|
|
# $my_uri to contain the script name in your $GITWEB_CONFIG.
|
2006-10-01 21:57:48 +00:00
|
|
|
'pathinfo' => {
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
2006-10-24 03:33:17 +00:00
|
|
|
|
|
|
|
# Make gitweb consider projects in project root subdirectories
|
|
|
|
# to be forks of existing projects. Given project $projname.git,
|
|
|
|
# projects matching $projname/*.git will not be shown in the main
|
|
|
|
# projects list, instead a '+' mark will be added to $projname
|
|
|
|
# there and a 'forks' view will be enabled for the project, listing
|
2007-04-06 21:58:11 +00:00
|
|
|
# all the forks. If project list is taken from a file, forks have
|
|
|
|
# to be listed after the main project.
|
2006-10-24 03:33:17 +00:00
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'forks'}{'default'} = [1];
|
|
|
|
# Project specific override is not supported.
|
|
|
|
'forks' => {
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
2008-10-02 14:36:52 +00:00
|
|
|
|
|
|
|
# Insert custom links to the action bar of all project pages.
|
|
|
|
# This enables you mainly to link to third-party scripts integrating
|
|
|
|
# into gitweb; e.g. git-browser for graphical history representation
|
|
|
|
# or custom web-based repository administration interface.
|
|
|
|
|
|
|
|
# The 'default' value consists of a list of triplets in the form
|
|
|
|
# (label, link, position) where position is the label after which
|
2008-10-11 22:02:32 +00:00
|
|
|
# to insert the link and link is a format string where %n expands
|
2008-10-02 14:36:52 +00:00
|
|
|
# to the project name, %f to the project path within the filesystem,
|
|
|
|
# %h to the current hash (h gitweb parameter) and %b to the current
|
2008-10-11 22:02:32 +00:00
|
|
|
# hash base (hb gitweb parameter); %% expands to %.
|
2008-10-02 14:36:52 +00:00
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG e.g.
|
|
|
|
# $feature{'actions'}{'default'} = [('graphiclog',
|
|
|
|
# '/git-browser/by-commit.html?r=%n', 'summary')];
|
|
|
|
# Project specific override is not supported.
|
|
|
|
'actions' => {
|
|
|
|
'override' => 0,
|
|
|
|
'default' => []},
|
2008-10-03 14:41:25 +00:00
|
|
|
|
2008-10-02 15:13:02 +00:00
|
|
|
# Allow gitweb scan project content tags described in ctags/
|
|
|
|
# of project repository, and display the popular Web 2.0-ish
|
|
|
|
# "tag cloud" near the project list. Note that this is something
|
|
|
|
# COMPLETELY different from the normal Git tags.
|
|
|
|
|
|
|
|
# gitweb by itself can show existing tags, but it does not handle
|
|
|
|
# tagging itself; you need an external application for that.
|
|
|
|
# For an example script, check Girocco's cgi/tagproj.cgi.
|
|
|
|
# You may want to install the HTML::TagCloud Perl module to get
|
|
|
|
# a pretty tag cloud instead of just a list of tags.
|
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'ctags'}{'default'} = ['path_to_tag_script'];
|
|
|
|
# Project specific override is not supported.
|
|
|
|
'ctags' => {
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
2008-12-18 07:13:16 +00:00
|
|
|
|
|
|
|
# The maximum number of patches in a patchset generated in patch
|
|
|
|
# view. Set this to 0 or undef to disable patch view, or to a
|
|
|
|
# negative number to remove any limit.
|
|
|
|
|
|
|
|
# To disable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'patches'}{'default'} = [0];
|
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
|
|
|
# $feature{'patches'}{'override'} = 1;
|
|
|
|
# and in project config gitweb.patches = 0|n;
|
|
|
|
# where n is the maximum number of patches allowed in a patchset.
|
|
|
|
'patches' => {
|
|
|
|
'sub' => \&feature_patches,
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [16]},
|
2009-06-29 22:00:51 +00:00
|
|
|
|
|
|
|
# Avatar support. When this feature is enabled, views such as
|
|
|
|
# shortlog or commit will display an avatar associated with
|
|
|
|
# the email of the committer(s) and/or author(s).
|
|
|
|
|
2009-06-29 22:00:53 +00:00
|
|
|
# Currently available providers are gravatar and picon.
|
|
|
|
# If an unknown provider is specified, the feature is disabled.
|
|
|
|
|
|
|
|
# Gravatar depends on Digest::MD5.
|
|
|
|
# Picon currently relies on the indiana.edu database.
|
2009-06-29 22:00:51 +00:00
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
2009-06-29 22:00:53 +00:00
|
|
|
# $feature{'avatar'}{'default'} = ['<provider>'];
|
|
|
|
# where <provider> is either gravatar or picon.
|
2009-06-29 22:00:51 +00:00
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
|
|
|
# $feature{'avatar'}{'override'} = 1;
|
2009-06-29 22:00:53 +00:00
|
|
|
# and in project config gitweb.avatar = <provider>;
|
2009-06-29 22:00:51 +00:00
|
|
|
'avatar' => {
|
|
|
|
'sub' => \&feature_avatar,
|
|
|
|
'override' => 0,
|
|
|
|
'default' => ['']},
|
2009-09-01 11:39:16 +00:00
|
|
|
|
|
|
|
# Enable displaying how much time and how many git commands
|
|
|
|
# it took to generate and display page. Disabled by default.
|
|
|
|
# Project specific override is not supported.
|
|
|
|
'timed' => {
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
2009-11-26 20:12:15 +00:00
|
|
|
|
|
|
|
# Enable turning some links into links to actions which require
|
|
|
|
# JavaScript to run (like 'blame_incremental'). Not enabled by
|
|
|
|
# default. Project specific override is currently not supported.
|
|
|
|
'javascript-actions' => {
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
2010-04-27 19:34:44 +00:00
|
|
|
|
|
|
|
# Syntax highlighting support. This is based on Daniel Svensson's
|
|
|
|
# and Sham Chukoury's work in gitweb-xmms2.git.
|
2010-04-27 19:34:45 +00:00
|
|
|
# It requires the 'highlight' program present in $PATH,
|
|
|
|
# and therefore is disabled by default.
|
2010-04-27 19:34:44 +00:00
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'highlight'}{'default'} = [1];
|
|
|
|
|
|
|
|
'highlight' => {
|
|
|
|
'sub' => sub { feature_bool('highlight', @_) },
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
2010-11-11 12:26:09 +00:00
|
|
|
|
|
|
|
# Enable displaying of remote heads in the heads list
|
|
|
|
|
|
|
|
# To enable system wide have in $GITWEB_CONFIG
|
|
|
|
# $feature{'remote_heads'}{'default'} = [1];
|
|
|
|
# To have project specific config enable override in $GITWEB_CONFIG
|
|
|
|
# $feature{'remote_heads'}{'override'} = 1;
|
|
|
|
# and in project config gitweb.remote_heads = 0|1;
|
|
|
|
'remote_heads' => {
|
|
|
|
'sub' => sub { feature_bool('remote_heads', @_) },
|
|
|
|
'override' => 0,
|
|
|
|
'default' => [0]},
|
2006-08-20 06:23:04 +00:00
|
|
|
);
|
|
|
|
|
2008-11-29 21:02:08 +00:00
|
|
|
sub gitweb_get_feature {
|
2006-08-20 06:23:04 +00:00
|
|
|
my ($name) = @_;
|
2006-09-25 23:56:17 +00:00
|
|
|
return unless exists $feature{$name};
|
2006-08-22 14:52:50 +00:00
|
|
|
my ($sub, $override, @defaults) = (
|
|
|
|
$feature{$name}{'sub'},
|
|
|
|
$feature{$name}{'override'},
|
|
|
|
@{$feature{$name}{'default'}});
|
gitweb: Fix project-specific feature override behavior
This commit fixes a bug in processing project-specific override in
a situation when there is no project, e.g. for the projects list page.
When 'snapshot' feature had project specific config override enabled
by putting
$feature{'snapshot'}{'override'} = 1;
(or equivalent) in $GITWEB_CONFIG, and when viewing toplevel gitweb
page, which means the projects list page (to be more exact this
happens for any project-less action), gitweb would put the following
Perl warnings in error log:
gitweb.cgi: Use of uninitialized value $git_dir in concatenation (.) or string at gitweb.cgi line 2065.
fatal: error processing config file(s)
gitweb.cgi: Use of uninitialized value $git_dir in concatenation (.) or string at gitweb.cgi line 2221.
gitweb.cgi: Use of uninitialized value $git_dir in concatenation (.) or string at gitweb.cgi line 2218.
The problem is in the following fragment of code:
# path to the current git repository
our $git_dir;
$git_dir = "$projectroot/$project" if $project;
# list of supported snapshot formats
our @snapshot_fmts = gitweb_get_feature('snapshot');
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
For the toplevel gitweb page, which is the list of projects, $project is not
defined, therefore neither is $git_dir. gitweb_get_feature() subroutine
calls git_get_project_config() if project specific override is turned
on... but we don't have project here.
Those errors mentioned above occur in the following fragment of code in
git_get_project_config():
# get config
if (!defined $config_file ||
$config_file ne "$git_dir/config") {
%config = git_parse_project_config('gitweb');
$config_file = "$git_dir/config";
}
git_parse_project_config() calls git_cmd() which has '--git-dir='.$git_dir
There are (at least) three possible solutions:
1. Harden gitweb_get_feature() so that it doesn't call
git_get_project_config() if $project (and therefore $git_dir) is not
defined; there is no project for project specific config.
2. Harden git_get_project_config() like you did in your fix, returning early
if $git_dir is not defined.
3. Harden git_cmd() so that it doesn't add "--git-dir=$git_dir" if $git_dir
is not defined, and change git_get_project_config() so that it doesn't
even try to access $git_dir if it is not defined.
This commit implements both 1.) and 2.), i.e. gitweb_get_feature() doesn't
call project-specific override if $git_dir is not defined (if there is no
project), and git_get_project_config() returns early if $git_dir is not
defined.
Add a test for this bug to t/t9500-gitweb-standalone-no-errors.sh test.
Reported-by: Eli Barzilay <eli@barzilay.org>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-03-01 21:51:34 +00:00
|
|
|
# project specific override is possible only if we have project
|
|
|
|
our $git_dir; # global variable, declared later
|
|
|
|
if (!$override || !defined $git_dir) {
|
|
|
|
return @defaults;
|
|
|
|
}
|
2006-10-03 18:07:43 +00:00
|
|
|
if (!defined $sub) {
|
2009-08-28 03:18:49 +00:00
|
|
|
warn "feature $name is not overridable";
|
2006-10-03 18:07:43 +00:00
|
|
|
return @defaults;
|
|
|
|
}
|
2006-08-20 06:23:04 +00:00
|
|
|
return $sub->(@defaults);
|
|
|
|
}
|
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
# A wrapper to check if a given feature is enabled.
|
|
|
|
# With this, you can say
|
|
|
|
#
|
|
|
|
# my $bool_feat = gitweb_check_feature('bool_feat');
|
|
|
|
# gitweb_check_feature('bool_feat') or somecode;
|
|
|
|
#
|
|
|
|
# instead of
|
|
|
|
#
|
|
|
|
# my ($bool_feat) = gitweb_get_feature('bool_feat');
|
|
|
|
# (gitweb_get_feature('bool_feat'))[0] or somecode;
|
|
|
|
#
|
|
|
|
sub gitweb_check_feature {
|
|
|
|
return (gitweb_get_feature(@_))[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-16 06:16:19 +00:00
|
|
|
sub feature_bool {
|
|
|
|
my $key = shift;
|
|
|
|
my ($val) = git_get_project_config($key, '--bool');
|
2006-08-20 06:23:04 +00:00
|
|
|
|
2009-02-18 13:09:41 +00:00
|
|
|
if (!defined $val) {
|
|
|
|
return ($_[0]);
|
|
|
|
} elsif ($val eq 'true') {
|
2008-12-16 06:16:19 +00:00
|
|
|
return (1);
|
2006-08-20 06:23:04 +00:00
|
|
|
} elsif ($val eq 'false') {
|
2008-12-16 06:16:19 +00:00
|
|
|
return (0);
|
2006-08-20 06:23:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub feature_snapshot {
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
my (@fmts) = @_;
|
2006-08-20 06:23:04 +00:00
|
|
|
|
|
|
|
my ($val) = git_get_project_config('snapshot');
|
|
|
|
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
if ($val) {
|
|
|
|
@fmts = ($val eq 'none' ? () : split /\s*[,\s]\s*/, $val);
|
2006-08-20 06:23:04 +00:00
|
|
|
}
|
|
|
|
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
return @fmts;
|
2006-09-28 23:49:21 +00:00
|
|
|
}
|
|
|
|
|
2008-12-18 07:13:16 +00:00
|
|
|
sub feature_patches {
|
|
|
|
my @val = (git_get_project_config('patches', '--int'));
|
|
|
|
|
|
|
|
if (@val) {
|
|
|
|
return @val;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ($_[0]);
|
|
|
|
}
|
|
|
|
|
2009-06-29 22:00:51 +00:00
|
|
|
sub feature_avatar {
|
|
|
|
my @val = (git_get_project_config('avatar'));
|
|
|
|
|
|
|
|
return @val ? @val : @_;
|
|
|
|
}
|
|
|
|
|
2006-10-03 09:30:47 +00:00
|
|
|
# checking HEAD file with -e is fragile if the repository was
|
|
|
|
# initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed
|
|
|
|
# and then pruned.
|
|
|
|
sub check_head_link {
|
|
|
|
my ($dir) = @_;
|
|
|
|
my $headfile = "$dir/HEAD";
|
|
|
|
return ((-e $headfile) ||
|
|
|
|
(-l $headfile && readlink($headfile) =~ /^refs\/heads\//));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub check_export_ok {
|
|
|
|
my ($dir) = @_;
|
|
|
|
return (check_head_link($dir) &&
|
2008-11-05 22:36:23 +00:00
|
|
|
(!$export_ok || -e "$dir/$export_ok") &&
|
|
|
|
(!$export_auth_hook || $export_auth_hook->($dir)));
|
2006-10-03 09:30:47 +00:00
|
|
|
}
|
|
|
|
|
gitweb: Fix support for legacy gitweb config for snapshots
Earlier commit which cleaned up snapshot support and introduced
support for multiple snapshot formats changed the format of
$feature{'snapshot'}{'default'} (gitweb configuration) and
gitweb.snapshot configuration variable (repository configuration).
It supported old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip'
and tried to support, but failed to do that, old values of
$feature{'snapshot'}{'default'}; at least those corresponding to
old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
This commit moves legacy configuration support out of feature_snapshot
subroutine to separate filter_snapshot_fmts subroutine. The
filter_snapshot_fmts is used on result on result of
gitweb_check_feature('snapshot'). This way feature_snapshot deals
_only_ with repository config.
As a byproduct you can now use 'gzip' and 'bzip2' as aliases to 'tgz'
and 'tbz2' also in $feature{'snapshot'}{'default'}, not only in
gitweb.snapshot.
While at it do some whitespace cleanup: use tabs for indent, but
spaces for align.
Noticed-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Tested-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-22 21:41:20 +00:00
|
|
|
# process alternate names for backward compatibility
|
|
|
|
# filter out unsupported (unknown) snapshot formats
|
|
|
|
sub filter_snapshot_fmts {
|
|
|
|
my @fmts = @_;
|
|
|
|
|
|
|
|
@fmts = map {
|
|
|
|
exists $known_snapshot_format_aliases{$_} ?
|
|
|
|
$known_snapshot_format_aliases{$_} : $_} @fmts;
|
2009-05-10 00:40:37 +00:00
|
|
|
@fmts = grep {
|
2009-08-06 14:25:39 +00:00
|
|
|
exists $known_snapshot_formats{$_} &&
|
|
|
|
!$known_snapshot_formats{$_}{'disabled'}} @fmts;
|
gitweb: Fix support for legacy gitweb config for snapshots
Earlier commit which cleaned up snapshot support and introduced
support for multiple snapshot formats changed the format of
$feature{'snapshot'}{'default'} (gitweb configuration) and
gitweb.snapshot configuration variable (repository configuration).
It supported old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip'
and tried to support, but failed to do that, old values of
$feature{'snapshot'}{'default'}; at least those corresponding to
old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
This commit moves legacy configuration support out of feature_snapshot
subroutine to separate filter_snapshot_fmts subroutine. The
filter_snapshot_fmts is used on result on result of
gitweb_check_feature('snapshot'). This way feature_snapshot deals
_only_ with repository config.
As a byproduct you can now use 'gzip' and 'bzip2' as aliases to 'tgz'
and 'tbz2' also in $feature{'snapshot'}{'default'}, not only in
gitweb.snapshot.
While at it do some whitespace cleanup: use tabs for indent, but
spaces for align.
Noticed-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Tested-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-22 21:41:20 +00:00
|
|
|
}
|
|
|
|
|
gitweb: selectable configurations that change with each request
Allow selecting whether configuration file should be (re)parsed on each
request (the default, for backward compatibility with configurations that
change per session, see commit 7f425db (gitweb: allow configurations that
change with each request, 2010-07-30)), or whether should it be parsed only
once (for performance speedup for persistent environments, though currently
only FastCGI is able to make use of it, when flexibility is not important).
You can also have configuration file parsed only once, but have parts of
configuration (re)evaluated once per each request.
This is done by introducing $per_request_config variable: if set to code
reference, this code would be run once per request, while config file would
be parsed only once. For example gitolite's contrib/gitweb/gitweb.conf
fragment mentioned in 7f425db could be rewritten as
our $per_request_config = sub {
$ENV{GL_USER} = ($cgi && $cgi->remote_user) || "gitweb";
};
to make use of this feature.
If $per_request_config is not a code reference, it is taken to be boolean
variable, to choose between running config file for each request
(flexibility), and running config file only once (performance in
persistent environments).
The default value for $per_request_config is 1 (true), which means that
old configuration that require to change per session (like gitolite's)
will keep working.
While at it, make it so evaluate_git_version() is run only once.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-11-25 18:43:59 +00:00
|
|
|
# If it is set to code reference, it is code that it is to be run once per
|
|
|
|
# request, allowing updating configurations that change with each request,
|
|
|
|
# while running other code in config file only once.
|
|
|
|
#
|
|
|
|
# Otherwise, if it is false then gitweb would process config file only once;
|
|
|
|
# if it is true then gitweb config would be run for each request.
|
|
|
|
our $per_request_config = 1;
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our ($GITWEB_CONFIG, $GITWEB_CONFIG_SYSTEM);
|
|
|
|
sub evaluate_gitweb_config {
|
|
|
|
our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
|
|
|
|
our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
|
|
|
|
# die if there are errors parsing config file
|
|
|
|
if (-e $GITWEB_CONFIG) {
|
|
|
|
do $GITWEB_CONFIG;
|
|
|
|
die $@ if $@;
|
|
|
|
} elsif (-e $GITWEB_CONFIG_SYSTEM) {
|
|
|
|
do $GITWEB_CONFIG_SYSTEM;
|
|
|
|
die $@ if $@;
|
|
|
|
}
|
2008-03-26 18:11:19 +00:00
|
|
|
}
|
2006-08-02 19:23:34 +00:00
|
|
|
|
2010-01-30 22:30:39 +00:00
|
|
|
# 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;
|
|
|
|
}
|
|
|
|
|
2006-08-02 19:23:34 +00:00
|
|
|
# version of the core git binary
|
2010-05-07 12:54:04 +00:00
|
|
|
our $git_version;
|
|
|
|
sub evaluate_git_version {
|
|
|
|
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
|
|
|
|
$number_of_git_cmds++;
|
|
|
|
}
|
2006-08-02 19:23:34 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
sub check_loadavg {
|
|
|
|
if (defined $maxload && get_loadavg() > $maxload) {
|
|
|
|
die_error(503, "The load average on the server is too high");
|
|
|
|
}
|
2010-01-30 22:30:39 +00:00
|
|
|
}
|
|
|
|
|
2006-08-05 10:55:20 +00:00
|
|
|
# ======================================================================
|
2005-08-07 18:21:23 +00:00
|
|
|
# input validation and dispatch
|
2008-10-10 18:42:26 +00:00
|
|
|
|
|
|
|
# input parameters can be collected from a variety of sources (presently, CGI
|
|
|
|
# and PATH_INFO), so we define an %input_params hash that collects them all
|
|
|
|
# together during validation: this allows subsequent uses (e.g. href()) to be
|
|
|
|
# agnostic of the parameter origin
|
|
|
|
|
2008-11-05 22:10:07 +00:00
|
|
|
our %input_params = ();
|
2008-10-10 18:42:26 +00:00
|
|
|
|
|
|
|
# input parameters are stored with the long parameter name as key. This will
|
|
|
|
# also be used in the href subroutine to convert parameters to their CGI
|
|
|
|
# equivalent, and since the href() usage is the most frequent one, we store
|
|
|
|
# the name -> CGI key mapping here, instead of the reverse.
|
|
|
|
#
|
|
|
|
# XXX: Warning: If you touch this, check the search form for updating,
|
|
|
|
# too.
|
|
|
|
|
2008-11-05 22:10:07 +00:00
|
|
|
our @cgi_param_mapping = (
|
2008-10-10 18:42:26 +00:00
|
|
|
project => "p",
|
|
|
|
action => "a",
|
|
|
|
file_name => "f",
|
|
|
|
file_parent => "fp",
|
|
|
|
hash => "h",
|
|
|
|
hash_parent => "hp",
|
|
|
|
hash_base => "hb",
|
|
|
|
hash_parent_base => "hpb",
|
|
|
|
page => "pg",
|
|
|
|
order => "o",
|
|
|
|
searchtext => "s",
|
|
|
|
searchtype => "st",
|
|
|
|
snapshot_format => "sf",
|
|
|
|
extra_options => "opt",
|
|
|
|
search_use_regexp => "sr",
|
gitweb: Create links leading to 'blame_incremental' using JavaScript
The new 'blame_incremental' view requires JavaScript to run. Not all
web browsers implement JavaScript (e.g. text browsers such as Lynx),
and not all users have JavaScript enabled. Therefore instead of
unconditionally linking to 'blame_incremental' view, we use JavaScript
to convert those links to lead to view utilizing JavaScript, by adding
'js=1' to link.
Currently the only action that takes 'js=1' into account is 'blame',
which then acts as if it was called as 'blame_incremental' action.
Possible enhancement would be to do JavaScript redirect by setting
window.location instead of modifying $format and $action in
git_blame_common() subroutine.
The only JavaScript-aware/using view is currently 'blame_incremental'.
While at it move reading JavaScript to git_footer_html() subroutine.
Note that in this view we do not add 'js=1' currently (even though
perhaps we should; note that for consistency we should also add 'js=1'
in links added by JavaScript part of 'blame_incremental').
This idea was originally implemented by Petr Baudis in
http://article.gmane.org/gmane.comp.version-control.git/47614
but it added <script> element with fixBlameLinks() function in page
header, to be added as onload event using 'onload' attribute of HTML
'body' element: <body onload="fixBlameLinks();">. This version adds
script at then end of page (in the page footer), and uses JavaScript
'window.onload=fixLinks();'. Also in Petr version only links marked
with 'blamelink' class were modified, and they were modified by
replacing "a=blame" by "a=blame_incremental"... which doesn't work for
path_info links, and might replace wrong part if there is "a=blame" in
project name, ref name or file name.
Slightly different solution was implemented by Martin Koegler in
http://thread.gmane.org/gmane.comp.version-control.git/47902/focus=47905
Here GitAddLinks() function was in gitweb.js file, not as contents of
<script> element. It was also included in page header (in <head>
element) though, which means waiting for a script to load (and run).
It was smarter in that to "fix" (modify) link, it split URL, modified
value of 'a' parameter, and then recreated modified link. It avoids
trouble with "a=blame" as substring in project name or file name, but
it doesn't work with path_info URL/link in the way it was written.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:19 +00:00
|
|
|
# this must be last entry (for manipulation from JavaScript)
|
|
|
|
javascript => "js"
|
2008-10-10 18:42:26 +00:00
|
|
|
);
|
2008-11-05 22:10:07 +00:00
|
|
|
our %cgi_param_mapping = @cgi_param_mapping;
|
2008-10-10 18:42:26 +00:00
|
|
|
|
|
|
|
# we will also need to know the possible actions, for validation
|
2008-11-05 22:10:07 +00:00
|
|
|
our %actions = (
|
2008-10-10 18:42:26 +00:00
|
|
|
"blame" => \&git_blame,
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
"blame_incremental" => \&git_blame_incremental,
|
|
|
|
"blame_data" => \&git_blame_data,
|
2008-10-10 18:42:26 +00:00
|
|
|
"blobdiff" => \&git_blobdiff,
|
|
|
|
"blobdiff_plain" => \&git_blobdiff_plain,
|
|
|
|
"blob" => \&git_blob,
|
|
|
|
"blob_plain" => \&git_blob_plain,
|
|
|
|
"commitdiff" => \&git_commitdiff,
|
|
|
|
"commitdiff_plain" => \&git_commitdiff_plain,
|
|
|
|
"commit" => \&git_commit,
|
|
|
|
"forks" => \&git_forks,
|
|
|
|
"heads" => \&git_heads,
|
|
|
|
"history" => \&git_history,
|
|
|
|
"log" => \&git_log,
|
2008-12-18 07:13:16 +00:00
|
|
|
"patch" => \&git_patch,
|
2008-12-18 07:13:18 +00:00
|
|
|
"patches" => \&git_patches,
|
2010-11-11 12:26:11 +00:00
|
|
|
"remotes" => \&git_remotes,
|
2008-10-10 18:42:26 +00:00
|
|
|
"rss" => \&git_rss,
|
|
|
|
"atom" => \&git_atom,
|
|
|
|
"search" => \&git_search,
|
|
|
|
"search_help" => \&git_search_help,
|
|
|
|
"shortlog" => \&git_shortlog,
|
|
|
|
"summary" => \&git_summary,
|
|
|
|
"tag" => \&git_tag,
|
|
|
|
"tags" => \&git_tags,
|
|
|
|
"tree" => \&git_tree,
|
|
|
|
"snapshot" => \&git_snapshot,
|
|
|
|
"object" => \&git_object,
|
|
|
|
# those below don't need $project
|
|
|
|
"opml" => \&git_opml,
|
|
|
|
"project_list" => \&git_project_list,
|
|
|
|
"project_index" => \&git_project_index,
|
|
|
|
);
|
|
|
|
|
|
|
|
# finally, we have the hash of allowed extra_options for the commands that
|
|
|
|
# allow them
|
2008-11-05 22:10:07 +00:00
|
|
|
our %allowed_options = (
|
2008-10-10 18:42:26 +00:00
|
|
|
"--no-merges" => [ qw(rss atom log shortlog history) ],
|
|
|
|
);
|
|
|
|
|
|
|
|
# fill %input_params with the CGI parameters. All values except for 'opt'
|
|
|
|
# should be single values, but opt can be an array. We should probably
|
|
|
|
# build an array of parameters that can be multi-valued, but since for the time
|
|
|
|
# being it's only this one, we just single it out
|
2010-05-07 12:54:04 +00:00
|
|
|
sub evaluate_query_params {
|
|
|
|
our $cgi;
|
|
|
|
|
|
|
|
while (my ($name, $symbol) = each %cgi_param_mapping) {
|
|
|
|
if ($symbol eq 'opt') {
|
|
|
|
$input_params{$name} = [ $cgi->param($symbol) ];
|
|
|
|
} else {
|
|
|
|
$input_params{$name} = $cgi->param($symbol);
|
|
|
|
}
|
2008-10-10 18:42:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# now read PATH_INFO and update the parameter list for missing parameters
|
|
|
|
sub evaluate_path_info {
|
|
|
|
return if defined $input_params{'project'};
|
|
|
|
return if !$path_info;
|
|
|
|
$path_info =~ s,^/+,,;
|
|
|
|
return if !$path_info;
|
|
|
|
|
|
|
|
# find which part of PATH_INFO is project
|
|
|
|
my $project = $path_info;
|
|
|
|
$project =~ s,/+$,,;
|
|
|
|
while ($project && !check_head_link("$projectroot/$project")) {
|
|
|
|
$project =~ s,/*[^/]*$,,;
|
|
|
|
}
|
|
|
|
return unless $project;
|
|
|
|
$input_params{'project'} = $project;
|
|
|
|
|
|
|
|
# do not change any parameters if an action is given using the query string
|
|
|
|
return if $input_params{'action'};
|
|
|
|
$path_info =~ s,^\Q$project\E/*,,;
|
|
|
|
|
2008-10-21 19:34:50 +00:00
|
|
|
# next, check if we have an action
|
|
|
|
my $action = $path_info;
|
|
|
|
$action =~ s,/.*$,,;
|
|
|
|
if (exists $actions{$action}) {
|
|
|
|
$path_info =~ s,^$action/*,,;
|
|
|
|
$input_params{'action'} = $action;
|
|
|
|
}
|
|
|
|
|
|
|
|
# list of actions that want hash_base instead of hash, but can have no
|
|
|
|
# pathname (f) parameter
|
|
|
|
my @wants_base = (
|
|
|
|
'tree',
|
|
|
|
'history',
|
|
|
|
);
|
|
|
|
|
2010-10-13 11:33:48 +00:00
|
|
|
# we want to catch, among others
|
2008-10-21 19:34:53 +00:00
|
|
|
# [$hash_parent_base[:$file_parent]..]$hash_parent[:$file_name]
|
|
|
|
my ($parentrefname, $parentpathname, $refname, $pathname) =
|
2010-10-13 11:33:48 +00:00
|
|
|
($path_info =~ /^(?:(.+?)(?::(.+))?\.\.)?([^:]+?)?(?::(.+))?$/);
|
2008-10-21 19:34:53 +00:00
|
|
|
|
|
|
|
# first, analyze the 'current' part
|
2008-10-10 18:42:26 +00:00
|
|
|
if (defined $pathname) {
|
2008-10-21 19:34:50 +00:00
|
|
|
# we got "branch:filename" or "branch:dir/"
|
|
|
|
# we could use git_get_type(branch:pathname), but:
|
|
|
|
# - it needs $git_dir
|
|
|
|
# - it does a git() call
|
|
|
|
# - the convention of terminating directories with a slash
|
|
|
|
# makes it superfluous
|
|
|
|
# - embedding the action in the PATH_INFO would make it even
|
|
|
|
# more superfluous
|
2008-10-10 18:42:26 +00:00
|
|
|
$pathname =~ s,^/+,,;
|
|
|
|
if (!$pathname || substr($pathname, -1) eq "/") {
|
2008-10-21 19:34:50 +00:00
|
|
|
$input_params{'action'} ||= "tree";
|
2008-10-10 18:42:26 +00:00
|
|
|
$pathname =~ s,/$,,;
|
|
|
|
} else {
|
2008-10-21 19:34:53 +00:00
|
|
|
# the default action depends on whether we had parent info
|
|
|
|
# or not
|
|
|
|
if ($parentrefname) {
|
|
|
|
$input_params{'action'} ||= "blobdiff_plain";
|
|
|
|
} else {
|
|
|
|
$input_params{'action'} ||= "blob_plain";
|
|
|
|
}
|
2008-10-10 18:42:26 +00:00
|
|
|
}
|
|
|
|
$input_params{'hash_base'} ||= $refname;
|
|
|
|
$input_params{'file_name'} ||= $pathname;
|
|
|
|
} elsif (defined $refname) {
|
2008-10-21 19:34:50 +00:00
|
|
|
# we got "branch". In this case we have to choose if we have to
|
|
|
|
# set hash or hash_base.
|
|
|
|
#
|
|
|
|
# Most of the actions without a pathname only want hash to be
|
|
|
|
# set, except for the ones specified in @wants_base that want
|
|
|
|
# hash_base instead. It should also be noted that hand-crafted
|
|
|
|
# links having 'history' as an action and no pathname or hash
|
|
|
|
# set will fail, but that happens regardless of PATH_INFO.
|
2010-10-13 11:35:20 +00:00
|
|
|
if (defined $parentrefname) {
|
|
|
|
# if there is parent let the default be 'shortlog' action
|
|
|
|
# (for http://git.example.com/repo.git/A..B links); if there
|
|
|
|
# is no parent, dispatch will detect type of object and set
|
|
|
|
# action appropriately if required (if action is not set)
|
|
|
|
$input_params{'action'} ||= "shortlog";
|
|
|
|
}
|
|
|
|
if ($input_params{'action'} &&
|
|
|
|
grep { $_ eq $input_params{'action'} } @wants_base) {
|
2008-10-21 19:34:50 +00:00
|
|
|
$input_params{'hash_base'} ||= $refname;
|
|
|
|
} else {
|
|
|
|
$input_params{'hash'} ||= $refname;
|
|
|
|
}
|
2008-10-10 18:42:26 +00:00
|
|
|
}
|
2008-10-21 19:34:53 +00:00
|
|
|
|
|
|
|
# next, handle the 'parent' part, if present
|
|
|
|
if (defined $parentrefname) {
|
|
|
|
# a missing pathspec defaults to the 'current' filename, allowing e.g.
|
|
|
|
# someproject/blobdiff/oldrev..newrev:/filename
|
|
|
|
if ($parentpathname) {
|
|
|
|
$parentpathname =~ s,^/+,,;
|
|
|
|
$parentpathname =~ s,/$,,;
|
|
|
|
$input_params{'file_parent'} ||= $parentpathname;
|
|
|
|
} else {
|
|
|
|
$input_params{'file_parent'} ||= $input_params{'file_name'};
|
|
|
|
}
|
|
|
|
# we assume that hash_parent_base is wanted if a path was specified,
|
|
|
|
# or if the action wants hash_base instead of hash
|
|
|
|
if (defined $input_params{'file_parent'} ||
|
|
|
|
grep { $_ eq $input_params{'action'} } @wants_base) {
|
|
|
|
$input_params{'hash_parent_base'} ||= $parentrefname;
|
|
|
|
} else {
|
|
|
|
$input_params{'hash_parent'} ||= $parentrefname;
|
|
|
|
}
|
|
|
|
}
|
2008-11-02 09:21:38 +00:00
|
|
|
|
|
|
|
# for the snapshot action, we allow URLs in the form
|
|
|
|
# $project/snapshot/$hash.ext
|
|
|
|
# where .ext determines the snapshot and gets removed from the
|
|
|
|
# passed $refname to provide the $hash.
|
|
|
|
#
|
|
|
|
# To be able to tell that $refname includes the format extension, we
|
|
|
|
# require the following two conditions to be satisfied:
|
|
|
|
# - the hash input parameter MUST have been set from the $refname part
|
|
|
|
# of the URL (i.e. they must be equal)
|
|
|
|
# - the snapshot format MUST NOT have been defined already (e.g. from
|
|
|
|
# CGI parameter sf)
|
|
|
|
# It's also useless to try any matching unless $refname has a dot,
|
|
|
|
# so we check for that too
|
|
|
|
if (defined $input_params{'action'} &&
|
|
|
|
$input_params{'action'} eq 'snapshot' &&
|
|
|
|
defined $refname && index($refname, '.') != -1 &&
|
|
|
|
$refname eq $input_params{'hash'} &&
|
|
|
|
!defined $input_params{'snapshot_format'}) {
|
|
|
|
# We loop over the known snapshot formats, checking for
|
|
|
|
# extensions. Allowed extensions are both the defined suffix
|
|
|
|
# (which includes the initial dot already) and the snapshot
|
|
|
|
# format key itself, with a prepended dot
|
2009-03-31 16:16:36 +00:00
|
|
|
while (my ($fmt, $opt) = each %known_snapshot_formats) {
|
2008-11-02 09:21:38 +00:00
|
|
|
my $hash = $refname;
|
2009-05-11 17:42:47 +00:00
|
|
|
unless ($hash =~ s/(\Q$opt->{'suffix'}\E|\Q.$fmt\E)$//) {
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
my $sfx = $1;
|
2008-11-02 09:21:38 +00:00
|
|
|
# a valid suffix was found, so set the snapshot format
|
|
|
|
# and reset the hash parameter
|
|
|
|
$input_params{'snapshot_format'} = $fmt;
|
|
|
|
$input_params{'hash'} = $hash;
|
|
|
|
# we also set the format suffix to the one requested
|
|
|
|
# in the URL: this way a request for e.g. .tgz returns
|
|
|
|
# a .tgz instead of a .tar.gz
|
|
|
|
$known_snapshot_formats{$fmt}{'suffix'} = $sfx;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
2008-10-10 18:42:26 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our ($action, $project, $file_name, $file_parent, $hash, $hash_parent, $hash_base,
|
|
|
|
$hash_parent_base, @extra_options, $page, $searchtype, $search_use_regexp,
|
|
|
|
$searchtext, $search_regexp);
|
|
|
|
sub evaluate_and_validate_params {
|
|
|
|
our $action = $input_params{'action'};
|
|
|
|
if (defined $action) {
|
|
|
|
if (!validate_action($action)) {
|
|
|
|
die_error(400, "Invalid action parameter");
|
|
|
|
}
|
2005-08-07 18:21:04 +00:00
|
|
|
}
|
2005-08-07 17:59:24 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
# parameters which are pathnames
|
|
|
|
our $project = $input_params{'project'};
|
|
|
|
if (defined $project) {
|
|
|
|
if (!validate_project($project)) {
|
|
|
|
undef $project;
|
|
|
|
die_error(404, "No such project");
|
|
|
|
}
|
2005-08-07 18:17:42 +00:00
|
|
|
}
|
2005-08-07 18:19:56 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $file_name = $input_params{'file_name'};
|
|
|
|
if (defined $file_name) {
|
|
|
|
if (!validate_pathname($file_name)) {
|
|
|
|
die_error(400, "Invalid file parameter");
|
|
|
|
}
|
2006-09-25 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $file_parent = $input_params{'file_parent'};
|
|
|
|
if (defined $file_parent) {
|
|
|
|
if (!validate_pathname($file_parent)) {
|
|
|
|
die_error(400, "Invalid file parent parameter");
|
|
|
|
}
|
2006-09-25 23:57:02 +00:00
|
|
|
}
|
2006-08-16 22:28:38 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
# parameters which are refnames
|
|
|
|
our $hash = $input_params{'hash'};
|
|
|
|
if (defined $hash) {
|
|
|
|
if (!validate_refname($hash)) {
|
|
|
|
die_error(400, "Invalid hash parameter");
|
|
|
|
}
|
2005-08-07 18:27:38 +00:00
|
|
|
}
|
2005-08-07 18:19:56 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $hash_parent = $input_params{'hash_parent'};
|
|
|
|
if (defined $hash_parent) {
|
|
|
|
if (!validate_refname($hash_parent)) {
|
|
|
|
die_error(400, "Invalid hash parent parameter");
|
|
|
|
}
|
2005-09-03 12:50:33 +00:00
|
|
|
}
|
2005-08-07 18:21:23 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $hash_base = $input_params{'hash_base'};
|
|
|
|
if (defined $hash_base) {
|
|
|
|
if (!validate_refname($hash_base)) {
|
|
|
|
die_error(400, "Invalid hash base parameter");
|
|
|
|
}
|
2005-09-03 12:50:33 +00:00
|
|
|
}
|
2005-08-07 18:19:56 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our @extra_options = @{$input_params{'extra_options'}};
|
|
|
|
# @extra_options is always defined, since it can only be (currently) set from
|
|
|
|
# CGI, and $cgi->param() returns the empty array in array context if the param
|
|
|
|
# is not set
|
|
|
|
foreach my $opt (@extra_options) {
|
|
|
|
if (not exists $allowed_options{$opt}) {
|
|
|
|
die_error(400, "Invalid option parameter");
|
|
|
|
}
|
|
|
|
if (not grep(/^$action$/, @{$allowed_options{$opt}})) {
|
|
|
|
die_error(400, "Invalid option parameter for this action");
|
|
|
|
}
|
2007-07-12 18:39:27 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $hash_parent_base = $input_params{'hash_parent_base'};
|
|
|
|
if (defined $hash_parent_base) {
|
|
|
|
if (!validate_refname($hash_parent_base)) {
|
|
|
|
die_error(400, "Invalid hash parent base parameter");
|
|
|
|
}
|
2006-08-24 21:53:54 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
# other parameters
|
|
|
|
our $page = $input_params{'page'};
|
|
|
|
if (defined $page) {
|
|
|
|
if ($page =~ m/[^0-9]/) {
|
|
|
|
die_error(400, "Invalid page parameter");
|
|
|
|
}
|
2005-08-07 18:21:04 +00:00
|
|
|
}
|
2005-08-07 17:57:58 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $searchtype = $input_params{'searchtype'};
|
|
|
|
if (defined $searchtype) {
|
|
|
|
if ($searchtype =~ m/[^a-z]/) {
|
|
|
|
die_error(400, "Invalid searchtype parameter");
|
|
|
|
}
|
2007-05-17 02:31:12 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $search_use_regexp = $input_params{'search_use_regexp'};
|
2008-02-26 12:22:08 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our $searchtext = $input_params{'searchtext'};
|
|
|
|
our $search_regexp;
|
|
|
|
if (defined $searchtext) {
|
|
|
|
if (length($searchtext) < 2) {
|
|
|
|
die_error(403, "At least two characters are required for search parameter");
|
|
|
|
}
|
|
|
|
$search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
|
2006-12-23 03:35:15 +00:00
|
|
|
}
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
|
|
|
|
2006-09-17 13:29:48 +00:00
|
|
|
# path to the current git repository
|
|
|
|
our $git_dir;
|
2010-05-07 12:54:04 +00:00
|
|
|
sub evaluate_git_dir {
|
|
|
|
our $git_dir = "$projectroot/$project" if $project;
|
2009-06-29 22:00:51 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
our (@snapshot_fmts, $git_avatar);
|
|
|
|
sub configure_gitweb_features {
|
|
|
|
# list of supported snapshot formats
|
|
|
|
our @snapshot_fmts = gitweb_get_feature('snapshot');
|
|
|
|
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
|
|
|
|
|
|
|
|
# check that the avatar feature is set to a known provider name,
|
|
|
|
# and for each provider check if the dependencies are satisfied.
|
|
|
|
# if the provider name is invalid or the dependencies are not met,
|
|
|
|
# reset $git_avatar to the empty string.
|
|
|
|
our ($git_avatar) = gitweb_get_feature('avatar');
|
|
|
|
if ($git_avatar eq 'gravatar') {
|
|
|
|
$git_avatar = '' unless (eval { require Digest::MD5; 1; });
|
|
|
|
} elsif ($git_avatar eq 'picon') {
|
|
|
|
# no dependencies
|
gitweb: choose appropriate view for file type if a= parameter missing
gitweb URLs use the a= parameter for the view to use on the given path, such
as "blob" or "tree". Currently, if a gitweb URL omits the a= parameter,
gitweb just shows the top-level repository summary, regardless of the path
given. gitweb could instead choose an appropriate view based on the file
type: blob for blobs (files), tree for trees (directories), and summary if
no path given (the URL included no f= parameter, or an empty f= parameter).
Apart from making gitweb more robust and supporting URL editing more easily,
this change would aid the creation of shortcuts to git repositories using
simple substitution, such as:
http://example.org/git/?p=path/to/repo.git;hb=HEAD;f=%s
With this patch, if given the hash through the h= parameter, or the hash
base (hb=) and a filename (f=), gitweb uses cat-file -t to automatically set
the a= parameter.
This feature was requested by Josh Triplett through
http://bugs.debian.org/410465
Signed-off-by: Gerrit Pape <pape@smarden.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-10 07:32:07 +00:00
|
|
|
} else {
|
2010-05-07 12:54:04 +00:00
|
|
|
$git_avatar = '';
|
gitweb: choose appropriate view for file type if a= parameter missing
gitweb URLs use the a= parameter for the view to use on the given path, such
as "blob" or "tree". Currently, if a gitweb URL omits the a= parameter,
gitweb just shows the top-level repository summary, regardless of the path
given. gitweb could instead choose an appropriate view based on the file
type: blob for blobs (files), tree for trees (directories), and summary if
no path given (the URL included no f= parameter, or an empty f= parameter).
Apart from making gitweb more robust and supporting URL editing more easily,
this change would aid the creation of shortcuts to git repositories using
simple substitution, such as:
http://example.org/git/?p=path/to/repo.git;hb=HEAD;f=%s
With this patch, if given the hash through the h= parameter, or the hash
base (hb=) and a filename (f=), gitweb uses cat-file -t to automatically set
the a= parameter.
This feature was requested by Josh Triplett through
http://bugs.debian.org/410465
Signed-off-by: Gerrit Pape <pape@smarden.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-10 07:32:07 +00:00
|
|
|
}
|
2009-06-29 22:00:51 +00:00
|
|
|
}
|
|
|
|
|
2010-04-24 14:00:04 +00:00
|
|
|
# custom error handler: 'die <message>' is Internal Server Error
|
|
|
|
sub handle_errors_html {
|
|
|
|
my $msg = shift; # it is already HTML escaped
|
|
|
|
|
|
|
|
# to avoid infinite loop where error occurs in die_error,
|
|
|
|
# change handler to default handler, disabling handle_errors_html
|
|
|
|
set_message("Error occured when inside die_error:\n$msg");
|
|
|
|
|
|
|
|
# you cannot jump out of die_error when called as error handler;
|
|
|
|
# the subroutine set via CGI::Carp::set_message is called _after_
|
|
|
|
# HTTP headers are already written, so it cannot write them itself
|
|
|
|
die_error(undef, undef, $msg, -error_handler => 1, -no_http_header => 1);
|
|
|
|
}
|
|
|
|
set_message(\&handle_errors_html);
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# dispatch
|
2010-05-07 12:54:04 +00:00
|
|
|
sub dispatch {
|
|
|
|
if (!defined $action) {
|
|
|
|
if (defined $hash) {
|
|
|
|
$action = git_get_type($hash);
|
|
|
|
} elsif (defined $hash_base && defined $file_name) {
|
|
|
|
$action = git_get_type("$hash_base:$file_name");
|
|
|
|
} elsif (defined $project) {
|
|
|
|
$action = 'summary';
|
|
|
|
} else {
|
|
|
|
$action = 'project_list';
|
|
|
|
}
|
gitweb: choose appropriate view for file type if a= parameter missing
gitweb URLs use the a= parameter for the view to use on the given path, such
as "blob" or "tree". Currently, if a gitweb URL omits the a= parameter,
gitweb just shows the top-level repository summary, regardless of the path
given. gitweb could instead choose an appropriate view based on the file
type: blob for blobs (files), tree for trees (directories), and summary if
no path given (the URL included no f= parameter, or an empty f= parameter).
Apart from making gitweb more robust and supporting URL editing more easily,
this change would aid the creation of shortcuts to git repositories using
simple substitution, such as:
http://example.org/git/?p=path/to/repo.git;hb=HEAD;f=%s
With this patch, if given the hash through the h= parameter, or the hash
base (hb=) and a filename (f=), gitweb uses cat-file -t to automatically set
the a= parameter.
This feature was requested by Josh Triplett through
http://bugs.debian.org/410465
Signed-off-by: Gerrit Pape <pape@smarden.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-10 07:32:07 +00:00
|
|
|
}
|
2010-05-07 12:54:04 +00:00
|
|
|
if (!defined($actions{$action})) {
|
|
|
|
die_error(400, "Unknown action");
|
|
|
|
}
|
|
|
|
if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
|
|
|
|
!$project) {
|
|
|
|
die_error(400, "Project needed");
|
|
|
|
}
|
|
|
|
$actions{$action}->();
|
2006-08-22 14:59:20 +00:00
|
|
|
}
|
2010-05-07 12:54:04 +00:00
|
|
|
|
2010-07-05 18:52:43 +00:00
|
|
|
sub reset_timer {
|
2010-11-09 18:27:54 +00:00
|
|
|
our $t0 = [ gettimeofday() ]
|
2010-05-07 12:54:04 +00:00
|
|
|
if defined $t0;
|
2010-07-05 18:52:43 +00:00
|
|
|
our $number_of_git_cmds = 0;
|
|
|
|
}
|
|
|
|
|
gitweb: selectable configurations that change with each request
Allow selecting whether configuration file should be (re)parsed on each
request (the default, for backward compatibility with configurations that
change per session, see commit 7f425db (gitweb: allow configurations that
change with each request, 2010-07-30)), or whether should it be parsed only
once (for performance speedup for persistent environments, though currently
only FastCGI is able to make use of it, when flexibility is not important).
You can also have configuration file parsed only once, but have parts of
configuration (re)evaluated once per each request.
This is done by introducing $per_request_config variable: if set to code
reference, this code would be run once per request, while config file would
be parsed only once. For example gitolite's contrib/gitweb/gitweb.conf
fragment mentioned in 7f425db could be rewritten as
our $per_request_config = sub {
$ENV{GL_USER} = ($cgi && $cgi->remote_user) || "gitweb";
};
to make use of this feature.
If $per_request_config is not a code reference, it is taken to be boolean
variable, to choose between running config file for each request
(flexibility), and running config file only once (performance in
persistent environments).
The default value for $per_request_config is 1 (true), which means that
old configuration that require to change per session (like gitolite's)
will keep working.
While at it, make it so evaluate_git_version() is run only once.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-11-25 18:43:59 +00:00
|
|
|
our $first_request = 1;
|
2010-07-05 18:52:43 +00:00
|
|
|
sub run_request {
|
|
|
|
reset_timer();
|
2010-05-07 12:54:04 +00:00
|
|
|
|
|
|
|
evaluate_uri();
|
gitweb: selectable configurations that change with each request
Allow selecting whether configuration file should be (re)parsed on each
request (the default, for backward compatibility with configurations that
change per session, see commit 7f425db (gitweb: allow configurations that
change with each request, 2010-07-30)), or whether should it be parsed only
once (for performance speedup for persistent environments, though currently
only FastCGI is able to make use of it, when flexibility is not important).
You can also have configuration file parsed only once, but have parts of
configuration (re)evaluated once per each request.
This is done by introducing $per_request_config variable: if set to code
reference, this code would be run once per request, while config file would
be parsed only once. For example gitolite's contrib/gitweb/gitweb.conf
fragment mentioned in 7f425db could be rewritten as
our $per_request_config = sub {
$ENV{GL_USER} = ($cgi && $cgi->remote_user) || "gitweb";
};
to make use of this feature.
If $per_request_config is not a code reference, it is taken to be boolean
variable, to choose between running config file for each request
(flexibility), and running config file only once (performance in
persistent environments).
The default value for $per_request_config is 1 (true), which means that
old configuration that require to change per session (like gitolite's)
will keep working.
While at it, make it so evaluate_git_version() is run only once.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-11-25 18:43:59 +00:00
|
|
|
if ($first_request) {
|
|
|
|
evaluate_gitweb_config();
|
|
|
|
evaluate_git_version();
|
|
|
|
}
|
|
|
|
if ($per_request_config) {
|
|
|
|
if (ref($per_request_config) eq 'CODE') {
|
|
|
|
$per_request_config->();
|
|
|
|
} elsif (!$first_request) {
|
|
|
|
evaluate_gitweb_config();
|
|
|
|
}
|
|
|
|
}
|
2010-05-07 12:54:04 +00:00
|
|
|
check_loadavg();
|
|
|
|
|
2010-07-31 03:01:59 +00:00
|
|
|
# $projectroot and $projects_list might be set in gitweb config file
|
|
|
|
$projects_list ||= $projectroot;
|
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
evaluate_query_params();
|
|
|
|
evaluate_path_info();
|
|
|
|
evaluate_and_validate_params();
|
|
|
|
evaluate_git_dir();
|
|
|
|
|
|
|
|
configure_gitweb_features();
|
|
|
|
|
|
|
|
dispatch();
|
2005-08-07 18:21:23 +00:00
|
|
|
}
|
2010-05-07 12:54:05 +00:00
|
|
|
|
|
|
|
our $is_last_request = sub { 1 };
|
|
|
|
our ($pre_dispatch_hook, $post_dispatch_hook, $pre_listen_hook);
|
|
|
|
our $CGI = 'CGI';
|
|
|
|
our $cgi;
|
2010-06-05 21:11:18 +00:00
|
|
|
sub configure_as_fcgi {
|
|
|
|
require CGI::Fast;
|
|
|
|
our $CGI = 'CGI::Fast';
|
|
|
|
|
|
|
|
my $request_number = 0;
|
|
|
|
# let each child service 100 requests
|
|
|
|
our $is_last_request = sub { ++$request_number > 100 };
|
2006-09-19 19:53:22 +00:00
|
|
|
}
|
2010-05-07 12:54:05 +00:00
|
|
|
sub evaluate_argv {
|
2010-06-05 21:11:18 +00:00
|
|
|
my $script_name = $ENV{'SCRIPT_NAME'} || $ENV{'SCRIPT_FILENAME'} || __FILE__;
|
|
|
|
configure_as_fcgi()
|
|
|
|
if $script_name =~ /\.fcgi$/;
|
|
|
|
|
2010-05-07 12:54:05 +00:00
|
|
|
return unless (@ARGV);
|
|
|
|
|
|
|
|
require Getopt::Long;
|
|
|
|
Getopt::Long::GetOptions(
|
2010-06-05 21:11:18 +00:00
|
|
|
'fastcgi|fcgi|f' => \&configure_as_fcgi,
|
2010-05-07 12:54:05 +00:00
|
|
|
'nproc|n=i' => sub {
|
|
|
|
my ($arg, $val) = @_;
|
|
|
|
return unless eval { require FCGI::ProcManager; 1; };
|
|
|
|
my $proc_manager = FCGI::ProcManager->new({
|
|
|
|
n_processes => $val,
|
|
|
|
});
|
|
|
|
our $pre_listen_hook = sub { $proc_manager->pm_manage() };
|
|
|
|
our $pre_dispatch_hook = sub { $proc_manager->pm_pre_dispatch() };
|
|
|
|
our $post_dispatch_hook = sub { $proc_manager->pm_post_dispatch() };
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub run {
|
|
|
|
evaluate_argv();
|
2010-07-05 18:52:43 +00:00
|
|
|
|
gitweb: selectable configurations that change with each request
Allow selecting whether configuration file should be (re)parsed on each
request (the default, for backward compatibility with configurations that
change per session, see commit 7f425db (gitweb: allow configurations that
change with each request, 2010-07-30)), or whether should it be parsed only
once (for performance speedup for persistent environments, though currently
only FastCGI is able to make use of it, when flexibility is not important).
You can also have configuration file parsed only once, but have parts of
configuration (re)evaluated once per each request.
This is done by introducing $per_request_config variable: if set to code
reference, this code would be run once per request, while config file would
be parsed only once. For example gitolite's contrib/gitweb/gitweb.conf
fragment mentioned in 7f425db could be rewritten as
our $per_request_config = sub {
$ENV{GL_USER} = ($cgi && $cgi->remote_user) || "gitweb";
};
to make use of this feature.
If $per_request_config is not a code reference, it is taken to be boolean
variable, to choose between running config file for each request
(flexibility), and running config file only once (performance in
persistent environments).
The default value for $per_request_config is 1 (true), which means that
old configuration that require to change per session (like gitolite's)
will keep working.
While at it, make it so evaluate_git_version() is run only once.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-11-25 18:43:59 +00:00
|
|
|
$first_request = 1;
|
2010-05-07 12:54:05 +00:00
|
|
|
$pre_listen_hook->()
|
|
|
|
if $pre_listen_hook;
|
|
|
|
|
|
|
|
REQUEST:
|
|
|
|
while ($cgi = $CGI->new()) {
|
|
|
|
$pre_dispatch_hook->()
|
|
|
|
if $pre_dispatch_hook;
|
|
|
|
|
|
|
|
run_request();
|
|
|
|
|
2010-08-02 20:21:47 +00:00
|
|
|
$post_dispatch_hook->()
|
2010-05-07 12:54:05 +00:00
|
|
|
if $post_dispatch_hook;
|
gitweb: selectable configurations that change with each request
Allow selecting whether configuration file should be (re)parsed on each
request (the default, for backward compatibility with configurations that
change per session, see commit 7f425db (gitweb: allow configurations that
change with each request, 2010-07-30)), or whether should it be parsed only
once (for performance speedup for persistent environments, though currently
only FastCGI is able to make use of it, when flexibility is not important).
You can also have configuration file parsed only once, but have parts of
configuration (re)evaluated once per each request.
This is done by introducing $per_request_config variable: if set to code
reference, this code would be run once per request, while config file would
be parsed only once. For example gitolite's contrib/gitweb/gitweb.conf
fragment mentioned in 7f425db could be rewritten as
our $per_request_config = sub {
$ENV{GL_USER} = ($cgi && $cgi->remote_user) || "gitweb";
};
to make use of this feature.
If $per_request_config is not a code reference, it is taken to be boolean
variable, to choose between running config file for each request
(flexibility), and running config file only once (performance in
persistent environments).
The default value for $per_request_config is 1 (true), which means that
old configuration that require to change per session (like gitolite's)
will keep working.
While at it, make it so evaluate_git_version() is run only once.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-11-25 18:43:59 +00:00
|
|
|
$first_request = 0;
|
2010-05-07 12:54:05 +00:00
|
|
|
|
|
|
|
last REQUEST if ($is_last_request->());
|
|
|
|
}
|
2010-05-07 12:54:04 +00:00
|
|
|
|
|
|
|
DONE_GITWEB:
|
|
|
|
1;
|
2006-09-19 19:53:22 +00:00
|
|
|
}
|
2010-05-07 12:54:05 +00:00
|
|
|
|
2010-05-07 12:54:04 +00:00
|
|
|
run();
|
2005-08-07 18:21:23 +00:00
|
|
|
|
2010-06-13 10:09:32 +00:00
|
|
|
if (defined caller) {
|
|
|
|
# wrapped in a subroutine processing requests,
|
|
|
|
# e.g. mod_perl with ModPerl::Registry, or PSGI with Plack::App::WrapCGI
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
# pure CGI script, serving single request
|
|
|
|
exit;
|
|
|
|
}
|
2005-08-07 18:21:23 +00:00
|
|
|
|
2006-08-15 22:23:50 +00:00
|
|
|
## ======================================================================
|
|
|
|
## action links
|
|
|
|
|
2010-04-24 13:53:19 +00:00
|
|
|
# possible values of extra options
|
|
|
|
# -full => 0|1 - use absolute/full URL ($my_uri/$my_url as base)
|
|
|
|
# -replay => 1 - start from a current view (replay with modifications)
|
|
|
|
# -path_info => 0|1 - don't use/use path_info URL (if possible)
|
2009-05-07 17:11:29 +00:00
|
|
|
sub href {
|
2006-08-22 17:05:25 +00:00
|
|
|
my %params = @_;
|
2006-11-19 14:05:21 +00:00
|
|
|
# default is to use -absolute url() i.e. $my_uri
|
|
|
|
my $href = $params{-full} ? $my_url : $my_uri;
|
2006-08-22 17:05:25 +00:00
|
|
|
|
2008-02-14 08:22:30 +00:00
|
|
|
$params{'project'} = $project unless exists $params{'project'};
|
|
|
|
|
2007-11-01 12:06:27 +00:00
|
|
|
if ($params{-replay}) {
|
2008-10-10 18:42:26 +00:00
|
|
|
while (my ($name, $symbol) = each %cgi_param_mapping) {
|
2007-11-01 12:06:27 +00:00
|
|
|
if (!exists $params{$name}) {
|
2008-10-10 18:42:26 +00:00
|
|
|
$params{$name} = $input_params{$name};
|
2007-11-01 12:06:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
my $use_pathinfo = gitweb_check_feature('pathinfo');
|
2010-04-24 13:53:19 +00:00
|
|
|
if (defined $params{'project'} &&
|
|
|
|
(exists $params{-path_info} ? $params{-path_info} : $use_pathinfo)) {
|
2008-10-21 19:34:51 +00:00
|
|
|
# try to put as many parameters as possible in PATH_INFO:
|
|
|
|
# - project name
|
|
|
|
# - action
|
2008-10-21 19:34:54 +00:00
|
|
|
# - hash_parent or hash_parent_base:/file_parent
|
2008-10-21 19:34:52 +00:00
|
|
|
# - hash or hash_base:/filename
|
2008-11-02 09:21:39 +00:00
|
|
|
# - the snapshot_format as an appropriate suffix
|
2008-10-21 19:34:51 +00:00
|
|
|
|
|
|
|
# When the script is the root DirectoryIndex for the domain,
|
|
|
|
# $href here would be something like http://gitweb.example.com/
|
|
|
|
# Thus, we strip any trailing / from $href, to spare us double
|
|
|
|
# slashes in the final URL
|
|
|
|
$href =~ s,/$,,;
|
|
|
|
|
|
|
|
# Then add the project name, if present
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= "/".esc_path_info($params{'project'});
|
2006-10-01 21:57:48 +00:00
|
|
|
delete $params{'project'};
|
|
|
|
|
2008-11-02 09:21:39 +00:00
|
|
|
# since we destructively absorb parameters, we keep this
|
|
|
|
# boolean that remembers if we're handling a snapshot
|
|
|
|
my $is_snapshot = $params{'action'} eq 'snapshot';
|
|
|
|
|
2008-10-21 19:34:51 +00:00
|
|
|
# Summary just uses the project path URL, any other action is
|
|
|
|
# added to the URL
|
|
|
|
if (defined $params{'action'}) {
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= "/".esc_path_info($params{'action'})
|
|
|
|
unless $params{'action'} eq 'summary';
|
2006-10-01 21:57:48 +00:00
|
|
|
delete $params{'action'};
|
|
|
|
}
|
2008-10-21 19:34:51 +00:00
|
|
|
|
2008-10-21 19:34:54 +00:00
|
|
|
# Next, we put hash_parent_base:/file_parent..hash_base:/file_name,
|
|
|
|
# stripping nonexistent or useless pieces
|
|
|
|
$href .= "/" if ($params{'hash_base'} || $params{'hash_parent_base'}
|
|
|
|
|| $params{'hash_parent'} || $params{'hash'});
|
2008-10-21 19:34:51 +00:00
|
|
|
if (defined $params{'hash_base'}) {
|
2008-10-21 19:34:54 +00:00
|
|
|
if (defined $params{'hash_parent_base'}) {
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= esc_path_info($params{'hash_parent_base'});
|
2008-10-21 19:34:54 +00:00
|
|
|
# skip the file_parent if it's the same as the file_name
|
2009-07-31 06:48:49 +00:00
|
|
|
if (defined $params{'file_parent'}) {
|
|
|
|
if (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) {
|
|
|
|
delete $params{'file_parent'};
|
|
|
|
} elsif ($params{'file_parent'} !~ /\.\./) {
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= ":/".esc_path_info($params{'file_parent'});
|
2009-07-31 06:48:49 +00:00
|
|
|
delete $params{'file_parent'};
|
|
|
|
}
|
2008-10-21 19:34:54 +00:00
|
|
|
}
|
|
|
|
$href .= "..";
|
|
|
|
delete $params{'hash_parent'};
|
|
|
|
delete $params{'hash_parent_base'};
|
|
|
|
} elsif (defined $params{'hash_parent'}) {
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= esc_path_info($params{'hash_parent'}). "..";
|
2008-10-21 19:34:54 +00:00
|
|
|
delete $params{'hash_parent'};
|
|
|
|
}
|
|
|
|
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= esc_path_info($params{'hash_base'});
|
2008-10-21 19:34:54 +00:00
|
|
|
if (defined $params{'file_name'} && $params{'file_name'} !~ /\.\./) {
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= ":/".esc_path_info($params{'file_name'});
|
2008-10-21 19:34:51 +00:00
|
|
|
delete $params{'file_name'};
|
|
|
|
}
|
|
|
|
delete $params{'hash'};
|
|
|
|
delete $params{'hash_base'};
|
|
|
|
} elsif (defined $params{'hash'}) {
|
2010-12-14 15:54:31 +00:00
|
|
|
$href .= esc_path_info($params{'hash'});
|
2008-10-21 19:34:51 +00:00
|
|
|
delete $params{'hash'};
|
|
|
|
}
|
2008-11-02 09:21:39 +00:00
|
|
|
|
|
|
|
# If the action was a snapshot, we can absorb the
|
|
|
|
# snapshot_format parameter too
|
|
|
|
if ($is_snapshot) {
|
|
|
|
my $fmt = $params{'snapshot_format'};
|
|
|
|
# snapshot_format should always be defined when href()
|
|
|
|
# is called, but just in case some code forgets, we
|
|
|
|
# fall back to the default
|
|
|
|
$fmt ||= $snapshot_fmts[0];
|
|
|
|
$href .= $known_snapshot_formats{$fmt}{'suffix'};
|
|
|
|
delete $params{'snapshot_format'};
|
|
|
|
}
|
2006-10-01 21:57:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# now encode the parameters explicitly
|
2006-08-22 17:05:25 +00:00
|
|
|
my @result = ();
|
2008-10-10 18:42:26 +00:00
|
|
|
for (my $i = 0; $i < @cgi_param_mapping; $i += 2) {
|
|
|
|
my ($name, $symbol) = ($cgi_param_mapping[$i], $cgi_param_mapping[$i+1]);
|
2006-08-22 17:05:25 +00:00
|
|
|
if (defined $params{$name}) {
|
2007-07-28 23:04:09 +00:00
|
|
|
if (ref($params{$name}) eq "ARRAY") {
|
|
|
|
foreach my $par (@{$params{$name}}) {
|
|
|
|
push @result, $symbol . "=" . esc_param($par);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
push @result, $symbol . "=" . esc_param($params{$name});
|
|
|
|
}
|
2006-08-22 17:05:25 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-01 21:57:48 +00:00
|
|
|
$href .= "?" . join(';', @result) if scalar @result;
|
|
|
|
|
2010-12-14 15:54:31 +00:00
|
|
|
# final transformation: trailing spaces must be escaped (URI-encoded)
|
|
|
|
$href =~ s/(\s+)$/CGI::escape($1)/e;
|
|
|
|
|
2006-10-01 21:57:48 +00:00
|
|
|
return $href;
|
2006-08-15 22:23:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ======================================================================
|
|
|
|
## validation, quoting/unquoting and escaping
|
|
|
|
|
2008-10-10 18:42:26 +00:00
|
|
|
sub validate_action {
|
|
|
|
my $input = shift || return undef;
|
|
|
|
return undef unless exists $actions{$input};
|
|
|
|
return $input;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub validate_project {
|
|
|
|
my $input = shift || return undef;
|
|
|
|
if (!validate_pathname($input) ||
|
|
|
|
!(-d "$projectroot/$input") ||
|
2008-11-05 22:15:56 +00:00
|
|
|
!check_export_ok("$projectroot/$input") ||
|
2008-10-10 18:42:26 +00:00
|
|
|
($strict_export && !project_in_list($input))) {
|
|
|
|
return undef;
|
|
|
|
} else {
|
|
|
|
return $input;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-25 23:57:02 +00:00
|
|
|
sub validate_pathname {
|
|
|
|
my $input = shift || return undef;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2006-09-25 23:57:02 +00:00
|
|
|
# no '.' or '..' as elements of path, i.e. no '.' nor '..'
|
|
|
|
# at the beginning, at the end, and between slashes.
|
|
|
|
# also this catches doubled slashes
|
|
|
|
if ($input =~ m!(^|/)(|\.|\.\.)(/|$)!) {
|
|
|
|
return undef;
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
2006-09-25 23:57:02 +00:00
|
|
|
# no null characters
|
|
|
|
if ($input =~ m!\0!) {
|
2006-07-31 19:22:15 +00:00
|
|
|
return undef;
|
|
|
|
}
|
2006-09-25 23:57:02 +00:00
|
|
|
return $input;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub validate_refname {
|
|
|
|
my $input = shift || return undef;
|
|
|
|
|
|
|
|
# textual hashes are O.K.
|
|
|
|
if ($input =~ m/^[0-9a-fA-F]{40}$/) {
|
|
|
|
return $input;
|
|
|
|
}
|
|
|
|
# it must be correct pathname
|
|
|
|
$input = validate_pathname($input)
|
|
|
|
or return undef;
|
|
|
|
# restrictions on ref name according to git-check-ref-format
|
|
|
|
if ($input =~ m!(/\.|\.\.|[\000-\040\177 ~^:?*\[]|/$)!) {
|
2006-07-31 19:22:15 +00:00
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
return $input;
|
|
|
|
}
|
|
|
|
|
2007-06-03 15:42:44 +00:00
|
|
|
# decode sequences of octets in utf8 into Perl's internal form,
|
|
|
|
# which is utf-8 with utf8 flag set if needed. gitweb writes out
|
|
|
|
# in utf-8 thanks to "binmode STDOUT, ':utf8'" at beginning
|
|
|
|
sub to_utf8 {
|
|
|
|
my $str = shift;
|
2010-02-07 20:52:25 +00:00
|
|
|
return undef unless defined $str;
|
2007-12-04 08:55:41 +00:00
|
|
|
if (utf8::valid($str)) {
|
|
|
|
utf8::decode($str);
|
|
|
|
return $str;
|
2007-06-03 15:42:44 +00:00
|
|
|
} else {
|
|
|
|
return decode($fallback_encoding, $str, Encode::FB_DEFAULT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-24 15:56:55 +00:00
|
|
|
# quote unsafe chars, but keep the slash, even when it's not
|
|
|
|
# correct, but quoted slashes look too horrible in bookmarks
|
|
|
|
sub esc_param {
|
2005-11-14 04:47:18 +00:00
|
|
|
my $str = shift;
|
2010-02-07 20:52:25 +00:00
|
|
|
return undef unless defined $str;
|
2009-10-13 19:51:36 +00:00
|
|
|
$str =~ s/([^A-Za-z0-9\-_.~()\/:@ ]+)/CGI::escape($1)/eg;
|
2005-11-14 14:15:12 +00:00
|
|
|
$str =~ s/ /\+/g;
|
2005-11-14 04:47:18 +00:00
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2010-12-14 15:54:31 +00:00
|
|
|
# the quoting rules for path_info fragment are slightly different
|
|
|
|
sub esc_path_info {
|
|
|
|
my $str = shift;
|
|
|
|
return undef unless defined $str;
|
|
|
|
|
|
|
|
# path_info doesn't treat '+' as space (specially), but '?' must be escaped
|
|
|
|
$str =~ s/([^A-Za-z0-9\-_.~();\/;:@&= +]+)/CGI::escape($1)/eg;
|
|
|
|
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2010-08-22 11:12:12 +00:00
|
|
|
# quote unsafe chars in whole URL, so some characters cannot be quoted
|
2006-09-25 23:58:41 +00:00
|
|
|
sub esc_url {
|
|
|
|
my $str = shift;
|
2010-02-07 20:52:25 +00:00
|
|
|
return undef unless defined $str;
|
2010-07-15 07:29:01 +00:00
|
|
|
$str =~ s/([^A-Za-z0-9\-_.~();\/;?:@&= ]+)/CGI::escape($1)/eg;
|
2006-09-25 23:58:41 +00:00
|
|
|
$str =~ s/ /\+/g;
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2010-12-14 23:34:01 +00:00
|
|
|
# quote unsafe characters in HTML attributes
|
|
|
|
sub esc_attr {
|
|
|
|
|
|
|
|
# for XHTML conformance escaping '"' to '"' is not enough
|
|
|
|
return esc_html(@_);
|
|
|
|
}
|
|
|
|
|
2005-11-24 15:56:55 +00:00
|
|
|
# replace invalid utf8 character with SUBSTITUTION sequence
|
2009-05-07 17:11:29 +00:00
|
|
|
sub esc_html {
|
replace invalid utf8 sequences by UTF-8 REPLACEMENT CHARACTER (efbfbd)
I still strongly disagree with the git maintainers not to hint people,
to use the only sane default encoding for a distributed project,
which is utf8. I'm tired of hearing filesystem development arguments.
Git is a software offered to merge forth and back across the world
and not to provide a content neutral filesystem.
Btw: I have nothing against the ability to run git in a closed environment,
with a different encoding, that's fine, sure. But that is obviously not
the case for the projects on kernel.org. It's about sane defaults,
nothing else.
You have to make decisions guy, as always in life. The problems to
allow random encoded garbage in commit messages _without_ storing
the encoding, just makes zero sense. Eighter you introduce a per-commit
encoding field, if you insist on this craziness, or you define a default
encoding. Everything else is just lazy and does not solve any problem,
besides that you can claim now, that you are not responsible for the mess
in the repository.
Gitweb shows several commits at once, you allow various encodings committed
to the same repository, without any hint what that garbage from the
individual commits is encoded with. No idea why you don't get
the problem - it's unsolvable. If you merge different peoples work, you
have to speak a common language!
Kay Sievers <kay.sievers@vrfy.org>
2005-11-19 16:41:29 +00:00
|
|
|
my $str = shift;
|
2006-11-01 13:33:21 +00:00
|
|
|
my %opts = @_;
|
|
|
|
|
2010-02-07 20:52:25 +00:00
|
|
|
return undef unless defined $str;
|
|
|
|
|
2007-06-03 15:42:44 +00:00
|
|
|
$str = to_utf8($str);
|
2007-03-06 03:58:56 +00:00
|
|
|
$str = $cgi->escapeHTML($str);
|
2006-11-01 13:33:21 +00:00
|
|
|
if ($opts{'-nbsp'}) {
|
|
|
|
$str =~ s/ / /g;
|
|
|
|
}
|
2006-11-08 23:11:10 +00:00
|
|
|
$str =~ s|([[:cntrl:]])|(($1 ne "\t") ? quot_cec($1) : $1)|eg;
|
replace invalid utf8 sequences by UTF-8 REPLACEMENT CHARACTER (efbfbd)
I still strongly disagree with the git maintainers not to hint people,
to use the only sane default encoding for a distributed project,
which is utf8. I'm tired of hearing filesystem development arguments.
Git is a software offered to merge forth and back across the world
and not to provide a content neutral filesystem.
Btw: I have nothing against the ability to run git in a closed environment,
with a different encoding, that's fine, sure. But that is obviously not
the case for the projects on kernel.org. It's about sane defaults,
nothing else.
You have to make decisions guy, as always in life. The problems to
allow random encoded garbage in commit messages _without_ storing
the encoding, just makes zero sense. Eighter you introduce a per-commit
encoding field, if you insist on this craziness, or you define a default
encoding. Everything else is just lazy and does not solve any problem,
besides that you can claim now, that you are not responsible for the mess
in the repository.
Gitweb shows several commits at once, you allow various encodings committed
to the same repository, without any hint what that garbage from the
individual commits is encoded with. No idea why you don't get
the problem - it's unsolvable. If you merge different peoples work, you
have to speak a common language!
Kay Sievers <kay.sievers@vrfy.org>
2005-11-19 16:41:29 +00:00
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2006-11-25 08:43:59 +00:00
|
|
|
# quote control characters and escape filename to HTML
|
|
|
|
sub esc_path {
|
|
|
|
my $str = shift;
|
|
|
|
my %opts = @_;
|
|
|
|
|
2010-02-07 20:52:25 +00:00
|
|
|
return undef unless defined $str;
|
|
|
|
|
2007-06-03 15:42:44 +00:00
|
|
|
$str = to_utf8($str);
|
2007-03-06 03:58:56 +00:00
|
|
|
$str = $cgi->escapeHTML($str);
|
2006-11-25 08:43:59 +00:00
|
|
|
if ($opts{'-nbsp'}) {
|
|
|
|
$str =~ s/ / /g;
|
|
|
|
}
|
|
|
|
$str =~ s|([[:cntrl:]])|quot_cec($1)|eg;
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Make control characters "printable", using character escape codes (CEC)
|
2006-11-08 10:50:07 +00:00
|
|
|
sub quot_cec {
|
|
|
|
my $cntrl = shift;
|
2008-02-17 17:48:13 +00:00
|
|
|
my %opts = @_;
|
2006-11-08 10:50:07 +00:00
|
|
|
my %es = ( # character escape codes, aka escape sequences
|
2008-02-17 17:48:13 +00:00
|
|
|
"\t" => '\t', # tab (HT)
|
|
|
|
"\n" => '\n', # line feed (LF)
|
|
|
|
"\r" => '\r', # carrige return (CR)
|
|
|
|
"\f" => '\f', # form feed (FF)
|
|
|
|
"\b" => '\b', # backspace (BS)
|
|
|
|
"\a" => '\a', # alarm (bell) (BEL)
|
|
|
|
"\e" => '\e', # escape (ESC)
|
|
|
|
"\013" => '\v', # vertical tab (VT)
|
|
|
|
"\000" => '\0', # nul character (NUL)
|
|
|
|
);
|
2006-11-08 10:50:07 +00:00
|
|
|
my $chr = ( (exists $es{$cntrl})
|
|
|
|
? $es{$cntrl}
|
2008-10-01 20:11:54 +00:00
|
|
|
: sprintf('\%2x', ord($cntrl)) );
|
2008-02-17 17:48:13 +00:00
|
|
|
if ($opts{-nohtml}) {
|
|
|
|
return $chr;
|
|
|
|
} else {
|
|
|
|
return "<span class=\"cntrl\">$chr</span>";
|
|
|
|
}
|
2006-11-08 10:50:07 +00:00
|
|
|
}
|
|
|
|
|
2006-11-25 08:43:59 +00:00
|
|
|
# Alternatively use unicode control pictures codepoints,
|
|
|
|
# Unicode "printable representation" (PR)
|
2006-11-08 10:50:07 +00:00
|
|
|
sub quot_upr {
|
|
|
|
my $cntrl = shift;
|
2008-02-17 17:48:13 +00:00
|
|
|
my %opts = @_;
|
|
|
|
|
2006-11-08 10:50:07 +00:00
|
|
|
my $chr = sprintf('&#%04d;', 0x2400+ord($cntrl));
|
2008-02-17 17:48:13 +00:00
|
|
|
if ($opts{-nohtml}) {
|
|
|
|
return $chr;
|
|
|
|
} else {
|
|
|
|
return "<span class=\"cntrl\">$chr</span>";
|
|
|
|
}
|
2006-11-08 10:50:07 +00:00
|
|
|
}
|
|
|
|
|
2005-11-24 15:56:55 +00:00
|
|
|
# git may return quoted and escaped filenames
|
|
|
|
sub unquote {
|
|
|
|
my $str = shift;
|
2006-11-08 10:48:56 +00:00
|
|
|
|
|
|
|
sub unq {
|
|
|
|
my $seq = shift;
|
|
|
|
my %es = ( # character escape codes, aka escape sequences
|
|
|
|
't' => "\t", # tab (HT, TAB)
|
|
|
|
'n' => "\n", # newline (NL)
|
|
|
|
'r' => "\r", # return (CR)
|
|
|
|
'f' => "\f", # form feed (FF)
|
|
|
|
'b' => "\b", # backspace (BS)
|
|
|
|
'a' => "\a", # alarm (bell) (BEL)
|
|
|
|
'e' => "\e", # escape (ESC)
|
|
|
|
'v' => "\013", # vertical tab (VT)
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($seq =~ m/^[0-7]{1,3}$/) {
|
|
|
|
# octal char sequence
|
|
|
|
return chr(oct($seq));
|
|
|
|
} elsif (exists $es{$seq}) {
|
|
|
|
# C escape sequence, aka character escape code
|
2008-02-17 17:48:13 +00:00
|
|
|
return $es{$seq};
|
2006-11-08 10:48:56 +00:00
|
|
|
}
|
|
|
|
# quoted ordinary character
|
|
|
|
return $seq;
|
|
|
|
}
|
|
|
|
|
2005-11-24 15:56:55 +00:00
|
|
|
if ($str =~ m/^"(.*)"$/) {
|
2006-11-08 10:48:56 +00:00
|
|
|
# needs unquoting
|
2005-11-24 15:56:55 +00:00
|
|
|
$str = $1;
|
2006-11-08 10:48:56 +00:00
|
|
|
$str =~ s/\\([^0-7]|[0-7]{1,3})/unq($1)/eg;
|
2005-11-24 15:56:55 +00:00
|
|
|
}
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2006-08-06 00:08:31 +00:00
|
|
|
# escape tabs (convert tabs to spaces)
|
|
|
|
sub untabify {
|
|
|
|
my $line = shift;
|
|
|
|
|
|
|
|
while ((my $pos = index($line, "\t")) != -1) {
|
|
|
|
if (my $count = (8 - ($pos % 8))) {
|
|
|
|
my $spaces = ' ' x $count;
|
|
|
|
$line =~ s/\t/$spaces/;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $line;
|
|
|
|
}
|
|
|
|
|
2006-09-16 22:31:01 +00:00
|
|
|
sub project_in_list {
|
|
|
|
my $project = shift;
|
|
|
|
my @list = git_get_projects_list();
|
|
|
|
return @list && scalar(grep { $_->{'path'} eq $project } @list);
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ----------------------------------------------------------------------
|
|
|
|
## HTML aware string manipulation
|
|
|
|
|
gitweb: Better cutting matched string and its context
Improve look of commit search output ('search' view) by better cutting
of matched string and its context in match info, as suggested by Junio.
For example, if you are looking for "very long search string" in the
following line:
Could somebody test this with very long search string, and see how
you would now see:
...this with <<very long ... string>>, and see...
instead of:
Could som... <<very long search...>>, and see...
(where <<something>> denotes emphasized / colored fragment; matched
fragment to be more exact).
For this feature, support for fourth [optional] parameter to chop_str
subroutine was added. This fourth parameter is used to denote where
to cut string to make it shorter. chop_str can now cut at the
beginning (from the _left_ side of the string), in the middle
(_center_ of the string), or at the end (from the _right_ side of
the string); cutting from right is the default:
chop_str(somestring, len, slop, 'left') -> ' ...string'
chop_str(somestring, len, slop, 'center') -> 'som ... ing'
chop_str(somestring, len, slop, 'right') -> 'somestr... '
If you want to use default slop (default additional length), use undef
as value for third parameter to chop_str.
While at it, return from chop_str early if given string is so short
that chop_str couldn't shorten it. Simplify also regexp used by
chop_str. Make ellipsis (dots) stick to shortened fragment for
cutting at ends, to better see which part got shortened.
Simplify passing all arguments to chop_str in chop_and_escape_str
subroutine. This was needed to pass additional options to chop_str.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-25 20:07:57 +00:00
|
|
|
# Try to chop given string on a word boundary between position
|
|
|
|
# $len and $len+$add_len. If there is no word boundary there,
|
|
|
|
# chop at $len+$add_len. Do not chop if chopped part plus ellipsis
|
|
|
|
# (marking chopped part) would be longer than given string.
|
2006-07-31 19:22:15 +00:00
|
|
|
sub chop_str {
|
|
|
|
my $str = shift;
|
|
|
|
my $len = shift;
|
|
|
|
my $add_len = shift || 10;
|
gitweb: Better cutting matched string and its context
Improve look of commit search output ('search' view) by better cutting
of matched string and its context in match info, as suggested by Junio.
For example, if you are looking for "very long search string" in the
following line:
Could somebody test this with very long search string, and see how
you would now see:
...this with <<very long ... string>>, and see...
instead of:
Could som... <<very long search...>>, and see...
(where <<something>> denotes emphasized / colored fragment; matched
fragment to be more exact).
For this feature, support for fourth [optional] parameter to chop_str
subroutine was added. This fourth parameter is used to denote where
to cut string to make it shorter. chop_str can now cut at the
beginning (from the _left_ side of the string), in the middle
(_center_ of the string), or at the end (from the _right_ side of
the string); cutting from right is the default:
chop_str(somestring, len, slop, 'left') -> ' ...string'
chop_str(somestring, len, slop, 'center') -> 'som ... ing'
chop_str(somestring, len, slop, 'right') -> 'somestr... '
If you want to use default slop (default additional length), use undef
as value for third parameter to chop_str.
While at it, return from chop_str early if given string is so short
that chop_str couldn't shorten it. Simplify also regexp used by
chop_str. Make ellipsis (dots) stick to shortened fragment for
cutting at ends, to better see which part got shortened.
Simplify passing all arguments to chop_str in chop_and_escape_str
subroutine. This was needed to pass additional options to chop_str.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-25 20:07:57 +00:00
|
|
|
my $where = shift || 'right'; # 'left' | 'center' | 'right'
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2008-05-21 11:44:43 +00:00
|
|
|
# Make sure perl knows it is utf8 encoded so we don't
|
|
|
|
# cut in the middle of a utf8 multibyte char.
|
|
|
|
$str = to_utf8($str);
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# allow only $len chars, but don't cut a word if it would fit in $add_len
|
|
|
|
# if it doesn't fit, cut it if it's still longer than the dots we would add
|
gitweb: Better cutting matched string and its context
Improve look of commit search output ('search' view) by better cutting
of matched string and its context in match info, as suggested by Junio.
For example, if you are looking for "very long search string" in the
following line:
Could somebody test this with very long search string, and see how
you would now see:
...this with <<very long ... string>>, and see...
instead of:
Could som... <<very long search...>>, and see...
(where <<something>> denotes emphasized / colored fragment; matched
fragment to be more exact).
For this feature, support for fourth [optional] parameter to chop_str
subroutine was added. This fourth parameter is used to denote where
to cut string to make it shorter. chop_str can now cut at the
beginning (from the _left_ side of the string), in the middle
(_center_ of the string), or at the end (from the _right_ side of
the string); cutting from right is the default:
chop_str(somestring, len, slop, 'left') -> ' ...string'
chop_str(somestring, len, slop, 'center') -> 'som ... ing'
chop_str(somestring, len, slop, 'right') -> 'somestr... '
If you want to use default slop (default additional length), use undef
as value for third parameter to chop_str.
While at it, return from chop_str early if given string is so short
that chop_str couldn't shorten it. Simplify also regexp used by
chop_str. Make ellipsis (dots) stick to shortened fragment for
cutting at ends, to better see which part got shortened.
Simplify passing all arguments to chop_str in chop_and_escape_str
subroutine. This was needed to pass additional options to chop_str.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-25 20:07:57 +00:00
|
|
|
# remove chopped character entities entirely
|
|
|
|
|
|
|
|
# when chopping in the middle, distribute $len into left and right part
|
|
|
|
# return early if chopping wouldn't make string shorter
|
|
|
|
if ($where eq 'center') {
|
|
|
|
return $str if ($len + 5 >= length($str)); # filler is length 5
|
|
|
|
$len = int($len/2);
|
|
|
|
} else {
|
|
|
|
return $str if ($len + 4 >= length($str)); # filler is length 4
|
|
|
|
}
|
|
|
|
|
|
|
|
# regexps: ending and beginning with word part up to $add_len
|
|
|
|
my $endre = qr/.{$len}\w{0,$add_len}/;
|
|
|
|
my $begre = qr/\w{0,$add_len}.{$len}/;
|
|
|
|
|
|
|
|
if ($where eq 'left') {
|
|
|
|
$str =~ m/^(.*?)($begre)$/;
|
|
|
|
my ($lead, $body) = ($1, $2);
|
|
|
|
if (length($lead) > 4) {
|
|
|
|
$lead = " ...";
|
|
|
|
}
|
|
|
|
return "$lead$body";
|
|
|
|
|
|
|
|
} elsif ($where eq 'center') {
|
|
|
|
$str =~ m/^($endre)(.*)$/;
|
|
|
|
my ($left, $str) = ($1, $2);
|
|
|
|
$str =~ m/^(.*?)($begre)$/;
|
|
|
|
my ($mid, $right) = ($1, $2);
|
|
|
|
if (length($mid) > 5) {
|
|
|
|
$mid = " ... ";
|
|
|
|
}
|
|
|
|
return "$left$mid$right";
|
|
|
|
|
|
|
|
} else {
|
|
|
|
$str =~ m/^($endre)(.*)$/;
|
|
|
|
my $body = $1;
|
|
|
|
my $tail = $2;
|
|
|
|
if (length($tail) > 4) {
|
|
|
|
$tail = "... ";
|
|
|
|
}
|
|
|
|
return "$body$tail";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-23 01:31:22 +00:00
|
|
|
# takes the same arguments as chop_str, but also wraps a <span> around the
|
|
|
|
# result with a title attribute if it does get chopped. Additionally, the
|
|
|
|
# string is HTML-escaped.
|
|
|
|
sub chop_and_escape_str {
|
gitweb: Better cutting matched string and its context
Improve look of commit search output ('search' view) by better cutting
of matched string and its context in match info, as suggested by Junio.
For example, if you are looking for "very long search string" in the
following line:
Could somebody test this with very long search string, and see how
you would now see:
...this with <<very long ... string>>, and see...
instead of:
Could som... <<very long search...>>, and see...
(where <<something>> denotes emphasized / colored fragment; matched
fragment to be more exact).
For this feature, support for fourth [optional] parameter to chop_str
subroutine was added. This fourth parameter is used to denote where
to cut string to make it shorter. chop_str can now cut at the
beginning (from the _left_ side of the string), in the middle
(_center_ of the string), or at the end (from the _right_ side of
the string); cutting from right is the default:
chop_str(somestring, len, slop, 'left') -> ' ...string'
chop_str(somestring, len, slop, 'center') -> 'som ... ing'
chop_str(somestring, len, slop, 'right') -> 'somestr... '
If you want to use default slop (default additional length), use undef
as value for third parameter to chop_str.
While at it, return from chop_str early if given string is so short
that chop_str couldn't shorten it. Simplify also regexp used by
chop_str. Make ellipsis (dots) stick to shortened fragment for
cutting at ends, to better see which part got shortened.
Simplify passing all arguments to chop_str in chop_and_escape_str
subroutine. This was needed to pass additional options to chop_str.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-25 20:07:57 +00:00
|
|
|
my ($str) = @_;
|
2007-10-23 01:31:22 +00:00
|
|
|
|
gitweb: Better cutting matched string and its context
Improve look of commit search output ('search' view) by better cutting
of matched string and its context in match info, as suggested by Junio.
For example, if you are looking for "very long search string" in the
following line:
Could somebody test this with very long search string, and see how
you would now see:
...this with <<very long ... string>>, and see...
instead of:
Could som... <<very long search...>>, and see...
(where <<something>> denotes emphasized / colored fragment; matched
fragment to be more exact).
For this feature, support for fourth [optional] parameter to chop_str
subroutine was added. This fourth parameter is used to denote where
to cut string to make it shorter. chop_str can now cut at the
beginning (from the _left_ side of the string), in the middle
(_center_ of the string), or at the end (from the _right_ side of
the string); cutting from right is the default:
chop_str(somestring, len, slop, 'left') -> ' ...string'
chop_str(somestring, len, slop, 'center') -> 'som ... ing'
chop_str(somestring, len, slop, 'right') -> 'somestr... '
If you want to use default slop (default additional length), use undef
as value for third parameter to chop_str.
While at it, return from chop_str early if given string is so short
that chop_str couldn't shorten it. Simplify also regexp used by
chop_str. Make ellipsis (dots) stick to shortened fragment for
cutting at ends, to better see which part got shortened.
Simplify passing all arguments to chop_str in chop_and_escape_str
subroutine. This was needed to pass additional options to chop_str.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-25 20:07:57 +00:00
|
|
|
my $chopped = chop_str(@_);
|
2007-10-23 01:31:22 +00:00
|
|
|
if ($chopped eq $str) {
|
|
|
|
return esc_html($chopped);
|
|
|
|
} else {
|
gitweb: Sanitize title attribute in format_subject_html
Replace control characters with question mark '?' (like in
chop_and_esc_str).
A little background: some web browsers turn on strict (and
unforgiving) XML validating mode for XHTML documents served using
application/xhtml+xml content type. This means among others that
control characters are forbidden to appear in gitweb output.
CGI.pm does by default slight escaping (using simple_escape subroutine
from CGI::Util) of all _attribute_ values (depending on the value of
autoEscape, by default on). This escaping, at least in CGI.pm version
3.10 (most current version at CPAN is 3.43), is minimal: only '"',
'&', '<' and '>' are escaped using named HTML entity references
(", &, < and > respectively). But simple_escape does
not do escaping of control characters such as ^X which are invalid in
XHTML (in strict mode).
If by some accident commit message do contain some control character
in first 50 characters (more or less) of first line of commit message,
and this line is longer than 50 characters (so gitweb shortens it for
display), then gitweb would put this control character in title
attribute (and CGI.pm would not remove them). The tag _contents_ is
safe because it is escaped using esc_html() explicitly, and it
replaces control characters by their printable representation.
While at it: chop_and_escape_str doesn't need capturing group.
Noticed-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-05-22 15:35:46 +00:00
|
|
|
$str =~ s/[[:cntrl:]]/?/g;
|
2008-02-16 22:07:46 +00:00
|
|
|
return $cgi->span({-title=>$str}, esc_html($chopped));
|
2007-10-23 01:31:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ----------------------------------------------------------------------
|
|
|
|
## functions returning short strings
|
|
|
|
|
2006-06-20 14:58:12 +00:00
|
|
|
# CSS class for given age value (in seconds)
|
|
|
|
sub age_class {
|
|
|
|
my $age = shift;
|
|
|
|
|
2007-05-13 10:39:22 +00:00
|
|
|
if (!defined $age) {
|
|
|
|
return "noage";
|
|
|
|
} elsif ($age < 60*60*2) {
|
2006-06-20 14:58:12 +00:00
|
|
|
return "age0";
|
|
|
|
} elsif ($age < 60*60*24*2) {
|
|
|
|
return "age1";
|
|
|
|
} else {
|
|
|
|
return "age2";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# convert age in seconds to "nn units ago" string
|
|
|
|
sub age_string {
|
|
|
|
my $age = shift;
|
|
|
|
my $age_str;
|
2005-08-07 18:15:44 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
if ($age > 60*60*24*365*2) {
|
|
|
|
$age_str = (int $age/60/60/24/365);
|
|
|
|
$age_str .= " years ago";
|
|
|
|
} elsif ($age > 60*60*24*(365/12)*2) {
|
|
|
|
$age_str = int $age/60/60/24/(365/12);
|
|
|
|
$age_str .= " months ago";
|
|
|
|
} elsif ($age > 60*60*24*7*2) {
|
|
|
|
$age_str = int $age/60/60/24/7;
|
|
|
|
$age_str .= " weeks ago";
|
|
|
|
} elsif ($age > 60*60*24*2) {
|
|
|
|
$age_str = int $age/60/60/24;
|
|
|
|
$age_str .= " days ago";
|
|
|
|
} elsif ($age > 60*60*2) {
|
|
|
|
$age_str = int $age/60/60;
|
|
|
|
$age_str .= " hours ago";
|
|
|
|
} elsif ($age > 60*2) {
|
|
|
|
$age_str = int $age/60;
|
|
|
|
$age_str .= " min ago";
|
|
|
|
} elsif ($age > 2) {
|
|
|
|
$age_str = int $age;
|
|
|
|
$age_str .= " sec ago";
|
2006-07-11 10:19:34 +00:00
|
|
|
} else {
|
2006-07-31 19:22:15 +00:00
|
|
|
$age_str .= " right now";
|
2005-08-07 17:52:52 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
return $age_str;
|
2005-08-07 17:49:46 +00:00
|
|
|
}
|
|
|
|
|
2007-07-28 14:27:31 +00:00
|
|
|
use constant {
|
|
|
|
S_IFINVALID => 0030000,
|
|
|
|
S_IFGITLINK => 0160000,
|
|
|
|
};
|
|
|
|
|
|
|
|
# submodule/subproject, a commit object reference
|
2009-05-07 17:11:29 +00:00
|
|
|
sub S_ISGITLINK {
|
2007-07-28 14:27:31 +00:00
|
|
|
my $mode = shift;
|
|
|
|
|
|
|
|
return (($mode & S_IFMT) == S_IFGITLINK)
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# convert file mode in octal to symbolic file mode string
|
|
|
|
sub mode_str {
|
|
|
|
my $mode = oct shift;
|
|
|
|
|
2007-07-28 14:27:31 +00:00
|
|
|
if (S_ISGITLINK($mode)) {
|
|
|
|
return 'm---------';
|
|
|
|
} elsif (S_ISDIR($mode & S_IFMT)) {
|
2006-07-31 19:22:15 +00:00
|
|
|
return 'drwxr-xr-x';
|
|
|
|
} elsif (S_ISLNK($mode)) {
|
|
|
|
return 'lrwxrwxrwx';
|
|
|
|
} elsif (S_ISREG($mode)) {
|
|
|
|
# git cares only about the executable bit
|
|
|
|
if ($mode & S_IXUSR) {
|
|
|
|
return '-rwxr-xr-x';
|
|
|
|
} else {
|
|
|
|
return '-rw-r--r--';
|
|
|
|
};
|
2005-08-07 18:27:18 +00:00
|
|
|
} else {
|
2006-07-31 19:22:15 +00:00
|
|
|
return '----------';
|
2005-08-07 18:13:02 +00:00
|
|
|
}
|
2005-08-07 17:49:46 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# convert file mode in octal to file type string
|
|
|
|
sub file_type {
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
my $mode = shift;
|
|
|
|
|
|
|
|
if ($mode !~ m/^[0-7]+$/) {
|
|
|
|
return $mode;
|
|
|
|
} else {
|
|
|
|
$mode = oct $mode;
|
|
|
|
}
|
2005-08-07 18:17:19 +00:00
|
|
|
|
2007-07-28 14:27:31 +00:00
|
|
|
if (S_ISGITLINK($mode)) {
|
|
|
|
return "submodule";
|
|
|
|
} elsif (S_ISDIR($mode & S_IFMT)) {
|
2006-07-31 19:22:15 +00:00
|
|
|
return "directory";
|
|
|
|
} elsif (S_ISLNK($mode)) {
|
|
|
|
return "symlink";
|
|
|
|
} elsif (S_ISREG($mode)) {
|
|
|
|
return "file";
|
|
|
|
} else {
|
|
|
|
return "unknown";
|
|
|
|
}
|
2005-08-07 18:15:44 +00:00
|
|
|
}
|
|
|
|
|
2006-11-08 16:59:41 +00:00
|
|
|
# convert file mode in octal to file type description string
|
|
|
|
sub file_type_long {
|
|
|
|
my $mode = shift;
|
|
|
|
|
|
|
|
if ($mode !~ m/^[0-7]+$/) {
|
|
|
|
return $mode;
|
|
|
|
} else {
|
|
|
|
$mode = oct $mode;
|
|
|
|
}
|
|
|
|
|
2007-07-28 14:27:31 +00:00
|
|
|
if (S_ISGITLINK($mode)) {
|
|
|
|
return "submodule";
|
|
|
|
} elsif (S_ISDIR($mode & S_IFMT)) {
|
2006-11-08 16:59:41 +00:00
|
|
|
return "directory";
|
|
|
|
} elsif (S_ISLNK($mode)) {
|
|
|
|
return "symlink";
|
|
|
|
} elsif (S_ISREG($mode)) {
|
|
|
|
if ($mode & S_IXUSR) {
|
|
|
|
return "executable";
|
|
|
|
} else {
|
|
|
|
return "file";
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ----------------------------------------------------------------------
|
|
|
|
## functions returning short HTML fragments, or transforming HTML fragments
|
2007-02-04 04:49:16 +00:00
|
|
|
## which don't belong to other sections
|
2006-07-30 12:59:57 +00:00
|
|
|
|
2006-11-09 08:57:13 +00:00
|
|
|
# format line of commit message.
|
2006-07-31 19:22:15 +00:00
|
|
|
sub format_log_line_html {
|
|
|
|
my $line = shift;
|
2006-07-30 12:59:57 +00:00
|
|
|
|
2006-11-09 08:57:13 +00:00
|
|
|
$line = esc_html($line, -nbsp=>1);
|
2009-02-18 03:00:43 +00:00
|
|
|
$line =~ s{\b([0-9a-fA-F]{8,40})\b}{
|
|
|
|
$cgi->a({-href => href(action=>"object", hash=>$1),
|
|
|
|
-class => "text"}, $1);
|
|
|
|
}eg;
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
return $line;
|
2006-07-30 12:59:57 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# format marker of refs pointing to given object
|
2008-09-02 19:47:05 +00:00
|
|
|
|
|
|
|
# the destination action is chosen based on object type and current context:
|
|
|
|
# - for annotated tags, we choose the tag view unless it's the current view
|
|
|
|
# already, in which case we go to shortlog view
|
|
|
|
# - for other refs, we keep the current view if we're in history, shortlog or
|
|
|
|
# log view, and select shortlog otherwise
|
2006-08-14 00:05:47 +00:00
|
|
|
sub format_ref_marker {
|
2006-07-31 19:22:15 +00:00
|
|
|
my ($refs, $id) = @_;
|
2006-08-14 00:14:20 +00:00
|
|
|
my $markers = '';
|
2006-07-30 18:32:01 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
if (defined $refs->{$id}) {
|
2006-08-14 00:14:20 +00:00
|
|
|
foreach my $ref (@{$refs->{$id}}) {
|
2008-09-02 19:47:05 +00:00
|
|
|
# this code exploits the fact that non-lightweight tags are the
|
|
|
|
# only indirect objects, and that they are the only objects for which
|
|
|
|
# we want to use tag instead of shortlog as action
|
2006-08-14 00:14:20 +00:00
|
|
|
my ($type, $name) = qw();
|
2008-09-02 19:47:05 +00:00
|
|
|
my $indirect = ($ref =~ s/\^\{\}$//);
|
2006-08-14 00:14:20 +00:00
|
|
|
# e.g. tags/v2.6.11 or heads/next
|
|
|
|
if ($ref =~ m!^(.*?)s?/(.*)$!) {
|
|
|
|
$type = $1;
|
|
|
|
$name = $2;
|
|
|
|
} else {
|
|
|
|
$type = "ref";
|
|
|
|
$name = $ref;
|
|
|
|
}
|
|
|
|
|
2008-09-02 19:47:05 +00:00
|
|
|
my $class = $type;
|
|
|
|
$class .= " indirect" if $indirect;
|
|
|
|
|
|
|
|
my $dest_action = "shortlog";
|
|
|
|
|
|
|
|
if ($indirect) {
|
|
|
|
$dest_action = "tag" unless $action eq "tag";
|
|
|
|
} elsif ($action =~ /^(history|(short)?log)$/) {
|
|
|
|
$dest_action = $action;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $dest = "";
|
|
|
|
$dest .= "refs/" unless $ref =~ m!^refs/!;
|
|
|
|
$dest .= $ref;
|
|
|
|
|
|
|
|
my $link = $cgi->a({
|
|
|
|
-href => href(
|
|
|
|
action=>$dest_action,
|
|
|
|
hash=>$dest
|
|
|
|
)}, $name);
|
|
|
|
|
2010-12-14 23:34:01 +00:00
|
|
|
$markers .= " <span class=\"".esc_attr($class)."\" title=\"".esc_attr($ref)."\">" .
|
2008-09-02 19:47:05 +00:00
|
|
|
$link . "</span>";
|
2006-08-14 00:14:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($markers) {
|
|
|
|
return ' <span class="refs">'. $markers . '</span>';
|
2006-07-31 19:22:15 +00:00
|
|
|
} else {
|
|
|
|
return "";
|
|
|
|
}
|
2006-07-30 18:32:01 +00:00
|
|
|
}
|
|
|
|
|
2006-08-14 00:08:27 +00:00
|
|
|
# format, perhaps shortened and with markers, title line
|
|
|
|
sub format_subject_html {
|
2006-08-15 22:24:30 +00:00
|
|
|
my ($long, $short, $href, $extra) = @_;
|
2006-08-14 00:08:27 +00:00
|
|
|
$extra = '' unless defined($extra);
|
|
|
|
|
|
|
|
if (length($short) < length($long)) {
|
gitweb: Sanitize title attribute in format_subject_html
Replace control characters with question mark '?' (like in
chop_and_esc_str).
A little background: some web browsers turn on strict (and
unforgiving) XML validating mode for XHTML documents served using
application/xhtml+xml content type. This means among others that
control characters are forbidden to appear in gitweb output.
CGI.pm does by default slight escaping (using simple_escape subroutine
from CGI::Util) of all _attribute_ values (depending on the value of
autoEscape, by default on). This escaping, at least in CGI.pm version
3.10 (most current version at CPAN is 3.43), is minimal: only '"',
'&', '<' and '>' are escaped using named HTML entity references
(", &, < and > respectively). But simple_escape does
not do escaping of control characters such as ^X which are invalid in
XHTML (in strict mode).
If by some accident commit message do contain some control character
in first 50 characters (more or less) of first line of commit message,
and this line is longer than 50 characters (so gitweb shortens it for
display), then gitweb would put this control character in title
attribute (and CGI.pm would not remove them). The tag _contents_ is
safe because it is escaped using esc_html() explicitly, and it
replaces control characters by their printable representation.
While at it: chop_and_escape_str doesn't need capturing group.
Noticed-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-05-22 15:35:46 +00:00
|
|
|
$long =~ s/[[:cntrl:]]/?/g;
|
2006-08-22 10:02:48 +00:00
|
|
|
return $cgi->a({-href => $href, -class => "list subject",
|
2007-06-03 15:42:44 +00:00
|
|
|
-title => to_utf8($long)},
|
2009-08-23 08:28:09 +00:00
|
|
|
esc_html($short)) . $extra;
|
2006-08-14 00:08:27 +00:00
|
|
|
} else {
|
2006-08-22 10:02:48 +00:00
|
|
|
return $cgi->a({-href => $href, -class => "list subject"},
|
2009-08-23 08:28:09 +00:00
|
|
|
esc_html($long)) . $extra;
|
2006-08-14 00:08:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 22:00:52 +00:00
|
|
|
# Rather than recomputing the url for an email multiple times, we cache it
|
|
|
|
# after the first hit. This gives a visible benefit in views where the avatar
|
|
|
|
# for the same email is used repeatedly (e.g. shortlog).
|
|
|
|
# The cache is shared by all avatar engines (currently gravatar only), which
|
|
|
|
# are free to use it as preferred. Since only one avatar engine is used for any
|
|
|
|
# given page, there's no risk for cache conflicts.
|
|
|
|
our %avatar_cache = ();
|
|
|
|
|
2009-06-29 22:00:53 +00:00
|
|
|
# Compute the picon url for a given email, by using the picon search service over at
|
|
|
|
# http://www.cs.indiana.edu/picons/search.html
|
|
|
|
sub picon_url {
|
|
|
|
my $email = lc shift;
|
|
|
|
if (!$avatar_cache{$email}) {
|
|
|
|
my ($user, $domain) = split('@', $email);
|
|
|
|
$avatar_cache{$email} =
|
|
|
|
"http://www.cs.indiana.edu/cgi-pub/kinzler/piconsearch.cgi/" .
|
|
|
|
"$domain/$user/" .
|
|
|
|
"users+domains+unknown/up/single";
|
|
|
|
}
|
|
|
|
return $avatar_cache{$email};
|
|
|
|
}
|
|
|
|
|
2009-06-29 22:00:52 +00:00
|
|
|
# Compute the gravatar url for a given email, if it's not in the cache already.
|
|
|
|
# Gravatar stores only the part of the URL before the size, since that's the
|
|
|
|
# one computationally more expensive. This also allows reuse of the cache for
|
|
|
|
# different sizes (for this particular engine).
|
|
|
|
sub gravatar_url {
|
|
|
|
my $email = lc shift;
|
|
|
|
my $size = shift;
|
|
|
|
$avatar_cache{$email} ||=
|
|
|
|
"http://www.gravatar.com/avatar/" .
|
|
|
|
Digest::MD5::md5_hex($email) . "?s=";
|
|
|
|
return $avatar_cache{$email} . $size;
|
|
|
|
}
|
|
|
|
|
2009-06-29 22:00:51 +00:00
|
|
|
# Insert an avatar for the given $email at the given $size if the feature
|
|
|
|
# is enabled.
|
|
|
|
sub git_get_avatar {
|
|
|
|
my ($email, %opts) = @_;
|
|
|
|
my $pre_white = ($opts{-pad_before} ? " " : "");
|
|
|
|
my $post_white = ($opts{-pad_after} ? " " : "");
|
|
|
|
$opts{-size} ||= 'default';
|
|
|
|
my $size = $avatar_size{$opts{-size}} || $avatar_size{'default'};
|
|
|
|
my $url = "";
|
|
|
|
if ($git_avatar eq 'gravatar') {
|
2009-06-29 22:00:52 +00:00
|
|
|
$url = gravatar_url($email, $size);
|
2009-06-29 22:00:53 +00:00
|
|
|
} elsif ($git_avatar eq 'picon') {
|
|
|
|
$url = picon_url($email);
|
2009-06-29 22:00:51 +00:00
|
|
|
}
|
2009-06-29 22:00:53 +00:00
|
|
|
# Other providers can be added by extending the if chain, defining $url
|
2009-06-29 22:00:51 +00:00
|
|
|
# as needed. If no variant puts something in $url, we assume avatars
|
|
|
|
# are completely disabled/unavailable.
|
|
|
|
if ($url) {
|
|
|
|
return $pre_white .
|
|
|
|
"<img width=\"$size\" " .
|
|
|
|
"class=\"avatar\" " .
|
2010-12-14 23:34:01 +00:00
|
|
|
"src=\"".esc_url($url)."\" " .
|
2009-06-29 22:00:54 +00:00
|
|
|
"alt=\"\" " .
|
2009-06-29 22:00:51 +00:00
|
|
|
"/>" . $post_white;
|
|
|
|
} else {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-16 04:14:59 +00:00
|
|
|
sub format_search_author {
|
|
|
|
my ($author, $searchtype, $displaytext) = @_;
|
|
|
|
my $have_search = gitweb_check_feature('search');
|
|
|
|
|
|
|
|
if ($have_search) {
|
|
|
|
my $performed = "";
|
|
|
|
if ($searchtype eq 'author') {
|
|
|
|
$performed = "authored";
|
|
|
|
} elsif ($searchtype eq 'committer') {
|
|
|
|
$performed = "committed";
|
|
|
|
}
|
|
|
|
|
|
|
|
return $cgi->a({-href => href(action=>"search", hash=>$hash,
|
|
|
|
searchtext=>$author,
|
|
|
|
searchtype=>$searchtype), class=>"list",
|
|
|
|
title=>"Search for commits $performed by $author"},
|
|
|
|
$displaytext);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
return $displaytext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 22:00:48 +00:00
|
|
|
# format the author name of the given commit with the given tag
|
|
|
|
# the author name is chopped and escaped according to the other
|
|
|
|
# optional parameters (see chop_str).
|
|
|
|
sub format_author_html {
|
|
|
|
my $tag = shift;
|
|
|
|
my $co = shift;
|
|
|
|
my $author = chop_and_escape_str($co->{'author_name'}, @_);
|
2009-06-29 22:00:51 +00:00
|
|
|
return "<$tag class=\"author\">" .
|
2009-10-16 04:14:59 +00:00
|
|
|
format_search_author($co->{'author_name'}, "author",
|
|
|
|
git_get_avatar($co->{'author_email'}, -pad_after => 1) .
|
|
|
|
$author) .
|
|
|
|
"</$tag>";
|
2009-06-29 22:00:48 +00:00
|
|
|
}
|
|
|
|
|
2007-06-08 11:27:42 +00:00
|
|
|
# format git diff header line, i.e. "diff --(git|combined|cc) ..."
|
|
|
|
sub format_git_diff_header_line {
|
|
|
|
my $line = shift;
|
|
|
|
my $diffinfo = shift;
|
|
|
|
my ($from, $to) = @_;
|
|
|
|
|
|
|
|
if ($diffinfo->{'nparents'}) {
|
|
|
|
# combined diff
|
|
|
|
$line =~ s!^(diff (.*?) )"?.*$!$1!;
|
|
|
|
if ($to->{'href'}) {
|
|
|
|
$line .= $cgi->a({-href => $to->{'href'}, -class => "path"},
|
|
|
|
esc_path($to->{'file'}));
|
|
|
|
} else { # file was deleted (no href)
|
|
|
|
$line .= esc_path($to->{'file'});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
# "ordinary" diff
|
|
|
|
$line =~ s!^(diff (.*?) )"?a/.*$!$1!;
|
|
|
|
if ($from->{'href'}) {
|
|
|
|
$line .= $cgi->a({-href => $from->{'href'}, -class => "path"},
|
|
|
|
'a/' . esc_path($from->{'file'}));
|
|
|
|
} else { # file was added (no href)
|
|
|
|
$line .= 'a/' . esc_path($from->{'file'});
|
|
|
|
}
|
|
|
|
$line .= ' ';
|
|
|
|
if ($to->{'href'}) {
|
|
|
|
$line .= $cgi->a({-href => $to->{'href'}, -class => "path"},
|
|
|
|
'b/' . esc_path($to->{'file'}));
|
|
|
|
} else { # file was deleted
|
|
|
|
$line .= 'b/' . esc_path($to->{'file'});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "<div class=\"diff header\">$line</div>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# format extended diff header line, before patch itself
|
|
|
|
sub format_extended_diff_header_line {
|
|
|
|
my $line = shift;
|
|
|
|
my $diffinfo = shift;
|
|
|
|
my ($from, $to) = @_;
|
|
|
|
|
|
|
|
# match <path>
|
|
|
|
if ($line =~ s!^((copy|rename) from ).*$!$1! && $from->{'href'}) {
|
|
|
|
$line .= $cgi->a({-href=>$from->{'href'}, -class=>"path"},
|
|
|
|
esc_path($from->{'file'}));
|
|
|
|
}
|
|
|
|
if ($line =~ s!^((copy|rename) to ).*$!$1! && $to->{'href'}) {
|
|
|
|
$line .= $cgi->a({-href=>$to->{'href'}, -class=>"path"},
|
|
|
|
esc_path($to->{'file'}));
|
|
|
|
}
|
|
|
|
# match single <mode>
|
|
|
|
if ($line =~ m/\s(\d{6})$/) {
|
|
|
|
$line .= '<span class="info"> (' .
|
|
|
|
file_type_long($1) .
|
|
|
|
')</span>';
|
|
|
|
}
|
|
|
|
# match <hash>
|
|
|
|
if ($line =~ m/^index [0-9a-fA-F]{40},[0-9a-fA-F]{40}/) {
|
|
|
|
# can match only for combined diff
|
|
|
|
$line = 'index ';
|
|
|
|
for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {
|
|
|
|
if ($from->{'href'}[$i]) {
|
|
|
|
$line .= $cgi->a({-href=>$from->{'href'}[$i],
|
|
|
|
-class=>"hash"},
|
|
|
|
substr($diffinfo->{'from_id'}[$i],0,7));
|
|
|
|
} else {
|
|
|
|
$line .= '0' x 7;
|
|
|
|
}
|
|
|
|
# separator
|
|
|
|
$line .= ',' if ($i < $diffinfo->{'nparents'} - 1);
|
|
|
|
}
|
|
|
|
$line .= '..';
|
|
|
|
if ($to->{'href'}) {
|
|
|
|
$line .= $cgi->a({-href=>$to->{'href'}, -class=>"hash"},
|
|
|
|
substr($diffinfo->{'to_id'},0,7));
|
|
|
|
} else {
|
|
|
|
$line .= '0' x 7;
|
|
|
|
}
|
|
|
|
|
|
|
|
} elsif ($line =~ m/^index [0-9a-fA-F]{40}..[0-9a-fA-F]{40}/) {
|
|
|
|
# can match only for ordinary diff
|
|
|
|
my ($from_link, $to_link);
|
|
|
|
if ($from->{'href'}) {
|
|
|
|
$from_link = $cgi->a({-href=>$from->{'href'}, -class=>"hash"},
|
|
|
|
substr($diffinfo->{'from_id'},0,7));
|
|
|
|
} else {
|
|
|
|
$from_link = '0' x 7;
|
|
|
|
}
|
|
|
|
if ($to->{'href'}) {
|
|
|
|
$to_link = $cgi->a({-href=>$to->{'href'}, -class=>"hash"},
|
|
|
|
substr($diffinfo->{'to_id'},0,7));
|
|
|
|
} else {
|
|
|
|
$to_link = '0' x 7;
|
|
|
|
}
|
|
|
|
my ($from_id, $to_id) = ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});
|
|
|
|
$line =~ s!$from_id\.\.$to_id!$from_link..$to_link!;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $line . "<br/>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# format from-file/to-file diff header
|
|
|
|
sub format_diff_from_to_header {
|
2007-06-08 11:32:44 +00:00
|
|
|
my ($from_line, $to_line, $diffinfo, $from, $to, @parents) = @_;
|
2007-06-08 11:27:42 +00:00
|
|
|
my $line;
|
|
|
|
my $result = '';
|
|
|
|
|
|
|
|
$line = $from_line;
|
|
|
|
#assert($line =~ m/^---/) if DEBUG;
|
2007-06-08 11:29:49 +00:00
|
|
|
# no extra formatting for "^--- /dev/null"
|
|
|
|
if (! $diffinfo->{'nparents'}) {
|
|
|
|
# ordinary (single parent) diff
|
|
|
|
if ($line =~ m!^--- "?a/!) {
|
|
|
|
if ($from->{'href'}) {
|
|
|
|
$line = '--- a/' .
|
|
|
|
$cgi->a({-href=>$from->{'href'}, -class=>"path"},
|
|
|
|
esc_path($from->{'file'}));
|
|
|
|
} else {
|
|
|
|
$line = '--- a/' .
|
|
|
|
esc_path($from->{'file'});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$result .= qq!<div class="diff from_file">$line</div>\n!;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
# combined diff (merge commit)
|
|
|
|
for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {
|
|
|
|
if ($from->{'href'}[$i]) {
|
|
|
|
$line = '--- ' .
|
2007-06-08 11:32:44 +00:00
|
|
|
$cgi->a({-href=>href(action=>"blobdiff",
|
|
|
|
hash_parent=>$diffinfo->{'from_id'}[$i],
|
|
|
|
hash_parent_base=>$parents[$i],
|
|
|
|
file_parent=>$from->{'file'}[$i],
|
|
|
|
hash=>$diffinfo->{'to_id'},
|
|
|
|
hash_base=>$hash,
|
|
|
|
file_name=>$to->{'file'}),
|
|
|
|
-class=>"path",
|
|
|
|
-title=>"diff" . ($i+1)},
|
|
|
|
$i+1) .
|
|
|
|
'/' .
|
2007-06-08 11:29:49 +00:00
|
|
|
$cgi->a({-href=>$from->{'href'}[$i], -class=>"path"},
|
|
|
|
esc_path($from->{'file'}[$i]));
|
|
|
|
} else {
|
|
|
|
$line = '--- /dev/null';
|
|
|
|
}
|
|
|
|
$result .= qq!<div class="diff from_file">$line</div>\n!;
|
2007-06-08 11:27:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$line = $to_line;
|
|
|
|
#assert($line =~ m/^\+\+\+/) if DEBUG;
|
|
|
|
# no extra formatting for "^+++ /dev/null"
|
|
|
|
if ($line =~ m!^\+\+\+ "?b/!) {
|
|
|
|
if ($to->{'href'}) {
|
|
|
|
$line = '+++ b/' .
|
|
|
|
$cgi->a({-href=>$to->{'href'}, -class=>"path"},
|
|
|
|
esc_path($to->{'file'}));
|
|
|
|
} else {
|
|
|
|
$line = '+++ b/' .
|
|
|
|
esc_path($to->{'file'});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$result .= qq!<div class="diff to_file">$line</div>\n!;
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2007-06-08 11:33:28 +00:00
|
|
|
# create note for patch simplified by combined diff
|
|
|
|
sub format_diff_cc_simplified {
|
|
|
|
my ($diffinfo, @parents) = @_;
|
|
|
|
my $result = '';
|
|
|
|
|
|
|
|
$result .= "<div class=\"diff header\">" .
|
|
|
|
"diff --cc ";
|
|
|
|
if (!is_deleted($diffinfo)) {
|
|
|
|
$result .= $cgi->a({-href => href(action=>"blob",
|
|
|
|
hash_base=>$hash,
|
|
|
|
hash=>$diffinfo->{'to_id'},
|
|
|
|
file_name=>$diffinfo->{'to_file'}),
|
|
|
|
-class => "path"},
|
|
|
|
esc_path($diffinfo->{'to_file'}));
|
|
|
|
} else {
|
|
|
|
$result .= esc_path($diffinfo->{'to_file'});
|
|
|
|
}
|
|
|
|
$result .= "</div>\n" . # class="diff header"
|
|
|
|
"<div class=\"diff nodifferences\">" .
|
|
|
|
"Simple merge" .
|
|
|
|
"</div>\n"; # class="diff nodifferences"
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2007-06-08 11:27:42 +00:00
|
|
|
# format patch (diff) line (not to be used for diff headers)
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
sub format_diff_line {
|
|
|
|
my $line = shift;
|
2006-11-18 22:35:40 +00:00
|
|
|
my ($from, $to) = @_;
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
my $diff_class = "";
|
|
|
|
|
|
|
|
chomp $line;
|
|
|
|
|
2007-05-06 23:10:05 +00:00
|
|
|
if ($from && $to && ref($from->{'href'}) eq "ARRAY") {
|
|
|
|
# combined diff
|
|
|
|
my $prefix = substr($line, 0, scalar @{$from->{'href'}});
|
|
|
|
if ($line =~ m/^\@{3}/) {
|
|
|
|
$diff_class = " chunk_header";
|
|
|
|
} elsif ($line =~ m/^\\/) {
|
|
|
|
$diff_class = " incomplete";
|
|
|
|
} elsif ($prefix =~ tr/+/+/) {
|
|
|
|
$diff_class = " add";
|
|
|
|
} elsif ($prefix =~ tr/-/-/) {
|
|
|
|
$diff_class = " rem";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
# assume ordinary diff
|
|
|
|
my $char = substr($line, 0, 1);
|
|
|
|
if ($char eq '+') {
|
|
|
|
$diff_class = " add";
|
|
|
|
} elsif ($char eq '-') {
|
|
|
|
$diff_class = " rem";
|
|
|
|
} elsif ($char eq '@') {
|
|
|
|
$diff_class = " chunk_header";
|
|
|
|
} elsif ($char eq "\\") {
|
|
|
|
$diff_class = " incomplete";
|
|
|
|
}
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
|
|
|
$line = untabify($line);
|
2006-11-18 22:35:40 +00:00
|
|
|
if ($from && $to && $line =~ m/^\@{2} /) {
|
|
|
|
my ($from_text, $from_start, $from_lines, $to_text, $to_start, $to_lines, $section) =
|
|
|
|
$line =~ m/^\@{2} (-(\d+)(?:,(\d+))?) (\+(\d+)(?:,(\d+))?) \@{2}(.*)$/;
|
|
|
|
|
|
|
|
$from_lines = 0 unless defined $from_lines;
|
|
|
|
$to_lines = 0 unless defined $to_lines;
|
|
|
|
|
|
|
|
if ($from->{'href'}) {
|
|
|
|
$from_text = $cgi->a({-href=>"$from->{'href'}#l$from_start",
|
|
|
|
-class=>"list"}, $from_text);
|
|
|
|
}
|
|
|
|
if ($to->{'href'}) {
|
|
|
|
$to_text = $cgi->a({-href=>"$to->{'href'}#l$to_start",
|
|
|
|
-class=>"list"}, $to_text);
|
|
|
|
}
|
|
|
|
$line = "<span class=\"chunk_info\">@@ $from_text $to_text @@</span>" .
|
|
|
|
"<span class=\"section\">" . esc_html($section, -nbsp=>1) . "</span>";
|
|
|
|
return "<div class=\"diff$diff_class\">$line</div>\n";
|
2007-05-06 23:10:05 +00:00
|
|
|
} elsif ($from && $to && $line =~ m/^\@{3}/) {
|
|
|
|
my ($prefix, $ranges, $section) = $line =~ m/^(\@+) (.*?) \@+(.*)$/;
|
|
|
|
my (@from_text, @from_start, @from_nlines, $to_text, $to_start, $to_nlines);
|
|
|
|
|
|
|
|
@from_text = split(' ', $ranges);
|
|
|
|
for (my $i = 0; $i < @from_text; ++$i) {
|
|
|
|
($from_start[$i], $from_nlines[$i]) =
|
|
|
|
(split(',', substr($from_text[$i], 1)), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
$to_text = pop @from_text;
|
|
|
|
$to_start = pop @from_start;
|
|
|
|
$to_nlines = pop @from_nlines;
|
|
|
|
|
|
|
|
$line = "<span class=\"chunk_info\">$prefix ";
|
|
|
|
for (my $i = 0; $i < @from_text; ++$i) {
|
|
|
|
if ($from->{'href'}[$i]) {
|
|
|
|
$line .= $cgi->a({-href=>"$from->{'href'}[$i]#l$from_start[$i]",
|
|
|
|
-class=>"list"}, $from_text[$i]);
|
|
|
|
} else {
|
|
|
|
$line .= $from_text[$i];
|
|
|
|
}
|
|
|
|
$line .= " ";
|
|
|
|
}
|
|
|
|
if ($to->{'href'}) {
|
|
|
|
$line .= $cgi->a({-href=>"$to->{'href'}#l$to_start",
|
|
|
|
-class=>"list"}, $to_text);
|
|
|
|
} else {
|
|
|
|
$line .= $to_text;
|
|
|
|
}
|
|
|
|
$line .= " $prefix</span>" .
|
|
|
|
"<span class=\"section\">" . esc_html($section, -nbsp=>1) . "</span>";
|
|
|
|
return "<div class=\"diff$diff_class\">$line</div>\n";
|
2006-11-18 22:35:40 +00:00
|
|
|
}
|
2006-11-01 13:33:21 +00:00
|
|
|
return "<div class=\"diff$diff_class\">" . esc_html($line, -nbsp=>1) . "</div>\n";
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
|
|
|
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
# Generates undef or something like "_snapshot_" or "snapshot (_tbz2_ _zip_)",
|
|
|
|
# linked. Pass the hash of the tree/commit to snapshot.
|
|
|
|
sub format_snapshot_links {
|
|
|
|
my ($hash) = @_;
|
|
|
|
my $num_fmts = @snapshot_fmts;
|
|
|
|
if ($num_fmts > 1) {
|
|
|
|
# A parenthesized list of links bearing format names.
|
gitweb: Fix support for legacy gitweb config for snapshots
Earlier commit which cleaned up snapshot support and introduced
support for multiple snapshot formats changed the format of
$feature{'snapshot'}{'default'} (gitweb configuration) and
gitweb.snapshot configuration variable (repository configuration).
It supported old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip'
and tried to support, but failed to do that, old values of
$feature{'snapshot'}{'default'}; at least those corresponding to
old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
This commit moves legacy configuration support out of feature_snapshot
subroutine to separate filter_snapshot_fmts subroutine. The
filter_snapshot_fmts is used on result on result of
gitweb_check_feature('snapshot'). This way feature_snapshot deals
_only_ with repository config.
As a byproduct you can now use 'gzip' and 'bzip2' as aliases to 'tgz'
and 'tbz2' also in $feature{'snapshot'}{'default'}, not only in
gitweb.snapshot.
While at it do some whitespace cleanup: use tabs for indent, but
spaces for align.
Noticed-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Tested-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-22 21:41:20 +00:00
|
|
|
# e.g. "snapshot (_tar.gz_ _zip_)"
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
return "snapshot (" . join(' ', map
|
|
|
|
$cgi->a({
|
|
|
|
-href => href(
|
|
|
|
action=>"snapshot",
|
|
|
|
hash=>$hash,
|
|
|
|
snapshot_format=>$_
|
|
|
|
)
|
|
|
|
}, $known_snapshot_formats{$_}{'display'})
|
|
|
|
, @snapshot_fmts) . ")";
|
|
|
|
} elsif ($num_fmts == 1) {
|
|
|
|
# A single "snapshot" link whose tooltip bears the format name.
|
gitweb: Fix support for legacy gitweb config for snapshots
Earlier commit which cleaned up snapshot support and introduced
support for multiple snapshot formats changed the format of
$feature{'snapshot'}{'default'} (gitweb configuration) and
gitweb.snapshot configuration variable (repository configuration).
It supported old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip'
and tried to support, but failed to do that, old values of
$feature{'snapshot'}{'default'}; at least those corresponding to
old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
This commit moves legacy configuration support out of feature_snapshot
subroutine to separate filter_snapshot_fmts subroutine. The
filter_snapshot_fmts is used on result on result of
gitweb_check_feature('snapshot'). This way feature_snapshot deals
_only_ with repository config.
As a byproduct you can now use 'gzip' and 'bzip2' as aliases to 'tgz'
and 'tbz2' also in $feature{'snapshot'}{'default'}, not only in
gitweb.snapshot.
While at it do some whitespace cleanup: use tabs for indent, but
spaces for align.
Noticed-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Tested-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-22 21:41:20 +00:00
|
|
|
# i.e. "_snapshot_"
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
my ($fmt) = @snapshot_fmts;
|
gitweb: Fix support for legacy gitweb config for snapshots
Earlier commit which cleaned up snapshot support and introduced
support for multiple snapshot formats changed the format of
$feature{'snapshot'}{'default'} (gitweb configuration) and
gitweb.snapshot configuration variable (repository configuration).
It supported old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip'
and tried to support, but failed to do that, old values of
$feature{'snapshot'}{'default'}; at least those corresponding to
old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
This commit moves legacy configuration support out of feature_snapshot
subroutine to separate filter_snapshot_fmts subroutine. The
filter_snapshot_fmts is used on result on result of
gitweb_check_feature('snapshot'). This way feature_snapshot deals
_only_ with repository config.
As a byproduct you can now use 'gzip' and 'bzip2' as aliases to 'tgz'
and 'tbz2' also in $feature{'snapshot'}{'default'}, not only in
gitweb.snapshot.
While at it do some whitespace cleanup: use tabs for indent, but
spaces for align.
Noticed-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Tested-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-22 21:41:20 +00:00
|
|
|
return
|
|
|
|
$cgi->a({
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
-href => href(
|
|
|
|
action=>"snapshot",
|
|
|
|
hash=>$hash,
|
|
|
|
snapshot_format=>$fmt
|
|
|
|
),
|
|
|
|
-title => "in format: $known_snapshot_formats{$fmt}{'display'}"
|
|
|
|
}, "snapshot");
|
|
|
|
} else { # $num_fmts == 0
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
gitweb: Use feed link according to current view
Michael G. Noll said in comments to the "Switching my code repository from
Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My
digital moleskine" blog, that one of the things he is missing in gitweb
from SVN::Web is an RSS feed with news/information of the current view
(including RSS feed for single file or directory).
This is not exactly true, as since refactoring feed generation in af6feeb
(gitweb: Refactor feed generation, make output prettier, add Atom feed,
2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a
given branch, history limited to a given directory, or history of a given
file. Nevertheless this required handcrafting the URL to get wanted RSS
feed.
This commit makes gitweb select feed links in the HTML header and in
page footer depending on current view (action). It is more elaborate,
and I guess more correct, than simple patch adding $hash ('h')
parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot
Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash
is specified in the current request
Message-ID: <ae63f8b50803211138y6355fd11pa64cda50a1f53011@mail.gmail.com>
If $hash ('h') or $hash_base ('hb') parameter is a branch name
(i.e. it starts with 'refs/heads/'; all generated URLs use this form
to discriminate between tags and heads), it is used in feed URLs; if
$file_name ('f') is defined, it is used in feed URLs. Feed title is
set according to the kind of web feed: it is either 'log' for generic
feed, 'log of <branch>', 'history of <filename>' for generic history
(using implicit or explicit HEAD, i.e. current branch) or 'history of
<filename> on <branch>'.
There are special cases: 'heads' and 'forks' views should use OPML
providing list of available feeds; 'tags' probably also should use
OPML; there is no web feed equivalent to 'search' view. Currently all
those cases fallback to (show) default feed. Such feed link uses
"generic" class, and is shown in slightly lighter color for
distinction.
Currently feed can have but one starting point, and does not support
negative (exclude) commit arguments. Therefore for now for *diff
views it is chosen that feed follow the "to" part: to-name, to-commit
for 'blobdiff', 'treediff' and 'commitdiff' views.
Generating parameters for href() for feed link was separated
(refactored) into get_feed_info() subroutine.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-20 20:09:48 +00:00
|
|
|
## ......................................................................
|
|
|
|
## functions returning values to be passed, perhaps after some
|
|
|
|
## transformation, to other functions; e.g. returning arguments to href()
|
|
|
|
|
|
|
|
# returns hash to be passed to href to generate gitweb URL
|
|
|
|
# in -title key it returns description of link
|
|
|
|
sub get_feed_info {
|
|
|
|
my $format = shift || 'Atom';
|
|
|
|
my %res = (action => lc($format));
|
|
|
|
|
|
|
|
# feed links are possible only for project views
|
|
|
|
return unless (defined $project);
|
|
|
|
# some views should link to OPML, or to generic project feed,
|
|
|
|
# or don't have specific feed yet (so they should use generic)
|
|
|
|
return if ($action =~ /^(?:tags|heads|forks|tag|search)$/x);
|
|
|
|
|
|
|
|
my $branch;
|
|
|
|
# branches refs uses 'refs/heads/' prefix (fullname) to differentiate
|
|
|
|
# from tag links; this also makes possible to detect branch links
|
|
|
|
if ((defined $hash_base && $hash_base =~ m!^refs/heads/(.*)$!) ||
|
|
|
|
(defined $hash && $hash =~ m!^refs/heads/(.*)$!)) {
|
|
|
|
$branch = $1;
|
|
|
|
}
|
|
|
|
# find log type for feed description (title)
|
|
|
|
my $type = 'log';
|
|
|
|
if (defined $file_name) {
|
|
|
|
$type = "history of $file_name";
|
|
|
|
$type .= "/" if ($action eq 'tree');
|
|
|
|
$type .= " on '$branch'" if (defined $branch);
|
|
|
|
} else {
|
|
|
|
$type = "log of $branch" if (defined $branch);
|
|
|
|
}
|
|
|
|
|
|
|
|
$res{-title} = $type;
|
|
|
|
$res{'hash'} = (defined $branch ? "refs/heads/$branch" : undef);
|
|
|
|
$res{'file_name'} = $file_name;
|
|
|
|
|
|
|
|
return %res;
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ----------------------------------------------------------------------
|
|
|
|
## git utility subroutines, invoking git commands
|
2005-08-07 18:21:46 +00:00
|
|
|
|
2006-08-28 15:49:58 +00:00
|
|
|
# returns path to the core git executable and the --git-dir parameter as list
|
|
|
|
sub git_cmd {
|
2009-09-01 11:39:16 +00:00
|
|
|
$number_of_git_cmds++;
|
2006-08-28 15:49:58 +00:00
|
|
|
return $GIT, '--git-dir='.$git_dir;
|
|
|
|
}
|
|
|
|
|
2008-06-17 21:46:35 +00:00
|
|
|
# quote the given arguments for passing them to the shell
|
|
|
|
# quote_command("command", "arg 1", "arg with ' and ! characters")
|
|
|
|
# => "'command' 'arg 1' 'arg with '\'' and '\!' characters'"
|
|
|
|
# Try to avoid using this function wherever possible.
|
|
|
|
sub quote_command {
|
|
|
|
return join(' ',
|
2009-05-10 00:40:37 +00:00
|
|
|
map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ );
|
2006-08-28 15:49:58 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# get HEAD ref of given project as hash
|
2006-08-14 00:05:47 +00:00
|
|
|
sub git_get_head_hash {
|
2009-11-07 15:13:29 +00:00
|
|
|
return git_get_full_hash(shift, 'HEAD');
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_get_full_hash {
|
|
|
|
return git_get_hash(@_);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_get_short_hash {
|
|
|
|
return git_get_hash(@_, '--short=7');
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_get_hash {
|
|
|
|
my ($project, $hash, @options) = @_;
|
2006-08-28 15:49:58 +00:00
|
|
|
my $o_git_dir = $git_dir;
|
2006-01-09 12:13:39 +00:00
|
|
|
my $retval = undef;
|
2006-08-28 15:49:58 +00:00
|
|
|
$git_dir = "$projectroot/$project";
|
2009-11-07 15:13:29 +00:00
|
|
|
if (open my $fd, '-|', git_cmd(), 'rev-parse',
|
|
|
|
'--verify', '-q', @options, $hash) {
|
|
|
|
$retval = <$fd>;
|
|
|
|
chomp $retval if defined $retval;
|
2006-01-09 12:13:39 +00:00
|
|
|
close $fd;
|
|
|
|
}
|
2006-08-28 15:49:58 +00:00
|
|
|
if (defined $o_git_dir) {
|
|
|
|
$git_dir = $o_git_dir;
|
2006-01-17 02:50:20 +00:00
|
|
|
}
|
2006-01-09 12:13:39 +00:00
|
|
|
return $retval;
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
# get type of given object
|
|
|
|
sub git_get_type {
|
|
|
|
my $hash = shift;
|
|
|
|
|
2006-08-28 15:49:58 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "cat-file", '-t', $hash or return;
|
2006-07-31 19:22:15 +00:00
|
|
|
my $type = <$fd>;
|
|
|
|
close $fd or return;
|
|
|
|
chomp $type;
|
|
|
|
return $type;
|
|
|
|
}
|
|
|
|
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
# repository configuration
|
|
|
|
our $config_file = '';
|
|
|
|
our %config;
|
|
|
|
|
|
|
|
# store multiple values for single key as anonymous array reference
|
|
|
|
# single values stored directly in the hash, not as [ <value> ]
|
|
|
|
sub hash_set_multi {
|
|
|
|
my ($hash, $key, $value) = @_;
|
|
|
|
|
|
|
|
if (!exists $hash->{$key}) {
|
|
|
|
$hash->{$key} = $value;
|
|
|
|
} elsif (!ref $hash->{$key}) {
|
|
|
|
$hash->{$key} = [ $hash->{$key}, $value ];
|
|
|
|
} else {
|
|
|
|
push @{$hash->{$key}}, $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# return hash of git project configuration
|
|
|
|
# optionally limited to some section, e.g. 'gitweb'
|
|
|
|
sub git_parse_project_config {
|
|
|
|
my $section_regexp = shift;
|
|
|
|
my %config;
|
|
|
|
|
|
|
|
local $/ = "\0";
|
|
|
|
|
|
|
|
open my $fh, "-|", git_cmd(), "config", '-z', '-l',
|
|
|
|
or return;
|
|
|
|
|
|
|
|
while (my $keyval = <$fh>) {
|
|
|
|
chomp $keyval;
|
|
|
|
my ($key, $value) = split(/\n/, $keyval, 2);
|
|
|
|
|
|
|
|
hash_set_multi(\%config, $key, $value)
|
|
|
|
if (!defined $section_regexp || $key =~ /^(?:$section_regexp)\./o);
|
|
|
|
}
|
|
|
|
close $fh;
|
|
|
|
|
|
|
|
return %config;
|
|
|
|
}
|
|
|
|
|
2009-02-18 13:09:41 +00:00
|
|
|
# convert config value to boolean: 'true' or 'false'
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
# no value, number > 0, 'true' and 'yes' values are true
|
|
|
|
# rest of values are treated as false (never as error)
|
|
|
|
sub config_to_bool {
|
|
|
|
my $val = shift;
|
|
|
|
|
2009-02-18 13:09:41 +00:00
|
|
|
return 1 if !defined $val; # section.key
|
|
|
|
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
# strip leading and trailing whitespace
|
|
|
|
$val =~ s/^\s+//;
|
|
|
|
$val =~ s/\s+$//;
|
|
|
|
|
2009-02-18 13:09:41 +00:00
|
|
|
return (($val =~ /^\d+$/ && $val) || # section.key = 1
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
($val =~ /^(?:true|yes)$/i)); # section.key = true
|
|
|
|
}
|
|
|
|
|
|
|
|
# convert config value to simple decimal number
|
|
|
|
# an optional value suffix of 'k', 'm', or 'g' will cause the value
|
|
|
|
# to be multiplied by 1024, 1048576, or 1073741824
|
|
|
|
sub config_to_int {
|
|
|
|
my $val = shift;
|
|
|
|
|
|
|
|
# strip leading and trailing whitespace
|
|
|
|
$val =~ s/^\s+//;
|
|
|
|
$val =~ s/\s+$//;
|
|
|
|
|
|
|
|
if (my ($num, $unit) = ($val =~ /^([0-9]*)([kmg])$/i)) {
|
|
|
|
$unit = lc($unit);
|
|
|
|
# unknown unit is treated as 1
|
|
|
|
return $num * ($unit eq 'g' ? 1073741824 :
|
|
|
|
$unit eq 'm' ? 1048576 :
|
|
|
|
$unit eq 'k' ? 1024 : 1);
|
|
|
|
}
|
|
|
|
return $val;
|
|
|
|
}
|
|
|
|
|
|
|
|
# convert config value to array reference, if needed
|
|
|
|
sub config_to_multi {
|
|
|
|
my $val = shift;
|
|
|
|
|
2007-12-20 09:48:09 +00:00
|
|
|
return ref($val) ? $val : (defined($val) ? [ $val ] : []);
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub git_get_project_config {
|
2006-08-20 06:23:04 +00:00
|
|
|
my ($key, $type) = @_;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2010-03-27 19:26:59 +00:00
|
|
|
return unless defined $git_dir;
|
gitweb: Fix project-specific feature override behavior
This commit fixes a bug in processing project-specific override in
a situation when there is no project, e.g. for the projects list page.
When 'snapshot' feature had project specific config override enabled
by putting
$feature{'snapshot'}{'override'} = 1;
(or equivalent) in $GITWEB_CONFIG, and when viewing toplevel gitweb
page, which means the projects list page (to be more exact this
happens for any project-less action), gitweb would put the following
Perl warnings in error log:
gitweb.cgi: Use of uninitialized value $git_dir in concatenation (.) or string at gitweb.cgi line 2065.
fatal: error processing config file(s)
gitweb.cgi: Use of uninitialized value $git_dir in concatenation (.) or string at gitweb.cgi line 2221.
gitweb.cgi: Use of uninitialized value $git_dir in concatenation (.) or string at gitweb.cgi line 2218.
The problem is in the following fragment of code:
# path to the current git repository
our $git_dir;
$git_dir = "$projectroot/$project" if $project;
# list of supported snapshot formats
our @snapshot_fmts = gitweb_get_feature('snapshot');
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
For the toplevel gitweb page, which is the list of projects, $project is not
defined, therefore neither is $git_dir. gitweb_get_feature() subroutine
calls git_get_project_config() if project specific override is turned
on... but we don't have project here.
Those errors mentioned above occur in the following fragment of code in
git_get_project_config():
# get config
if (!defined $config_file ||
$config_file ne "$git_dir/config") {
%config = git_parse_project_config('gitweb');
$config_file = "$git_dir/config";
}
git_parse_project_config() calls git_cmd() which has '--git-dir='.$git_dir
There are (at least) three possible solutions:
1. Harden gitweb_get_feature() so that it doesn't call
git_get_project_config() if $project (and therefore $git_dir) is not
defined; there is no project for project specific config.
2. Harden git_get_project_config() like you did in your fix, returning early
if $git_dir is not defined.
3. Harden git_cmd() so that it doesn't add "--git-dir=$git_dir" if $git_dir
is not defined, and change git_get_project_config() so that it doesn't
even try to access $git_dir if it is not defined.
This commit implements both 1.) and 2.), i.e. gitweb_get_feature() doesn't
call project-specific override if $git_dir is not defined (if there is no
project), and git_get_project_config() returns early if $git_dir is not
defined.
Add a test for this bug to t/t9500-gitweb-standalone-no-errors.sh test.
Reported-by: Eli Barzilay <eli@barzilay.org>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-03-01 21:51:34 +00:00
|
|
|
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
# key sanity check
|
2006-07-31 19:22:15 +00:00
|
|
|
return unless ($key);
|
|
|
|
$key =~ s/^gitweb\.//;
|
|
|
|
return if ($key =~ m/\W/);
|
|
|
|
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
# type sanity check
|
|
|
|
if (defined $type) {
|
|
|
|
$type =~ s/^--//;
|
|
|
|
$type = undef
|
|
|
|
unless ($type eq 'bool' || $type eq 'int');
|
|
|
|
}
|
|
|
|
|
|
|
|
# get config
|
|
|
|
if (!defined $config_file ||
|
|
|
|
$config_file ne "$git_dir/config") {
|
|
|
|
%config = git_parse_project_config('gitweb');
|
|
|
|
$config_file = "$git_dir/config";
|
|
|
|
}
|
|
|
|
|
2009-02-18 13:09:41 +00:00
|
|
|
# check if config variable (key) exists
|
|
|
|
return unless exists $config{"gitweb.$key"};
|
|
|
|
|
gitweb: Read repo config using 'git config -z -l'
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-02 23:41:19 +00:00
|
|
|
# ensure given type
|
|
|
|
if (!defined $type) {
|
|
|
|
return $config{"gitweb.$key"};
|
|
|
|
} elsif ($type eq 'bool') {
|
|
|
|
# backward compatibility: 'git config --bool' returns true/false
|
|
|
|
return config_to_bool($config{"gitweb.$key"}) ? 'true' : 'false';
|
|
|
|
} elsif ($type eq 'int') {
|
|
|
|
return config_to_int($config{"gitweb.$key"});
|
|
|
|
}
|
|
|
|
return $config{"gitweb.$key"};
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# get hash of given path at given ref
|
|
|
|
sub git_get_hash_by_path {
|
|
|
|
my $base = shift;
|
|
|
|
my $path = shift || return undef;
|
2006-09-21 16:09:12 +00:00
|
|
|
my $type = shift;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2006-09-25 23:54:24 +00:00
|
|
|
$path =~ s,/+$,,;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2006-08-28 15:49:58 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "ls-tree", $base, "--", $path
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-ls-tree failed");
|
2006-07-31 19:22:15 +00:00
|
|
|
my $line = <$fd>;
|
|
|
|
close $fd or return undef;
|
|
|
|
|
2007-05-12 19:16:34 +00:00
|
|
|
if (!defined $line) {
|
|
|
|
# there is no tree or hash given by $path at $base
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
|
2006-10-30 21:25:11 +00:00
|
|
|
$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/;
|
2006-09-21 16:09:12 +00:00
|
|
|
if (defined $type && $type ne $2) {
|
|
|
|
# type doesn't match
|
|
|
|
return undef;
|
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
return $3;
|
|
|
|
}
|
|
|
|
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
# get path of entry with given hash at given tree-ish (ref)
|
|
|
|
# used to get 'from' filename for combined diff (merge commit) for renames
|
|
|
|
sub git_get_path_by_hash {
|
|
|
|
my $base = shift || return;
|
|
|
|
my $hash = shift || return;
|
|
|
|
|
|
|
|
local $/ = "\0";
|
|
|
|
|
|
|
|
open my $fd, "-|", git_cmd(), "ls-tree", '-r', '-t', '-z', $base
|
|
|
|
or return undef;
|
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
|
|
|
|
#'040000 tree 595596a6a9117ddba9fe379b6b012b558bac8423 gitweb'
|
|
|
|
#'100644 blob e02e90f0429be0d2a69b76571101f20b8f75530f gitweb/README'
|
|
|
|
if ($line =~ m/(?:[0-9]+) (?:.+) $hash\t(.+)$/) {
|
|
|
|
close $fd;
|
|
|
|
return $1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $fd;
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ......................................................................
|
|
|
|
## git utility functions, directly accessing git repository
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub git_get_project_description {
|
2005-08-07 18:21:04 +00:00
|
|
|
my $path = shift;
|
2005-08-07 18:21:23 +00:00
|
|
|
|
2007-11-02 23:41:20 +00:00
|
|
|
$git_dir = "$projectroot/$path";
|
2009-05-10 00:38:34 +00:00
|
|
|
open my $fd, '<', "$git_dir/description"
|
2007-11-02 23:41:20 +00:00
|
|
|
or return git_get_project_config('description');
|
2005-08-07 18:21:04 +00:00
|
|
|
my $descr = <$fd>;
|
|
|
|
close $fd;
|
2007-05-17 04:04:16 +00:00
|
|
|
if (defined $descr) {
|
|
|
|
chomp $descr;
|
|
|
|
}
|
2005-08-07 18:21:04 +00:00
|
|
|
return $descr;
|
2005-08-07 18:02:47 +00:00
|
|
|
}
|
|
|
|
|
2008-10-02 15:13:02 +00:00
|
|
|
sub git_get_project_ctags {
|
|
|
|
my $path = shift;
|
|
|
|
my $ctags = {};
|
|
|
|
|
|
|
|
$git_dir = "$projectroot/$path";
|
2009-05-11 01:21:06 +00:00
|
|
|
opendir my $dh, "$git_dir/ctags"
|
|
|
|
or return $ctags;
|
|
|
|
foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir($dh)) {
|
2009-05-10 00:38:34 +00:00
|
|
|
open my $ct, '<', $_ or next;
|
2009-05-11 01:21:06 +00:00
|
|
|
my $val = <$ct>;
|
2008-10-02 15:13:02 +00:00
|
|
|
chomp $val;
|
2009-05-11 01:21:06 +00:00
|
|
|
close $ct;
|
2008-10-02 15:13:02 +00:00
|
|
|
my $ctag = $_; $ctag =~ s#.*/##;
|
|
|
|
$ctags->{$ctag} = $val;
|
|
|
|
}
|
2009-05-11 01:21:06 +00:00
|
|
|
closedir $dh;
|
2008-10-02 15:13:02 +00:00
|
|
|
$ctags;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_populate_project_tagcloud {
|
|
|
|
my $ctags = shift;
|
|
|
|
|
|
|
|
# First, merge different-cased tags; tags vote on casing
|
|
|
|
my %ctags_lc;
|
|
|
|
foreach (keys %$ctags) {
|
|
|
|
$ctags_lc{lc $_}->{count} += $ctags->{$_};
|
|
|
|
if (not $ctags_lc{lc $_}->{topcount}
|
|
|
|
or $ctags_lc{lc $_}->{topcount} < $ctags->{$_}) {
|
|
|
|
$ctags_lc{lc $_}->{topcount} = $ctags->{$_};
|
|
|
|
$ctags_lc{lc $_}->{topname} = $_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
my $cloud;
|
|
|
|
if (eval { require HTML::TagCloud; 1; }) {
|
|
|
|
$cloud = HTML::TagCloud->new;
|
|
|
|
foreach (sort keys %ctags_lc) {
|
|
|
|
# Pad the title with spaces so that the cloud looks
|
|
|
|
# less crammed.
|
|
|
|
my $title = $ctags_lc{$_}->{topname};
|
|
|
|
$title =~ s/ / /g;
|
|
|
|
$title =~ s/^/ /g;
|
|
|
|
$title =~ s/$/ /g;
|
|
|
|
$cloud->add($title, $home_link."?by_tag=".$_, $ctags_lc{$_}->{count});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$cloud = \%ctags_lc;
|
|
|
|
}
|
|
|
|
$cloud;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_show_project_tagcloud {
|
|
|
|
my ($cloud, $count) = @_;
|
|
|
|
print STDERR ref($cloud)."..\n";
|
|
|
|
if (ref $cloud eq 'HTML::TagCloud') {
|
|
|
|
return $cloud->html_and_css($count);
|
|
|
|
} else {
|
|
|
|
my @tags = sort { $cloud->{$a}->{count} <=> $cloud->{$b}->{count} } keys %$cloud;
|
|
|
|
return '<p align="center">' . join (', ', map {
|
2010-12-14 23:34:01 +00:00
|
|
|
$cgi->a({-href=>"$home_link?by_tag=$_"}, $cloud->{$_}->{topname})
|
2008-10-02 15:13:02 +00:00
|
|
|
} splice(@tags, 0, $count)) . '</p>';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-16 12:50:34 +00:00
|
|
|
sub git_get_project_url_list {
|
|
|
|
my $path = shift;
|
|
|
|
|
2007-11-02 23:41:20 +00:00
|
|
|
$git_dir = "$projectroot/$path";
|
2009-05-10 00:38:34 +00:00
|
|
|
open my $fd, '<', "$git_dir/cloneurl"
|
2007-11-02 23:41:20 +00:00
|
|
|
or return wantarray ?
|
|
|
|
@{ config_to_multi(git_get_project_config('url')) } :
|
|
|
|
config_to_multi(git_get_project_config('url'));
|
2006-08-16 12:50:34 +00:00
|
|
|
my @git_project_url_list = map { chomp; $_ } <$fd>;
|
|
|
|
close $fd;
|
|
|
|
|
|
|
|
return wantarray ? @git_project_url_list : \@git_project_url_list;
|
|
|
|
}
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub git_get_projects_list {
|
2006-10-24 03:33:17 +00:00
|
|
|
my ($filter) = @_;
|
2006-07-31 19:22:15 +00:00
|
|
|
my @list;
|
|
|
|
|
2006-10-24 03:33:17 +00:00
|
|
|
$filter ||= '';
|
|
|
|
$filter =~ s/\.git$//;
|
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
my $check_forks = gitweb_check_feature('forks');
|
2007-04-06 21:58:11 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
if (-d $projects_list) {
|
|
|
|
# search in directory
|
2006-10-24 03:33:17 +00:00
|
|
|
my $dir = $projects_list . ($filter ? "/$filter" : '');
|
2006-11-03 05:11:45 +00:00
|
|
|
# remove the trailing "/"
|
|
|
|
$dir =~ s!/+$!!;
|
2006-09-14 20:18:59 +00:00
|
|
|
my $pfxlen = length("$dir");
|
2007-10-17 03:45:25 +00:00
|
|
|
my $pfxdepth = ($dir =~ tr!/!!);
|
2006-09-14 20:18:59 +00:00
|
|
|
|
|
|
|
File::Find::find({
|
|
|
|
follow_fast => 1, # follow symbolic links
|
2007-07-27 08:23:03 +00:00
|
|
|
follow_skip => 2, # ignore duplicates
|
2006-09-14 20:18:59 +00:00
|
|
|
dangling_symlinks => 0, # ignore dangling symlinks, silently
|
|
|
|
wanted => sub {
|
2010-04-30 16:30:31 +00:00
|
|
|
# global variables
|
|
|
|
our $project_maxdepth;
|
|
|
|
our $projectroot;
|
2006-09-14 20:18:59 +00:00
|
|
|
# skip project-list toplevel, if we get it.
|
|
|
|
return if (m!^[/.]$!);
|
|
|
|
# only directories can be git repositories
|
|
|
|
return unless (-d $_);
|
2007-10-17 03:45:25 +00:00
|
|
|
# don't traverse too deep (Find is super slow on os x)
|
|
|
|
if (($File::Find::name =~ tr!/!!) - $pfxdepth > $project_maxdepth) {
|
|
|
|
$File::Find::prune = 1;
|
|
|
|
return;
|
|
|
|
}
|
2006-09-14 20:18:59 +00:00
|
|
|
|
|
|
|
my $subdir = substr($File::Find::name, $pfxlen + 1);
|
|
|
|
# we check related file in $projectroot
|
2008-12-27 09:39:31 +00:00
|
|
|
my $path = ($filter ? "$filter/" : '') . $subdir;
|
|
|
|
if (check_export_ok("$projectroot/$path")) {
|
|
|
|
push @list, { path => $path };
|
2006-09-14 20:18:59 +00:00
|
|
|
$File::Find::prune = 1;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}, "$dir");
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
} elsif (-f $projects_list) {
|
|
|
|
# read from file(url-encoded):
|
|
|
|
# 'git%2Fgit.git Linus+Torvalds'
|
|
|
|
# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'
|
|
|
|
# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'
|
2007-04-06 21:58:11 +00:00
|
|
|
my %paths;
|
2009-05-10 00:38:34 +00:00
|
|
|
open my $fd, '<', $projects_list or return;
|
2007-04-06 21:58:11 +00:00
|
|
|
PROJECT:
|
2006-07-31 19:22:15 +00:00
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
my ($path, $owner) = split ' ', $line;
|
|
|
|
$path = unescape($path);
|
|
|
|
$owner = unescape($owner);
|
|
|
|
if (!defined $path) {
|
|
|
|
next;
|
|
|
|
}
|
2006-11-08 06:37:17 +00:00
|
|
|
if ($filter ne '') {
|
|
|
|
# looking for forks;
|
|
|
|
my $pfx = substr($path, 0, length($filter));
|
|
|
|
if ($pfx ne $filter) {
|
2007-04-06 21:58:11 +00:00
|
|
|
next PROJECT;
|
2006-11-08 06:37:17 +00:00
|
|
|
}
|
|
|
|
my $sfx = substr($path, length($filter));
|
|
|
|
if ($sfx !~ /^\/.*\.git$/) {
|
2007-04-06 21:58:11 +00:00
|
|
|
next PROJECT;
|
|
|
|
}
|
|
|
|
} elsif ($check_forks) {
|
|
|
|
PATH:
|
|
|
|
foreach my $filter (keys %paths) {
|
|
|
|
# looking for forks;
|
|
|
|
my $pfx = substr($path, 0, length($filter));
|
|
|
|
if ($pfx ne $filter) {
|
|
|
|
next PATH;
|
|
|
|
}
|
|
|
|
my $sfx = substr($path, length($filter));
|
|
|
|
if ($sfx !~ /^\/.*\.git$/) {
|
|
|
|
next PATH;
|
|
|
|
}
|
|
|
|
# is a fork, don't include it in
|
|
|
|
# the list
|
|
|
|
next PROJECT;
|
2006-11-08 06:37:17 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-03 09:30:47 +00:00
|
|
|
if (check_export_ok("$projectroot/$path")) {
|
2006-07-31 19:22:15 +00:00
|
|
|
my $pr = {
|
|
|
|
path => $path,
|
2007-06-03 15:42:44 +00:00
|
|
|
owner => to_utf8($owner),
|
2006-07-31 19:22:15 +00:00
|
|
|
};
|
2007-04-06 21:58:11 +00:00
|
|
|
push @list, $pr;
|
|
|
|
(my $forks_path = $path) =~ s/\.git$//;
|
|
|
|
$paths{$forks_path}++;
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
close $fd;
|
|
|
|
}
|
|
|
|
return @list;
|
|
|
|
}
|
|
|
|
|
2007-07-04 05:10:42 +00:00
|
|
|
our $gitweb_project_owner = undef;
|
|
|
|
sub git_get_project_list_from_file {
|
2006-08-14 00:10:06 +00:00
|
|
|
|
2007-07-04 05:10:42 +00:00
|
|
|
return if (defined $gitweb_project_owner);
|
2006-08-14 00:10:06 +00:00
|
|
|
|
2007-07-04 05:10:42 +00:00
|
|
|
$gitweb_project_owner = {};
|
2006-08-14 00:10:06 +00:00
|
|
|
# read from file (url-encoded):
|
|
|
|
# 'git%2Fgit.git Linus+Torvalds'
|
|
|
|
# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'
|
|
|
|
# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'
|
|
|
|
if (-f $projects_list) {
|
2009-05-10 00:38:34 +00:00
|
|
|
open(my $fd, '<', $projects_list);
|
2006-08-14 00:10:06 +00:00
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
my ($pr, $ow) = split ' ', $line;
|
|
|
|
$pr = unescape($pr);
|
|
|
|
$ow = unescape($ow);
|
2007-07-04 05:10:42 +00:00
|
|
|
$gitweb_project_owner->{$pr} = to_utf8($ow);
|
2006-08-14 00:10:06 +00:00
|
|
|
}
|
|
|
|
close $fd;
|
|
|
|
}
|
2007-07-04 05:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sub git_get_project_owner {
|
|
|
|
my $project = shift;
|
|
|
|
my $owner;
|
|
|
|
|
|
|
|
return undef unless $project;
|
2008-02-08 16:38:04 +00:00
|
|
|
$git_dir = "$projectroot/$project";
|
2007-07-04 05:10:42 +00:00
|
|
|
|
|
|
|
if (!defined $gitweb_project_owner) {
|
|
|
|
git_get_project_list_from_file();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exists $gitweb_project_owner->{$project}) {
|
|
|
|
$owner = $gitweb_project_owner->{$project};
|
|
|
|
}
|
2008-02-08 16:38:04 +00:00
|
|
|
if (!defined $owner){
|
|
|
|
$owner = git_get_project_config('owner');
|
|
|
|
}
|
2006-08-14 00:10:06 +00:00
|
|
|
if (!defined $owner) {
|
2008-02-08 16:38:04 +00:00
|
|
|
$owner = get_file_owner("$git_dir");
|
2006-08-14 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $owner;
|
|
|
|
}
|
|
|
|
|
2006-10-28 17:43:40 +00:00
|
|
|
sub git_get_last_activity {
|
|
|
|
my ($path) = @_;
|
|
|
|
my $fd;
|
|
|
|
|
|
|
|
$git_dir = "$projectroot/$path";
|
|
|
|
open($fd, "-|", git_cmd(), 'for-each-ref',
|
2006-12-22 19:38:13 +00:00
|
|
|
'--format=%(committer)',
|
2006-10-28 17:43:40 +00:00
|
|
|
'--sort=-committerdate',
|
2006-12-22 19:38:13 +00:00
|
|
|
'--count=1',
|
2006-10-28 17:43:40 +00:00
|
|
|
'refs/heads') or return;
|
|
|
|
my $most_recent = <$fd>;
|
|
|
|
close $fd or return;
|
2007-05-13 10:39:22 +00:00
|
|
|
if (defined $most_recent &&
|
|
|
|
$most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
|
2006-10-28 17:43:40 +00:00
|
|
|
my $timestamp = $1;
|
|
|
|
my $age = time - $timestamp;
|
|
|
|
return ($age, age_string($age));
|
|
|
|
}
|
2007-06-28 22:15:22 +00:00
|
|
|
return (undef, undef);
|
2006-10-28 17:43:40 +00:00
|
|
|
}
|
|
|
|
|
2010-11-11 12:26:17 +00:00
|
|
|
# Implementation note: when a single remote is wanted, we cannot use 'git
|
|
|
|
# remote show -n' because that command always work (assuming it's a remote URL
|
|
|
|
# if it's not defined), and we cannot use 'git remote show' because that would
|
|
|
|
# try to make a network roundtrip. So the only way to find if that particular
|
|
|
|
# remote is defined is to walk the list provided by 'git remote -v' and stop if
|
|
|
|
# and when we find what we want.
|
|
|
|
sub git_get_remotes_list {
|
|
|
|
my $wanted = shift;
|
|
|
|
my %remotes = ();
|
|
|
|
|
|
|
|
open my $fd, '-|' , git_cmd(), 'remote', '-v';
|
|
|
|
return unless $fd;
|
|
|
|
while (my $remote = <$fd>) {
|
|
|
|
chomp $remote;
|
|
|
|
$remote =~ s!\t(.*?)\s+\((\w+)\)$!!;
|
|
|
|
next if $wanted and not $remote eq $wanted;
|
|
|
|
my ($url, $key) = ($1, $2);
|
|
|
|
|
|
|
|
$remotes{$remote} ||= { 'heads' => () };
|
|
|
|
$remotes{$remote}{$key} = $url;
|
|
|
|
}
|
|
|
|
close $fd or return;
|
|
|
|
return wantarray ? %remotes : \%remotes;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Takes a hash of remotes as first parameter and fills it by adding the
|
|
|
|
# available remote heads for each of the indicated remotes.
|
|
|
|
sub fill_remote_heads {
|
|
|
|
my $remotes = shift;
|
|
|
|
my @heads = map { "remotes/$_" } keys %$remotes;
|
|
|
|
my @remoteheads = git_get_heads_list(undef, @heads);
|
|
|
|
foreach my $remote (keys %$remotes) {
|
|
|
|
$remotes->{$remote}{'heads'} = [ grep {
|
|
|
|
$_->{'name'} =~ s!^$remote/!!
|
|
|
|
} @remoteheads ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub git_get_references {
|
2006-07-31 19:22:15 +00:00
|
|
|
my $type = shift || "";
|
|
|
|
my %refs;
|
2006-11-25 10:32:08 +00:00
|
|
|
# 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11
|
|
|
|
# c39ae07f393806ccf406ef966e9a15afc43cc36a refs/tags/v2.6.11^{}
|
|
|
|
open my $fd, "-|", git_cmd(), "show-ref", "--dereference",
|
|
|
|
($type ? ("--", "refs/$type") : ()) # use -- <pattern> if $type
|
2006-09-19 12:31:49 +00:00
|
|
|
or return;
|
2006-08-14 00:14:20 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
2008-09-02 19:47:05 +00:00
|
|
|
if ($line =~ m!^([0-9a-fA-F]{40})\srefs/($type.*)$!) {
|
2006-07-31 19:22:15 +00:00
|
|
|
if (defined $refs{$1}) {
|
2006-08-14 00:14:20 +00:00
|
|
|
push @{$refs{$1}}, $2;
|
2006-07-31 19:22:15 +00:00
|
|
|
} else {
|
2006-08-14 00:14:20 +00:00
|
|
|
$refs{$1} = [ $2 ];
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $fd or return;
|
|
|
|
return \%refs;
|
|
|
|
}
|
|
|
|
|
2006-08-24 17:41:23 +00:00
|
|
|
sub git_get_rev_name_tags {
|
|
|
|
my $hash = shift || return undef;
|
|
|
|
|
2006-08-28 15:49:58 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "name-rev", "--tags", $hash
|
2006-08-24 17:41:23 +00:00
|
|
|
or return;
|
|
|
|
my $name_rev = <$fd>;
|
|
|
|
close $fd;
|
|
|
|
|
|
|
|
if ($name_rev =~ m|^$hash tags/(.*)$|) {
|
|
|
|
return $1;
|
|
|
|
} else {
|
|
|
|
# catches also '$hash undefined' output
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ----------------------------------------------------------------------
|
|
|
|
## parse to hash functions
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub parse_date {
|
2006-07-31 19:22:15 +00:00
|
|
|
my $epoch = shift;
|
|
|
|
my $tz = shift || "-0000";
|
|
|
|
|
|
|
|
my %date;
|
|
|
|
my @months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
|
|
|
|
my @days = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
|
|
|
|
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($epoch);
|
|
|
|
$date{'hour'} = $hour;
|
|
|
|
$date{'minute'} = $min;
|
|
|
|
$date{'mday'} = $mday;
|
|
|
|
$date{'day'} = $days[$wday];
|
|
|
|
$date{'month'} = $months[$mon];
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
$date{'rfc2822'} = sprintf "%s, %d %s %4d %02d:%02d:%02d +0000",
|
|
|
|
$days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;
|
2006-08-22 14:52:50 +00:00
|
|
|
$date{'mday-time'} = sprintf "%d %s %02d:%02d",
|
|
|
|
$mday, $months[$mon], $hour ,$min;
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
$date{'iso-8601'} = sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ",
|
2007-11-10 18:55:27 +00:00
|
|
|
1900+$year, 1+$mon, $mday, $hour ,$min, $sec;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
gitweb: Fix handling of fractional timezones in parse_date
Fractional timezones, like -0330 (NST used in Canada) or +0430
(Afghanistan, Iran DST), were not handled properly in parse_date; this
means values such as 'minute_local' and 'iso-tz' were not generated
correctly.
This was caused by two mistakes:
* sign of timezone was applied only to hour part of offset, and not
as it should be also to minutes part (this affected only negative
fractional timezones).
* 'int $h + $m/60' is 'int($h + $m/60)' and not 'int($h) + $m/60',
so fractional part was discarded altogether ($h is hours, $m is
minutes, which is always less than 60).
Note that positive fractional timezones +0430, +0530 and +1030 can be
found as authortime in git.git repository itself.
For example http://repo.or.cz/w/git.git/commit/88d50e7 had authortime
of "Fri, 8 Jan 2010 18:48:07 +0000 (23:48 +0530)", which is not marked
with 'atnight', when "git show 88d50e7" gives correct author date of
"Sat Jan 9 00:18:07 2010 +0530".
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-03-25 19:20:49 +00:00
|
|
|
my ($tz_sign, $tz_hour, $tz_min) =
|
|
|
|
($tz =~ m/^([-+])(\d\d)(\d\d)$/);
|
|
|
|
$tz_sign = ($tz_sign eq '-' ? -1 : +1);
|
|
|
|
my $local = $epoch + $tz_sign*((($tz_hour*60) + $tz_min)*60);
|
2006-07-31 19:22:15 +00:00
|
|
|
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);
|
|
|
|
$date{'hour_local'} = $hour;
|
|
|
|
$date{'minute_local'} = $min;
|
|
|
|
$date{'tz_local'} = $tz;
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
$date{'iso-tz'} = sprintf("%04d-%02d-%02d %02d:%02d:%02d %s",
|
|
|
|
1900+$year, $mon+1, $mday,
|
|
|
|
$hour, $min, $sec, $tz);
|
2006-07-31 19:22:15 +00:00
|
|
|
return %date;
|
|
|
|
}
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub parse_tag {
|
2005-08-07 18:23:12 +00:00
|
|
|
my $tag_id = shift;
|
|
|
|
my %tag;
|
2005-08-07 18:28:53 +00:00
|
|
|
my @comment;
|
2005-08-07 18:23:12 +00:00
|
|
|
|
2006-08-28 15:49:58 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "cat-file", "tag", $tag_id or return;
|
2005-08-07 18:28:53 +00:00
|
|
|
$tag{'id'} = $tag_id;
|
2005-08-07 18:23:12 +00:00
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
if ($line =~ m/^object ([0-9a-fA-F]{40})$/) {
|
|
|
|
$tag{'object'} = $1;
|
2005-08-07 18:25:54 +00:00
|
|
|
} elsif ($line =~ m/^type (.+)$/) {
|
2005-08-07 18:23:12 +00:00
|
|
|
$tag{'type'} = $1;
|
2005-08-07 18:25:54 +00:00
|
|
|
} elsif ($line =~ m/^tag (.+)$/) {
|
2005-08-07 18:23:12 +00:00
|
|
|
$tag{'name'} = $1;
|
2005-08-07 18:28:53 +00:00
|
|
|
} elsif ($line =~ m/^tagger (.*) ([0-9]+) (.*)$/) {
|
|
|
|
$tag{'author'} = $1;
|
2009-06-29 22:00:50 +00:00
|
|
|
$tag{'author_epoch'} = $2;
|
|
|
|
$tag{'author_tz'} = $3;
|
|
|
|
if ($tag{'author'} =~ m/^([^<]+) <([^>]*)>/) {
|
|
|
|
$tag{'author_name'} = $1;
|
|
|
|
$tag{'author_email'} = $2;
|
|
|
|
} else {
|
|
|
|
$tag{'author_name'} = $tag{'author'};
|
|
|
|
}
|
2005-08-07 18:28:53 +00:00
|
|
|
} elsif ($line =~ m/--BEGIN/) {
|
|
|
|
push @comment, $line;
|
|
|
|
last;
|
|
|
|
} elsif ($line eq "") {
|
|
|
|
last;
|
2005-08-07 18:23:12 +00:00
|
|
|
}
|
|
|
|
}
|
2005-08-07 18:28:53 +00:00
|
|
|
push @comment, <$fd>;
|
|
|
|
$tag{'comment'} = \@comment;
|
2005-08-07 18:26:27 +00:00
|
|
|
close $fd or return;
|
2005-08-07 18:23:12 +00:00
|
|
|
if (!defined $tag{'name'}) {
|
|
|
|
return
|
|
|
|
};
|
|
|
|
return %tag
|
|
|
|
}
|
|
|
|
|
2006-12-24 14:31:42 +00:00
|
|
|
sub parse_commit_text {
|
2006-12-27 14:22:21 +00:00
|
|
|
my ($commit_text, $withparents) = @_;
|
2006-12-24 14:31:42 +00:00
|
|
|
my @commit_lines = split '\n', $commit_text;
|
2005-08-07 18:03:14 +00:00
|
|
|
my %co;
|
|
|
|
|
2006-12-24 14:31:42 +00:00
|
|
|
pop @commit_lines; # Remove '\0'
|
|
|
|
|
2007-05-12 19:16:34 +00:00
|
|
|
if (! @commit_lines) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-13 00:21:59 +00:00
|
|
|
my $header = shift @commit_lines;
|
2007-05-12 19:16:34 +00:00
|
|
|
if ($header !~ m/^[0-9a-fA-F]{40}/) {
|
2005-09-13 00:21:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-12-27 14:22:21 +00:00
|
|
|
($co{'id'}, my @parents) = split ' ', $header;
|
2005-08-07 18:26:27 +00:00
|
|
|
while (my $line = shift @commit_lines) {
|
2005-08-07 18:21:04 +00:00
|
|
|
last if $line eq "\n";
|
2005-08-07 18:25:54 +00:00
|
|
|
if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) {
|
2005-08-07 18:03:14 +00:00
|
|
|
$co{'tree'} = $1;
|
2006-12-27 14:22:21 +00:00
|
|
|
} elsif ((!defined $withparents) && ($line =~ m/^parent ([0-9a-fA-F]{40})$/)) {
|
2006-12-24 14:31:43 +00:00
|
|
|
push @parents, $1;
|
2005-08-07 18:06:09 +00:00
|
|
|
} elsif ($line =~ m/^author (.*) ([0-9]+) (.*)$/) {
|
2009-08-02 07:42:24 +00:00
|
|
|
$co{'author'} = to_utf8($1);
|
2005-08-07 18:13:11 +00:00
|
|
|
$co{'author_epoch'} = $2;
|
|
|
|
$co{'author_tz'} = $3;
|
2006-11-25 14:54:32 +00:00
|
|
|
if ($co{'author'} =~ m/^([^<]+) <([^>]*)>/) {
|
|
|
|
$co{'author_name'} = $1;
|
|
|
|
$co{'author_email'} = $2;
|
2005-08-07 18:26:03 +00:00
|
|
|
} else {
|
|
|
|
$co{'author_name'} = $co{'author'};
|
|
|
|
}
|
2005-08-07 18:08:29 +00:00
|
|
|
} elsif ($line =~ m/^committer (.*) ([0-9]+) (.*)$/) {
|
2009-08-02 07:42:24 +00:00
|
|
|
$co{'committer'} = to_utf8($1);
|
2005-08-07 18:13:11 +00:00
|
|
|
$co{'committer_epoch'} = $2;
|
|
|
|
$co{'committer_tz'} = $3;
|
2006-11-25 14:54:32 +00:00
|
|
|
if ($co{'committer'} =~ m/^([^<]+) <([^>]*)>/) {
|
|
|
|
$co{'committer_name'} = $1;
|
|
|
|
$co{'committer_email'} = $2;
|
|
|
|
} else {
|
|
|
|
$co{'committer_name'} = $co{'committer'};
|
|
|
|
}
|
2005-08-07 18:03:14 +00:00
|
|
|
}
|
|
|
|
}
|
2005-08-07 18:23:12 +00:00
|
|
|
if (!defined $co{'tree'}) {
|
2005-09-13 00:21:59 +00:00
|
|
|
return;
|
2005-08-07 18:23:12 +00:00
|
|
|
};
|
2006-12-24 14:31:43 +00:00
|
|
|
$co{'parents'} = \@parents;
|
|
|
|
$co{'parent'} = $parents[0];
|
2005-09-13 00:21:59 +00:00
|
|
|
|
2005-08-07 18:26:27 +00:00
|
|
|
foreach my $title (@commit_lines) {
|
2005-12-07 15:32:51 +00:00
|
|
|
$title =~ s/^ //;
|
2005-08-07 18:26:27 +00:00
|
|
|
if ($title ne "") {
|
2005-08-31 01:54:45 +00:00
|
|
|
$co{'title'} = chop_str($title, 80, 5);
|
2005-08-07 18:26:27 +00:00
|
|
|
# remove leading stuff of merges to make the interesting part visible
|
|
|
|
if (length($title) > 50) {
|
|
|
|
$title =~ s/^Automatic //;
|
|
|
|
$title =~ s/^merge (of|with) /Merge ... /i;
|
|
|
|
if (length($title) > 50) {
|
|
|
|
$title =~ s/(http|rsync):\/\///;
|
|
|
|
}
|
|
|
|
if (length($title) > 50) {
|
|
|
|
$title =~ s/(master|www|rsync)\.//;
|
|
|
|
}
|
|
|
|
if (length($title) > 50) {
|
|
|
|
$title =~ s/kernel.org:?//;
|
|
|
|
}
|
|
|
|
if (length($title) > 50) {
|
|
|
|
$title =~ s/\/pub\/scm//;
|
|
|
|
}
|
|
|
|
}
|
2005-08-31 01:54:45 +00:00
|
|
|
$co{'title_short'} = chop_str($title, 50, 5);
|
2005-08-07 18:26:27 +00:00
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
2008-09-05 18:26:29 +00:00
|
|
|
if (! defined $co{'title'} || $co{'title'} eq "") {
|
2006-10-06 16:55:04 +00:00
|
|
|
$co{'title'} = $co{'title_short'} = '(no commit message)';
|
|
|
|
}
|
2005-09-13 00:21:59 +00:00
|
|
|
# remove added spaces
|
|
|
|
foreach my $line (@commit_lines) {
|
|
|
|
$line =~ s/^ //;
|
|
|
|
}
|
|
|
|
$co{'comment'} = \@commit_lines;
|
2005-08-07 18:17:00 +00:00
|
|
|
|
|
|
|
my $age = time - $co{'committer_epoch'};
|
|
|
|
$co{'age'} = $age;
|
2005-08-07 18:29:03 +00:00
|
|
|
$co{'age_string'} = age_string($age);
|
2005-08-07 18:27:27 +00:00
|
|
|
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($co{'committer_epoch'});
|
|
|
|
if ($age > 60*60*24*7*2) {
|
2005-08-07 18:28:01 +00:00
|
|
|
$co{'age_string_date'} = sprintf "%4i-%02u-%02i", 1900 + $year, $mon+1, $mday;
|
2005-08-07 18:27:27 +00:00
|
|
|
$co{'age_string_age'} = $co{'age_string'};
|
|
|
|
} else {
|
|
|
|
$co{'age_string_date'} = $co{'age_string'};
|
2005-08-07 18:28:01 +00:00
|
|
|
$co{'age_string_age'} = sprintf "%4i-%02u-%02i", 1900 + $year, $mon+1, $mday;
|
2005-08-07 18:27:27 +00:00
|
|
|
}
|
2005-08-07 18:03:14 +00:00
|
|
|
return %co;
|
|
|
|
}
|
|
|
|
|
2006-12-24 14:31:42 +00:00
|
|
|
sub parse_commit {
|
|
|
|
my ($commit_id) = @_;
|
|
|
|
my %co;
|
|
|
|
|
|
|
|
local $/ = "\0";
|
|
|
|
|
|
|
|
open my $fd, "-|", git_cmd(), "rev-list",
|
2006-12-27 14:22:21 +00:00
|
|
|
"--parents",
|
2006-12-24 14:31:42 +00:00
|
|
|
"--header",
|
|
|
|
"--max-count=1",
|
|
|
|
$commit_id,
|
|
|
|
"--",
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-rev-list failed");
|
2006-12-27 14:22:21 +00:00
|
|
|
%co = parse_commit_text(<$fd>, 1);
|
2006-12-24 14:31:42 +00:00
|
|
|
close $fd;
|
|
|
|
|
|
|
|
return %co;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub parse_commits {
|
2008-02-26 12:22:06 +00:00
|
|
|
my ($commit_id, $maxcount, $skip, $filename, @args) = @_;
|
2006-12-24 14:31:42 +00:00
|
|
|
my @cos;
|
|
|
|
|
|
|
|
$maxcount ||= 1;
|
|
|
|
$skip ||= 0;
|
|
|
|
|
|
|
|
local $/ = "\0";
|
|
|
|
|
|
|
|
open my $fd, "-|", git_cmd(), "rev-list",
|
|
|
|
"--header",
|
2008-02-26 12:22:06 +00:00
|
|
|
@args,
|
2006-12-24 14:31:42 +00:00
|
|
|
("--max-count=" . $maxcount),
|
2006-12-24 14:31:49 +00:00
|
|
|
("--skip=" . $skip),
|
2007-07-12 18:39:27 +00:00
|
|
|
@extra_options,
|
2006-12-24 14:31:42 +00:00
|
|
|
$commit_id,
|
|
|
|
"--",
|
|
|
|
($filename ? ($filename) : ())
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-rev-list failed");
|
2006-12-24 14:31:42 +00:00
|
|
|
while (my $line = <$fd>) {
|
|
|
|
my %co = parse_commit_text($line);
|
|
|
|
push @cos, \%co;
|
|
|
|
}
|
|
|
|
close $fd;
|
|
|
|
|
|
|
|
return wantarray ? @cos : \@cos;
|
|
|
|
}
|
|
|
|
|
2006-08-21 21:08:52 +00:00
|
|
|
# parse line of git-diff-tree "raw" output
|
2006-08-21 21:07:00 +00:00
|
|
|
sub parse_difftree_raw_line {
|
|
|
|
my $line = shift;
|
|
|
|
my %res;
|
|
|
|
|
|
|
|
# ':100644 100644 03b218260e99b78c6df0ed378e59ed9205ccc96d 3b93d5e7cc7f7dd4ebed13a5cc1a4ad976fc94d8 M ls-files.c'
|
|
|
|
# ':100644 100644 7f9281985086971d3877aca27704f2aaf9c448ce bc190ebc71bbd923f2b728e505408f5e54bd073a M rev-tree.c'
|
|
|
|
if ($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/) {
|
|
|
|
$res{'from_mode'} = $1;
|
|
|
|
$res{'to_mode'} = $2;
|
|
|
|
$res{'from_id'} = $3;
|
|
|
|
$res{'to_id'} = $4;
|
2008-04-05 20:13:24 +00:00
|
|
|
$res{'status'} = $5;
|
2006-08-21 21:07:00 +00:00
|
|
|
$res{'similarity'} = $6;
|
|
|
|
if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied
|
2006-08-21 21:08:52 +00:00
|
|
|
($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7);
|
2006-08-21 21:07:00 +00:00
|
|
|
} else {
|
2007-11-01 11:38:08 +00:00
|
|
|
$res{'from_file'} = $res{'to_file'} = $res{'file'} = unquote($7);
|
2006-08-21 21:07:00 +00:00
|
|
|
}
|
|
|
|
}
|
2007-05-06 23:10:03 +00:00
|
|
|
# '::100755 100755 100755 60e79ca1b01bc8b057abe17ddab484699a7f5fdb 94067cc5f73388f33722d52ae02f44692bc07490 94067cc5f73388f33722d52ae02f44692bc07490 MR git-gui/git-gui.sh'
|
|
|
|
# combined diff (for merge commit)
|
|
|
|
elsif ($line =~ s/^(::+)((?:[0-7]{6} )+)((?:[0-9a-fA-F]{40} )+)([a-zA-Z]+)\t(.*)$//) {
|
|
|
|
$res{'nparents'} = length($1);
|
|
|
|
$res{'from_mode'} = [ split(' ', $2) ];
|
|
|
|
$res{'to_mode'} = pop @{$res{'from_mode'}};
|
|
|
|
$res{'from_id'} = [ split(' ', $3) ];
|
|
|
|
$res{'to_id'} = pop @{$res{'from_id'}};
|
|
|
|
$res{'status'} = [ split('', $4) ];
|
|
|
|
$res{'to_file'} = unquote($5);
|
|
|
|
}
|
2006-08-21 21:07:00 +00:00
|
|
|
# 'c512b523472485aef4fff9e57b229d9d243c967f'
|
2006-08-30 22:36:04 +00:00
|
|
|
elsif ($line =~ m/^([0-9a-fA-F]{40})$/) {
|
|
|
|
$res{'commit'} = $1;
|
|
|
|
}
|
2006-08-21 21:07:00 +00:00
|
|
|
|
|
|
|
return wantarray ? %res : \%res;
|
|
|
|
}
|
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# wrapper: return parsed line of git-diff-tree "raw" output
|
|
|
|
# (the argument might be raw line, or parsed info)
|
|
|
|
sub parsed_difftree_line {
|
|
|
|
my $line_or_ref = shift;
|
|
|
|
|
|
|
|
if (ref($line_or_ref) eq "HASH") {
|
|
|
|
# pre-parsed (or generated by hand)
|
|
|
|
return $line_or_ref;
|
|
|
|
} else {
|
|
|
|
return parse_difftree_raw_line($line_or_ref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-30 22:32:15 +00:00
|
|
|
# parse line of git-ls-tree output
|
2009-05-07 17:11:29 +00:00
|
|
|
sub parse_ls_tree_line {
|
2006-08-30 22:32:15 +00:00
|
|
|
my $line = shift;
|
|
|
|
my %opts = @_;
|
|
|
|
my %res;
|
|
|
|
|
2009-09-07 12:40:00 +00:00
|
|
|
if ($opts{'-l'}) {
|
|
|
|
#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa 16717 panic.c'
|
|
|
|
$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40}) +(-|[0-9]+)\t(.+)$/s;
|
2006-08-30 22:32:15 +00:00
|
|
|
|
2009-09-07 12:40:00 +00:00
|
|
|
$res{'mode'} = $1;
|
|
|
|
$res{'type'} = $2;
|
|
|
|
$res{'hash'} = $3;
|
|
|
|
$res{'size'} = $4;
|
|
|
|
if ($opts{'-z'}) {
|
|
|
|
$res{'name'} = $5;
|
|
|
|
} else {
|
|
|
|
$res{'name'} = unquote($5);
|
|
|
|
}
|
2006-08-30 22:32:15 +00:00
|
|
|
} else {
|
2009-09-07 12:40:00 +00:00
|
|
|
#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
|
|
|
|
$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s;
|
|
|
|
|
|
|
|
$res{'mode'} = $1;
|
|
|
|
$res{'type'} = $2;
|
|
|
|
$res{'hash'} = $3;
|
|
|
|
if ($opts{'-z'}) {
|
|
|
|
$res{'name'} = $4;
|
|
|
|
} else {
|
|
|
|
$res{'name'} = unquote($4);
|
|
|
|
}
|
2006-08-30 22:32:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return wantarray ? %res : \%res;
|
|
|
|
}
|
|
|
|
|
2007-06-08 11:27:42 +00:00
|
|
|
# generates _two_ hashes, references to which are passed as 2 and 3 argument
|
|
|
|
sub parse_from_to_diffinfo {
|
|
|
|
my ($diffinfo, $from, $to, @parents) = @_;
|
|
|
|
|
|
|
|
if ($diffinfo->{'nparents'}) {
|
|
|
|
# combined diff
|
|
|
|
$from->{'file'} = [];
|
|
|
|
$from->{'href'} = [];
|
|
|
|
fill_from_file_info($diffinfo, @parents)
|
|
|
|
unless exists $diffinfo->{'from_file'};
|
|
|
|
for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {
|
2007-11-01 11:38:08 +00:00
|
|
|
$from->{'file'}[$i] =
|
|
|
|
defined $diffinfo->{'from_file'}[$i] ?
|
|
|
|
$diffinfo->{'from_file'}[$i] :
|
|
|
|
$diffinfo->{'to_file'};
|
2007-06-08 11:27:42 +00:00
|
|
|
if ($diffinfo->{'status'}[$i] ne "A") { # not new (added) file
|
|
|
|
$from->{'href'}[$i] = href(action=>"blob",
|
|
|
|
hash_base=>$parents[$i],
|
|
|
|
hash=>$diffinfo->{'from_id'}[$i],
|
|
|
|
file_name=>$from->{'file'}[$i]);
|
|
|
|
} else {
|
|
|
|
$from->{'href'}[$i] = undef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2007-10-30 00:35:05 +00:00
|
|
|
# ordinary (not combined) diff
|
2007-11-01 11:38:08 +00:00
|
|
|
$from->{'file'} = $diffinfo->{'from_file'};
|
2007-06-08 11:27:42 +00:00
|
|
|
if ($diffinfo->{'status'} ne "A") { # not new (added) file
|
|
|
|
$from->{'href'} = href(action=>"blob", hash_base=>$hash_parent,
|
|
|
|
hash=>$diffinfo->{'from_id'},
|
|
|
|
file_name=>$from->{'file'});
|
|
|
|
} else {
|
|
|
|
delete $from->{'href'};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-01 11:38:08 +00:00
|
|
|
$to->{'file'} = $diffinfo->{'to_file'};
|
2007-06-08 11:27:42 +00:00
|
|
|
if (!is_deleted($diffinfo)) { # file exists in result
|
|
|
|
$to->{'href'} = href(action=>"blob", hash_base=>$hash,
|
|
|
|
hash=>$diffinfo->{'to_id'},
|
|
|
|
file_name=>$to->{'file'});
|
|
|
|
} else {
|
|
|
|
delete $to->{'href'};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ......................................................................
|
|
|
|
## parse to array of hashes functions
|
2005-08-07 17:52:52 +00:00
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
sub git_get_heads_list {
|
2010-11-11 12:26:10 +00:00
|
|
|
my ($limit, @classes) = @_;
|
2010-11-11 12:26:11 +00:00
|
|
|
@classes = ('heads') unless @classes;
|
2010-11-11 12:26:10 +00:00
|
|
|
my @patterns = map { "refs/$_" } @classes;
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
my @headslist;
|
|
|
|
|
|
|
|
open my $fd, '-|', git_cmd(), 'for-each-ref',
|
|
|
|
($limit ? '--count='.($limit+1) : ()), '--sort=-committerdate',
|
|
|
|
'--format=%(objectname) %(refname) %(subject)%00%(committer)',
|
2010-11-11 12:26:10 +00:00
|
|
|
@patterns
|
2006-09-15 01:43:28 +00:00
|
|
|
or return;
|
|
|
|
while (my $line = <$fd>) {
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
my %ref_item;
|
2006-09-19 12:33:22 +00:00
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
chomp $line;
|
|
|
|
my ($refinfo, $committerinfo) = split(/\0/, $line);
|
|
|
|
my ($hash, $name, $title) = split(' ', $refinfo, 3);
|
|
|
|
my ($committer, $epoch, $tz) =
|
|
|
|
($committerinfo =~ /^(.*) ([0-9]+) (.*)$/);
|
2007-12-15 14:40:28 +00:00
|
|
|
$ref_item{'fullname'} = $name;
|
2010-11-11 12:26:09 +00:00
|
|
|
$name =~ s!^refs/(?:head|remote)s/!!;
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
|
|
|
|
$ref_item{'name'} = $name;
|
|
|
|
$ref_item{'id'} = $hash;
|
|
|
|
$ref_item{'title'} = $title || '(no commit message)';
|
|
|
|
$ref_item{'epoch'} = $epoch;
|
|
|
|
if ($epoch) {
|
|
|
|
$ref_item{'age'} = age_string(time - $ref_item{'epoch'});
|
|
|
|
} else {
|
|
|
|
$ref_item{'age'} = "unknown";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
|
|
|
|
push @headslist, \%ref_item;
|
2006-09-15 01:43:28 +00:00
|
|
|
}
|
|
|
|
close $fd;
|
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
return wantarray ? @headslist : \@headslist;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_get_tags_list {
|
|
|
|
my $limit = shift;
|
|
|
|
my @tagslist;
|
|
|
|
|
|
|
|
open my $fd, '-|', git_cmd(), 'for-each-ref',
|
|
|
|
($limit ? '--count='.($limit+1) : ()), '--sort=-creatordate',
|
|
|
|
'--format=%(objectname) %(objecttype) %(refname) '.
|
|
|
|
'%(*objectname) %(*objecttype) %(subject)%00%(creator)',
|
|
|
|
'refs/tags'
|
|
|
|
or return;
|
|
|
|
while (my $line = <$fd>) {
|
|
|
|
my %ref_item;
|
2006-08-01 02:18:34 +00:00
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
chomp $line;
|
|
|
|
my ($refinfo, $creatorinfo) = split(/\0/, $line);
|
|
|
|
my ($id, $type, $name, $refid, $reftype, $title) = split(' ', $refinfo, 6);
|
|
|
|
my ($creator, $epoch, $tz) =
|
|
|
|
($creatorinfo =~ /^(.*) ([0-9]+) (.*)$/);
|
2007-12-15 14:40:28 +00:00
|
|
|
$ref_item{'fullname'} = $name;
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
$name =~ s!^refs/tags/!!;
|
|
|
|
|
|
|
|
$ref_item{'type'} = $type;
|
|
|
|
$ref_item{'id'} = $id;
|
|
|
|
$ref_item{'name'} = $name;
|
|
|
|
if ($type eq "tag") {
|
|
|
|
$ref_item{'subject'} = $title;
|
|
|
|
$ref_item{'reftype'} = $reftype;
|
|
|
|
$ref_item{'refid'} = $refid;
|
|
|
|
} else {
|
|
|
|
$ref_item{'reftype'} = $type;
|
|
|
|
$ref_item{'refid'} = $id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($type eq "tag" || $type eq "commit") {
|
|
|
|
$ref_item{'epoch'} = $epoch;
|
|
|
|
if ($epoch) {
|
|
|
|
$ref_item{'age'} = age_string(time - $ref_item{'epoch'});
|
|
|
|
} else {
|
|
|
|
$ref_item{'age'} = "unknown";
|
|
|
|
}
|
|
|
|
}
|
2005-08-07 18:09:33 +00:00
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
push @tagslist, \%ref_item;
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
close $fd;
|
|
|
|
|
|
|
|
return wantarray ? @tagslist : \@tagslist;
|
2005-08-07 18:08:29 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ----------------------------------------------------------------------
|
|
|
|
## filesystem-related functions
|
2005-08-07 18:06:09 +00:00
|
|
|
|
2005-08-07 18:22:44 +00:00
|
|
|
sub get_file_owner {
|
|
|
|
my $path = shift;
|
|
|
|
|
|
|
|
my ($dev, $ino, $mode, $nlink, $st_uid, $st_gid, $rdev, $size) = stat($path);
|
|
|
|
my ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid($st_uid);
|
|
|
|
if (!defined $gcos) {
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
my $owner = $gcos;
|
|
|
|
$owner =~ s/[,;].*$//;
|
2007-06-03 15:42:44 +00:00
|
|
|
return to_utf8($owner);
|
2005-08-07 18:22:44 +00:00
|
|
|
}
|
|
|
|
|
2008-12-01 18:01:42 +00:00
|
|
|
# assume that file exists
|
|
|
|
sub insert_file {
|
|
|
|
my $filename = shift;
|
|
|
|
|
|
|
|
open my $fd, '<', $filename;
|
2008-12-08 13:13:21 +00:00
|
|
|
print map { to_utf8($_) } <$fd>;
|
2008-12-01 18:01:42 +00:00
|
|
|
close $fd;
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ......................................................................
|
|
|
|
## mimetype related functions
|
2005-08-07 18:21:23 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub mimetype_guess_file {
|
|
|
|
my $filename = shift;
|
|
|
|
my $mimemap = shift;
|
|
|
|
-r $mimemap or return undef;
|
|
|
|
|
|
|
|
my %mimemap;
|
2009-05-10 00:38:34 +00:00
|
|
|
open(my $mh, '<', $mimemap) or return undef;
|
2009-05-11 01:21:06 +00:00
|
|
|
while (<$mh>) {
|
2006-08-14 00:15:22 +00:00
|
|
|
next if m/^#/; # skip comments
|
2009-05-11 01:21:06 +00:00
|
|
|
my ($mimetype, $exts) = split(/\t+/);
|
2006-08-01 02:24:37 +00:00
|
|
|
if (defined $exts) {
|
|
|
|
my @exts = split(/\s+/, $exts);
|
|
|
|
foreach my $ext (@exts) {
|
2009-05-11 01:21:06 +00:00
|
|
|
$mimemap{$ext} = $mimetype;
|
2006-08-01 02:24:37 +00:00
|
|
|
}
|
2005-08-07 18:21:23 +00:00
|
|
|
}
|
|
|
|
}
|
2009-05-11 01:21:06 +00:00
|
|
|
close($mh);
|
2005-08-07 18:21:23 +00:00
|
|
|
|
2006-09-19 11:57:03 +00:00
|
|
|
$filename =~ /\.([^.]*)$/;
|
2006-07-31 19:22:15 +00:00
|
|
|
return $mimemap{$1};
|
|
|
|
}
|
2006-06-12 08:31:57 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub mimetype_guess {
|
|
|
|
my $filename = shift;
|
|
|
|
my $mime;
|
|
|
|
$filename =~ /\./ or return undef;
|
2006-06-12 08:31:57 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
if ($mimetypes_file) {
|
|
|
|
my $file = $mimetypes_file;
|
2006-08-14 00:16:33 +00:00
|
|
|
if ($file !~ m!^/!) { # if it is relative path
|
|
|
|
# it is relative to project
|
|
|
|
$file = "$projectroot/$project/$file";
|
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
$mime = mimetype_guess_file($filename, $file);
|
|
|
|
}
|
|
|
|
$mime ||= mimetype_guess_file($filename, '/etc/mime.types');
|
|
|
|
return $mime;
|
2006-06-12 08:31:57 +00:00
|
|
|
}
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub blob_mimetype {
|
2006-07-31 19:22:15 +00:00
|
|
|
my $fd = shift;
|
|
|
|
my $filename = shift;
|
2006-06-12 08:31:57 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
if ($filename) {
|
|
|
|
my $mime = mimetype_guess($filename);
|
|
|
|
$mime and return $mime;
|
2005-08-12 19:43:32 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
|
|
|
|
# just in case
|
|
|
|
return $default_blob_plain_mimetype unless $fd;
|
|
|
|
|
|
|
|
if (-T $fd) {
|
2008-06-03 14:47:10 +00:00
|
|
|
return 'text/plain';
|
2006-07-31 19:22:15 +00:00
|
|
|
} elsif (! $filename) {
|
|
|
|
return 'application/octet-stream';
|
|
|
|
} elsif ($filename =~ m/\.png$/i) {
|
|
|
|
return 'image/png';
|
|
|
|
} elsif ($filename =~ m/\.gif$/i) {
|
|
|
|
return 'image/gif';
|
|
|
|
} elsif ($filename =~ m/\.jpe?g$/i) {
|
|
|
|
return 'image/jpeg';
|
2005-08-12 19:43:32 +00:00
|
|
|
} else {
|
2006-07-31 19:22:15 +00:00
|
|
|
return 'application/octet-stream';
|
2005-08-10 01:53:09 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
|
2008-06-03 14:47:10 +00:00
|
|
|
sub blob_contenttype {
|
|
|
|
my ($fd, $file_name, $type) = @_;
|
|
|
|
|
|
|
|
$type ||= blob_mimetype($fd, $file_name);
|
|
|
|
if ($type eq 'text/plain' && defined $default_text_plain_charset) {
|
|
|
|
$type .= "; charset=$default_text_plain_charset";
|
|
|
|
}
|
|
|
|
|
|
|
|
return $type;
|
|
|
|
}
|
|
|
|
|
2010-04-27 19:34:45 +00:00
|
|
|
# guess file syntax for syntax highlighting; return undef if no highlighting
|
|
|
|
# the name of syntax can (in the future) depend on syntax highlighter used
|
|
|
|
sub guess_file_syntax {
|
|
|
|
my ($highlight, $mimetype, $file_name) = @_;
|
|
|
|
return undef unless ($highlight && defined $file_name);
|
|
|
|
my $basename = basename($file_name, '.in');
|
|
|
|
return $highlight_basename{$basename}
|
|
|
|
if exists $highlight_basename{$basename};
|
|
|
|
|
|
|
|
$basename =~ /\.([^.]*)$/;
|
|
|
|
my $ext = $1 or return undef;
|
|
|
|
return $highlight_ext{$ext}
|
|
|
|
if exists $highlight_ext{$ext};
|
|
|
|
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
|
|
|
# run highlighter and return FD of its output,
|
|
|
|
# or return original FD if no highlighting
|
|
|
|
sub run_highlighter {
|
|
|
|
my ($fd, $highlight, $syntax) = @_;
|
|
|
|
return $fd unless ($highlight && defined $syntax);
|
|
|
|
|
2010-12-30 21:20:29 +00:00
|
|
|
close $fd;
|
2010-04-27 19:34:45 +00:00
|
|
|
open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ".
|
2010-09-21 07:25:19 +00:00
|
|
|
quote_command($highlight_bin).
|
2011-03-16 22:34:13 +00:00
|
|
|
" --replace-tabs=8 --fragment --syntax $syntax |"
|
2010-04-27 19:34:45 +00:00
|
|
|
or die_error(500, "Couldn't open file or run syntax highlighter");
|
|
|
|
return $fd;
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ======================================================================
|
|
|
|
## functions printing HTML: header, footer, error page
|
|
|
|
|
2010-04-24 14:01:10 +00:00
|
|
|
sub get_page_title {
|
|
|
|
my $title = to_utf8($site_name);
|
|
|
|
|
|
|
|
return $title unless (defined $project);
|
|
|
|
$title .= " - " . to_utf8($project);
|
|
|
|
|
|
|
|
return $title unless (defined $action);
|
|
|
|
$title .= "/$action"; # $action is US-ASCII (7bit ASCII)
|
|
|
|
|
|
|
|
return $title unless (defined $file_name);
|
|
|
|
$title .= " - " . esc_path($file_name);
|
|
|
|
if ($action eq "tree" && $file_name !~ m|/$|) {
|
|
|
|
$title .= "/";
|
|
|
|
}
|
|
|
|
|
|
|
|
return $title;
|
|
|
|
}
|
|
|
|
|
2010-12-18 20:02:13 +00:00
|
|
|
sub print_feed_meta {
|
|
|
|
if (defined $project) {
|
|
|
|
my %href_params = get_feed_info();
|
|
|
|
if (!exists $href_params{'-title'}) {
|
|
|
|
$href_params{'-title'} = 'log';
|
|
|
|
}
|
|
|
|
|
2011-02-19 15:27:41 +00:00
|
|
|
foreach my $format (qw(RSS Atom)) {
|
2010-12-18 20:02:13 +00:00
|
|
|
my $type = lc($format);
|
|
|
|
my %link_attr = (
|
|
|
|
'-rel' => 'alternate',
|
|
|
|
'-title' => esc_attr("$project - $href_params{'-title'} - $format feed"),
|
|
|
|
'-type' => "application/$type+xml"
|
|
|
|
);
|
|
|
|
|
|
|
|
$href_params{'action'} = $type;
|
|
|
|
$link_attr{'-href'} = href(%href_params);
|
|
|
|
print "<link ".
|
|
|
|
"rel=\"$link_attr{'-rel'}\" ".
|
|
|
|
"title=\"$link_attr{'-title'}\" ".
|
|
|
|
"href=\"$link_attr{'-href'}\" ".
|
|
|
|
"type=\"$link_attr{'-type'}\" ".
|
|
|
|
"/>\n";
|
|
|
|
|
|
|
|
$href_params{'extra_options'} = '--no-merges';
|
|
|
|
$link_attr{'-href'} = href(%href_params);
|
|
|
|
$link_attr{'-title'} .= ' (no merges)';
|
|
|
|
print "<link ".
|
|
|
|
"rel=\"$link_attr{'-rel'}\" ".
|
|
|
|
"title=\"$link_attr{'-title'}\" ".
|
|
|
|
"href=\"$link_attr{'-href'}\" ".
|
|
|
|
"type=\"$link_attr{'-type'}\" ".
|
|
|
|
"/>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
printf('<link rel="alternate" title="%s projects list" '.
|
|
|
|
'href="%s" type="text/plain; charset=utf-8" />'."\n",
|
|
|
|
esc_attr($site_name), href(project=>undef, action=>"project_index"));
|
|
|
|
printf('<link rel="alternate" title="%s projects feeds" '.
|
|
|
|
'href="%s" type="text/x-opml" />'."\n",
|
|
|
|
esc_attr($site_name), href(project=>undef, action=>"opml"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub git_header_html {
|
|
|
|
my $status = shift || "200 OK";
|
|
|
|
my $expires = shift;
|
2010-04-24 14:00:04 +00:00
|
|
|
my %opts = @_;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2010-04-24 14:01:10 +00:00
|
|
|
my $title = get_page_title();
|
2006-07-31 19:22:15 +00:00
|
|
|
my $content_type;
|
|
|
|
# require explicit support from the UA if we are to send the page as
|
|
|
|
# 'application/xhtml+xml', otherwise send it as plain old 'text/html'.
|
|
|
|
# we have to do this because MSIE sometimes globs '*/*', pretending to
|
|
|
|
# support xhtml+xml but choking when it gets what it asked for.
|
2006-08-22 14:52:50 +00:00
|
|
|
if (defined $cgi->http('HTTP_ACCEPT') &&
|
|
|
|
$cgi->http('HTTP_ACCEPT') =~ m/(,|;|\s|^)application\/xhtml\+xml(,|;|\s|$)/ &&
|
|
|
|
$cgi->Accept('application/xhtml+xml') != 0) {
|
2006-07-31 19:22:15 +00:00
|
|
|
$content_type = 'application/xhtml+xml';
|
2005-08-10 01:53:09 +00:00
|
|
|
} else {
|
2006-07-31 19:22:15 +00:00
|
|
|
$content_type = 'text/html';
|
2005-08-10 01:53:09 +00:00
|
|
|
}
|
2006-08-22 14:52:50 +00:00
|
|
|
print $cgi->header(-type=>$content_type, -charset => 'utf-8',
|
2010-04-24 14:00:04 +00:00
|
|
|
-status=> $status, -expires => $expires)
|
2010-06-12 22:35:59 +00:00
|
|
|
unless ($opts{'-no_http_header'});
|
2006-12-27 22:59:51 +00:00
|
|
|
my $mod_perl_version = $ENV{'MOD_PERL'} ? " $ENV{'MOD_PERL'}" : '';
|
2006-07-31 19:22:15 +00:00
|
|
|
print <<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">
|
2006-08-17 09:21:28 +00:00
|
|
|
<!-- git web interface version $version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
|
2006-07-31 19:22:15 +00:00
|
|
|
<!-- git core binaries version $git_version -->
|
|
|
|
<head>
|
|
|
|
<meta http-equiv="content-type" content="$content_type; charset=utf-8"/>
|
2006-12-27 22:59:51 +00:00
|
|
|
<meta name="generator" content="gitweb/$version git/$git_version$mod_perl_version"/>
|
2006-07-31 19:22:15 +00:00
|
|
|
<meta name="robots" content="index, nofollow"/>
|
|
|
|
<title>$title</title>
|
|
|
|
EOF
|
2009-01-31 01:31:52 +00:00
|
|
|
# the stylesheet, favicon etc urls won't work correctly with path_info
|
|
|
|
# unless we set the appropriate base URL
|
2009-01-31 01:31:50 +00:00
|
|
|
if ($ENV{'PATH_INFO'}) {
|
2009-02-15 09:18:36 +00:00
|
|
|
print "<base href=\"".esc_url($base_url)."\" />\n";
|
2009-01-31 01:31:50 +00:00
|
|
|
}
|
2009-01-31 01:31:52 +00:00
|
|
|
# print out each stylesheet that exist, providing backwards capability
|
|
|
|
# for those people who defined $stylesheet in a config file
|
2006-10-03 12:49:03 +00:00
|
|
|
if (defined $stylesheet) {
|
2010-12-14 23:34:01 +00:00
|
|
|
print '<link rel="stylesheet" type="text/css" href="'.esc_url($stylesheet).'"/>'."\n";
|
2006-10-03 12:49:03 +00:00
|
|
|
} else {
|
|
|
|
foreach my $stylesheet (@stylesheets) {
|
|
|
|
next unless $stylesheet;
|
2010-12-14 23:34:01 +00:00
|
|
|
print '<link rel="stylesheet" type="text/css" href="'.esc_url($stylesheet).'"/>'."\n";
|
2006-10-03 12:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-18 20:02:13 +00:00
|
|
|
print_feed_meta()
|
|
|
|
if ($status eq '200 OK');
|
2006-09-04 18:32:13 +00:00
|
|
|
if (defined $favicon) {
|
2010-12-14 23:34:01 +00:00
|
|
|
print qq(<link rel="shortcut icon" href=").esc_url($favicon).qq(" type="image/png" />\n);
|
2006-09-04 18:32:13 +00:00
|
|
|
}
|
2006-08-05 11:18:58 +00:00
|
|
|
|
2006-08-06 11:25:41 +00:00
|
|
|
print "</head>\n" .
|
2006-10-03 12:49:03 +00:00
|
|
|
"<body>\n";
|
|
|
|
|
2010-01-30 22:30:41 +00:00
|
|
|
if (defined $site_header && -f $site_header) {
|
2008-12-01 18:01:42 +00:00
|
|
|
insert_file($site_header);
|
2006-10-03 12:49:03 +00:00
|
|
|
}
|
|
|
|
|
2010-09-04 00:45:09 +00:00
|
|
|
print "<div class=\"page_header\">\n";
|
|
|
|
if (defined $logo) {
|
|
|
|
print $cgi->a({-href => esc_url($logo_url),
|
|
|
|
-title => $logo_label},
|
|
|
|
$cgi->img({-src => esc_url($logo),
|
|
|
|
-width => 72, -height => 27,
|
|
|
|
-alt => "git",
|
|
|
|
-class => "logo"}));
|
|
|
|
}
|
2006-09-25 23:58:41 +00:00
|
|
|
print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / ";
|
2006-07-31 19:22:15 +00:00
|
|
|
if (defined $project) {
|
2006-08-15 22:24:30 +00:00
|
|
|
print $cgi->a({-href => href(action=>"summary")}, esc_html($project));
|
2006-07-31 19:22:15 +00:00
|
|
|
if (defined $action) {
|
2010-11-11 12:26:13 +00:00
|
|
|
my $action_print = $action ;
|
|
|
|
if (defined $opts{-action_extra}) {
|
|
|
|
$action_print = $cgi->a({-href => href(action=>$action)},
|
|
|
|
$action);
|
|
|
|
}
|
|
|
|
print " / $action_print";
|
|
|
|
}
|
|
|
|
if (defined $opts{-action_extra}) {
|
|
|
|
print " / $opts{-action_extra}";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
print "\n";
|
2006-12-23 03:35:16 +00:00
|
|
|
}
|
2007-05-17 02:24:19 +00:00
|
|
|
print "</div>\n";
|
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
my $have_search = gitweb_check_feature('search');
|
2008-06-02 09:54:41 +00:00
|
|
|
if (defined $project && $have_search) {
|
2006-07-31 19:22:15 +00:00
|
|
|
if (!defined $searchtext) {
|
|
|
|
$searchtext = "";
|
|
|
|
}
|
|
|
|
my $search_hash;
|
|
|
|
if (defined $hash_base) {
|
|
|
|
$search_hash = $hash_base;
|
|
|
|
} elsif (defined $hash) {
|
|
|
|
$search_hash = $hash;
|
2005-08-07 18:25:42 +00:00
|
|
|
} else {
|
2006-07-31 19:22:15 +00:00
|
|
|
$search_hash = "HEAD";
|
2005-08-07 18:25:42 +00:00
|
|
|
}
|
2007-06-28 18:57:07 +00:00
|
|
|
my $action = $my_uri;
|
2008-11-29 21:07:29 +00:00
|
|
|
my $use_pathinfo = gitweb_check_feature('pathinfo');
|
2007-06-28 18:57:07 +00:00
|
|
|
if ($use_pathinfo) {
|
2008-04-20 21:23:38 +00:00
|
|
|
$action .= "/".esc_url($project);
|
2007-06-28 18:57:07 +00:00
|
|
|
}
|
|
|
|
print $cgi->startform(-method => "get", -action => $action) .
|
2006-07-31 19:22:15 +00:00
|
|
|
"<div class=\"search\">\n" .
|
2008-06-02 09:54:41 +00:00
|
|
|
(!$use_pathinfo &&
|
|
|
|
$cgi->input({-name=>"p", -value=>$project, -type=>"hidden"}) . "\n") .
|
|
|
|
$cgi->input({-name=>"a", -value=>"search", -type=>"hidden"}) . "\n" .
|
|
|
|
$cgi->input({-name=>"h", -value=>$search_hash, -type=>"hidden"}) . "\n" .
|
2006-10-24 03:15:46 +00:00
|
|
|
$cgi->popup_menu(-name => 'st', -default => 'commit',
|
2007-05-17 02:31:12 +00:00
|
|
|
-values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) .
|
2006-10-24 03:15:46 +00:00
|
|
|
$cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) .
|
|
|
|
" search:\n",
|
2006-07-31 19:22:15 +00:00
|
|
|
$cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
|
2008-02-26 12:22:08 +00:00
|
|
|
"<span title=\"Extended regular expression\">" .
|
|
|
|
$cgi->checkbox(-name => 'sr', -value => 1, -label => 're',
|
|
|
|
-checked => $search_use_regexp) .
|
|
|
|
"</span>" .
|
2006-07-31 19:22:15 +00:00
|
|
|
"</div>" .
|
|
|
|
$cgi->end_form() . "\n";
|
2005-08-07 18:21:04 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sub git_footer_html {
|
gitweb: Use feed link according to current view
Michael G. Noll said in comments to the "Switching my code repository from
Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My
digital moleskine" blog, that one of the things he is missing in gitweb
from SVN::Web is an RSS feed with news/information of the current view
(including RSS feed for single file or directory).
This is not exactly true, as since refactoring feed generation in af6feeb
(gitweb: Refactor feed generation, make output prettier, add Atom feed,
2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a
given branch, history limited to a given directory, or history of a given
file. Nevertheless this required handcrafting the URL to get wanted RSS
feed.
This commit makes gitweb select feed links in the HTML header and in
page footer depending on current view (action). It is more elaborate,
and I guess more correct, than simple patch adding $hash ('h')
parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot
Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash
is specified in the current request
Message-ID: <ae63f8b50803211138y6355fd11pa64cda50a1f53011@mail.gmail.com>
If $hash ('h') or $hash_base ('hb') parameter is a branch name
(i.e. it starts with 'refs/heads/'; all generated URLs use this form
to discriminate between tags and heads), it is used in feed URLs; if
$file_name ('f') is defined, it is used in feed URLs. Feed title is
set according to the kind of web feed: it is either 'log' for generic
feed, 'log of <branch>', 'history of <filename>' for generic history
(using implicit or explicit HEAD, i.e. current branch) or 'history of
<filename> on <branch>'.
There are special cases: 'heads' and 'forks' views should use OPML
providing list of available feeds; 'tags' probably also should use
OPML; there is no web feed equivalent to 'search' view. Currently all
those cases fallback to (show) default feed. Such feed link uses
"generic" class, and is shown in slightly lighter color for
distinction.
Currently feed can have but one starting point, and does not support
negative (exclude) commit arguments. Therefore for now for *diff
views it is chosen that feed follow the "to" part: to-name, to-commit
for 'blobdiff', 'treediff' and 'commitdiff' views.
Generating parameters for href() for feed link was separated
(refactored) into get_feed_info() subroutine.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-20 20:09:48 +00:00
|
|
|
my $feed_class = 'rss_logo';
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
print "<div class=\"page_footer\">\n";
|
|
|
|
if (defined $project) {
|
2006-08-14 00:05:47 +00:00
|
|
|
my $descr = git_get_project_description($project);
|
2006-07-31 19:22:15 +00:00
|
|
|
if (defined $descr) {
|
|
|
|
print "<div class=\"page_footer_text\">" . esc_html($descr) . "</div>\n";
|
|
|
|
}
|
gitweb: Use feed link according to current view
Michael G. Noll said in comments to the "Switching my code repository from
Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My
digital moleskine" blog, that one of the things he is missing in gitweb
from SVN::Web is an RSS feed with news/information of the current view
(including RSS feed for single file or directory).
This is not exactly true, as since refactoring feed generation in af6feeb
(gitweb: Refactor feed generation, make output prettier, add Atom feed,
2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a
given branch, history limited to a given directory, or history of a given
file. Nevertheless this required handcrafting the URL to get wanted RSS
feed.
This commit makes gitweb select feed links in the HTML header and in
page footer depending on current view (action). It is more elaborate,
and I guess more correct, than simple patch adding $hash ('h')
parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot
Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash
is specified in the current request
Message-ID: <ae63f8b50803211138y6355fd11pa64cda50a1f53011@mail.gmail.com>
If $hash ('h') or $hash_base ('hb') parameter is a branch name
(i.e. it starts with 'refs/heads/'; all generated URLs use this form
to discriminate between tags and heads), it is used in feed URLs; if
$file_name ('f') is defined, it is used in feed URLs. Feed title is
set according to the kind of web feed: it is either 'log' for generic
feed, 'log of <branch>', 'history of <filename>' for generic history
(using implicit or explicit HEAD, i.e. current branch) or 'history of
<filename> on <branch>'.
There are special cases: 'heads' and 'forks' views should use OPML
providing list of available feeds; 'tags' probably also should use
OPML; there is no web feed equivalent to 'search' view. Currently all
those cases fallback to (show) default feed. Such feed link uses
"generic" class, and is shown in slightly lighter color for
distinction.
Currently feed can have but one starting point, and does not support
negative (exclude) commit arguments. Therefore for now for *diff
views it is chosen that feed follow the "to" part: to-name, to-commit
for 'blobdiff', 'treediff' and 'commitdiff' views.
Generating parameters for href() for feed link was separated
(refactored) into get_feed_info() subroutine.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-20 20:09:48 +00:00
|
|
|
|
|
|
|
my %href_params = get_feed_info();
|
|
|
|
if (!%href_params) {
|
|
|
|
$feed_class .= ' generic';
|
|
|
|
}
|
|
|
|
$href_params{'-title'} ||= 'log';
|
|
|
|
|
2011-02-19 15:27:41 +00:00
|
|
|
foreach my $format (qw(RSS Atom)) {
|
gitweb: Use feed link according to current view
Michael G. Noll said in comments to the "Switching my code repository from
Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My
digital moleskine" blog, that one of the things he is missing in gitweb
from SVN::Web is an RSS feed with news/information of the current view
(including RSS feed for single file or directory).
This is not exactly true, as since refactoring feed generation in af6feeb
(gitweb: Refactor feed generation, make output prettier, add Atom feed,
2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a
given branch, history limited to a given directory, or history of a given
file. Nevertheless this required handcrafting the URL to get wanted RSS
feed.
This commit makes gitweb select feed links in the HTML header and in
page footer depending on current view (action). It is more elaborate,
and I guess more correct, than simple patch adding $hash ('h')
parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot
Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash
is specified in the current request
Message-ID: <ae63f8b50803211138y6355fd11pa64cda50a1f53011@mail.gmail.com>
If $hash ('h') or $hash_base ('hb') parameter is a branch name
(i.e. it starts with 'refs/heads/'; all generated URLs use this form
to discriminate between tags and heads), it is used in feed URLs; if
$file_name ('f') is defined, it is used in feed URLs. Feed title is
set according to the kind of web feed: it is either 'log' for generic
feed, 'log of <branch>', 'history of <filename>' for generic history
(using implicit or explicit HEAD, i.e. current branch) or 'history of
<filename> on <branch>'.
There are special cases: 'heads' and 'forks' views should use OPML
providing list of available feeds; 'tags' probably also should use
OPML; there is no web feed equivalent to 'search' view. Currently all
those cases fallback to (show) default feed. Such feed link uses
"generic" class, and is shown in slightly lighter color for
distinction.
Currently feed can have but one starting point, and does not support
negative (exclude) commit arguments. Therefore for now for *diff
views it is chosen that feed follow the "to" part: to-name, to-commit
for 'blobdiff', 'treediff' and 'commitdiff' views.
Generating parameters for href() for feed link was separated
(refactored) into get_feed_info() subroutine.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-20 20:09:48 +00:00
|
|
|
$href_params{'action'} = lc($format);
|
|
|
|
print $cgi->a({-href => href(%href_params),
|
|
|
|
-title => "$href_params{'-title'} $format feed",
|
|
|
|
-class => $feed_class}, $format)."\n";
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
} else {
|
2006-09-15 17:30:34 +00:00
|
|
|
print $cgi->a({-href => href(project=>undef, action=>"opml"),
|
gitweb: Use feed link according to current view
Michael G. Noll said in comments to the "Switching my code repository from
Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My
digital moleskine" blog, that one of the things he is missing in gitweb
from SVN::Web is an RSS feed with news/information of the current view
(including RSS feed for single file or directory).
This is not exactly true, as since refactoring feed generation in af6feeb
(gitweb: Refactor feed generation, make output prettier, add Atom feed,
2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a
given branch, history limited to a given directory, or history of a given
file. Nevertheless this required handcrafting the URL to get wanted RSS
feed.
This commit makes gitweb select feed links in the HTML header and in
page footer depending on current view (action). It is more elaborate,
and I guess more correct, than simple patch adding $hash ('h')
parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot
Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash
is specified in the current request
Message-ID: <ae63f8b50803211138y6355fd11pa64cda50a1f53011@mail.gmail.com>
If $hash ('h') or $hash_base ('hb') parameter is a branch name
(i.e. it starts with 'refs/heads/'; all generated URLs use this form
to discriminate between tags and heads), it is used in feed URLs; if
$file_name ('f') is defined, it is used in feed URLs. Feed title is
set according to the kind of web feed: it is either 'log' for generic
feed, 'log of <branch>', 'history of <filename>' for generic history
(using implicit or explicit HEAD, i.e. current branch) or 'history of
<filename> on <branch>'.
There are special cases: 'heads' and 'forks' views should use OPML
providing list of available feeds; 'tags' probably also should use
OPML; there is no web feed equivalent to 'search' view. Currently all
those cases fallback to (show) default feed. Such feed link uses
"generic" class, and is shown in slightly lighter color for
distinction.
Currently feed can have but one starting point, and does not support
negative (exclude) commit arguments. Therefore for now for *diff
views it is chosen that feed follow the "to" part: to-name, to-commit
for 'blobdiff', 'treediff' and 'commitdiff' views.
Generating parameters for href() for feed link was separated
(refactored) into get_feed_info() subroutine.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-20 20:09:48 +00:00
|
|
|
-class => $feed_class}, "OPML") . " ";
|
2006-09-15 09:11:33 +00:00
|
|
|
print $cgi->a({-href => href(project=>undef, action=>"project_index"),
|
gitweb: Use feed link according to current view
Michael G. Noll said in comments to the "Switching my code repository from
Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My
digital moleskine" blog, that one of the things he is missing in gitweb
from SVN::Web is an RSS feed with news/information of the current view
(including RSS feed for single file or directory).
This is not exactly true, as since refactoring feed generation in af6feeb
(gitweb: Refactor feed generation, make output prettier, add Atom feed,
2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a
given branch, history limited to a given directory, or history of a given
file. Nevertheless this required handcrafting the URL to get wanted RSS
feed.
This commit makes gitweb select feed links in the HTML header and in
page footer depending on current view (action). It is more elaborate,
and I guess more correct, than simple patch adding $hash ('h')
parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot
Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash
is specified in the current request
Message-ID: <ae63f8b50803211138y6355fd11pa64cda50a1f53011@mail.gmail.com>
If $hash ('h') or $hash_base ('hb') parameter is a branch name
(i.e. it starts with 'refs/heads/'; all generated URLs use this form
to discriminate between tags and heads), it is used in feed URLs; if
$file_name ('f') is defined, it is used in feed URLs. Feed title is
set according to the kind of web feed: it is either 'log' for generic
feed, 'log of <branch>', 'history of <filename>' for generic history
(using implicit or explicit HEAD, i.e. current branch) or 'history of
<filename> on <branch>'.
There are special cases: 'heads' and 'forks' views should use OPML
providing list of available feeds; 'tags' probably also should use
OPML; there is no web feed equivalent to 'search' view. Currently all
those cases fallback to (show) default feed. Such feed link uses
"generic" class, and is shown in slightly lighter color for
distinction.
Currently feed can have but one starting point, and does not support
negative (exclude) commit arguments. Therefore for now for *diff
views it is chosen that feed follow the "to" part: to-name, to-commit
for 'blobdiff', 'treediff' and 'commitdiff' views.
Generating parameters for href() for feed link was separated
(refactored) into get_feed_info() subroutine.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-20 20:09:48 +00:00
|
|
|
-class => $feed_class}, "TXT") . "\n";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
gitweb: Use feed link according to current view
Michael G. Noll said in comments to the "Switching my code repository from
Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My
digital moleskine" blog, that one of the things he is missing in gitweb
from SVN::Web is an RSS feed with news/information of the current view
(including RSS feed for single file or directory).
This is not exactly true, as since refactoring feed generation in af6feeb
(gitweb: Refactor feed generation, make output prettier, add Atom feed,
2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a
given branch, history limited to a given directory, or history of a given
file. Nevertheless this required handcrafting the URL to get wanted RSS
feed.
This commit makes gitweb select feed links in the HTML header and in
page footer depending on current view (action). It is more elaborate,
and I guess more correct, than simple patch adding $hash ('h')
parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot
Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash
is specified in the current request
Message-ID: <ae63f8b50803211138y6355fd11pa64cda50a1f53011@mail.gmail.com>
If $hash ('h') or $hash_base ('hb') parameter is a branch name
(i.e. it starts with 'refs/heads/'; all generated URLs use this form
to discriminate between tags and heads), it is used in feed URLs; if
$file_name ('f') is defined, it is used in feed URLs. Feed title is
set according to the kind of web feed: it is either 'log' for generic
feed, 'log of <branch>', 'history of <filename>' for generic history
(using implicit or explicit HEAD, i.e. current branch) or 'history of
<filename> on <branch>'.
There are special cases: 'heads' and 'forks' views should use OPML
providing list of available feeds; 'tags' probably also should use
OPML; there is no web feed equivalent to 'search' view. Currently all
those cases fallback to (show) default feed. Such feed link uses
"generic" class, and is shown in slightly lighter color for
distinction.
Currently feed can have but one starting point, and does not support
negative (exclude) commit arguments. Therefore for now for *diff
views it is chosen that feed follow the "to" part: to-name, to-commit
for 'blobdiff', 'treediff' and 'commitdiff' views.
Generating parameters for href() for feed link was separated
(refactored) into get_feed_info() subroutine.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-20 20:09:48 +00:00
|
|
|
print "</div>\n"; # class="page_footer"
|
2006-10-03 12:49:03 +00:00
|
|
|
|
2009-09-01 11:39:16 +00:00
|
|
|
if (defined $t0 && gitweb_check_feature('timed')) {
|
|
|
|
print "<div id=\"generating_info\">\n";
|
|
|
|
print 'This page took '.
|
|
|
|
'<span id="generating_time" class="time_span">'.
|
2010-11-09 18:27:54 +00:00
|
|
|
tv_interval($t0, [ gettimeofday() ]).
|
2009-09-01 11:39:16 +00:00
|
|
|
' seconds </span>'.
|
|
|
|
' and '.
|
|
|
|
'<span id="generating_cmd">'.
|
|
|
|
$number_of_git_cmds.
|
|
|
|
'</span> git commands '.
|
|
|
|
" to generate.\n";
|
|
|
|
print "</div>\n"; # class="page_footer"
|
|
|
|
}
|
|
|
|
|
2010-01-30 22:30:41 +00:00
|
|
|
if (defined $site_footer && -f $site_footer) {
|
2008-12-01 18:01:42 +00:00
|
|
|
insert_file($site_footer);
|
2006-10-03 12:49:03 +00:00
|
|
|
}
|
|
|
|
|
2010-12-15 19:32:57 +00:00
|
|
|
print qq!<script type="text/javascript" src="!.esc_url($javascript).qq!"></script>\n!;
|
2010-01-30 22:30:39 +00:00
|
|
|
if (defined $action &&
|
|
|
|
$action eq 'blame_incremental') {
|
gitweb: Create links leading to 'blame_incremental' using JavaScript
The new 'blame_incremental' view requires JavaScript to run. Not all
web browsers implement JavaScript (e.g. text browsers such as Lynx),
and not all users have JavaScript enabled. Therefore instead of
unconditionally linking to 'blame_incremental' view, we use JavaScript
to convert those links to lead to view utilizing JavaScript, by adding
'js=1' to link.
Currently the only action that takes 'js=1' into account is 'blame',
which then acts as if it was called as 'blame_incremental' action.
Possible enhancement would be to do JavaScript redirect by setting
window.location instead of modifying $format and $action in
git_blame_common() subroutine.
The only JavaScript-aware/using view is currently 'blame_incremental'.
While at it move reading JavaScript to git_footer_html() subroutine.
Note that in this view we do not add 'js=1' currently (even though
perhaps we should; note that for consistency we should also add 'js=1'
in links added by JavaScript part of 'blame_incremental').
This idea was originally implemented by Petr Baudis in
http://article.gmane.org/gmane.comp.version-control.git/47614
but it added <script> element with fixBlameLinks() function in page
header, to be added as onload event using 'onload' attribute of HTML
'body' element: <body onload="fixBlameLinks();">. This version adds
script at then end of page (in the page footer), and uses JavaScript
'window.onload=fixLinks();'. Also in Petr version only links marked
with 'blamelink' class were modified, and they were modified by
replacing "a=blame" by "a=blame_incremental"... which doesn't work for
path_info links, and might replace wrong part if there is "a=blame" in
project name, ref name or file name.
Slightly different solution was implemented by Martin Koegler in
http://thread.gmane.org/gmane.comp.version-control.git/47902/focus=47905
Here GitAddLinks() function was in gitweb.js file, not as contents of
<script> element. It was also included in page header (in <head>
element) though, which means waiting for a script to load (and run).
It was smarter in that to "fix" (modify) link, it split URL, modified
value of 'a' parameter, and then recreated modified link. It avoids
trouble with "a=blame" as substring in project name or file name, but
it doesn't work with path_info URL/link in the way it was written.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:19 +00:00
|
|
|
print qq!<script type="text/javascript">\n!.
|
|
|
|
qq!startBlame("!. href(action=>"blame_data", -replay=>1) .qq!",\n!.
|
|
|
|
qq! "!. href() .qq!");\n!.
|
|
|
|
qq!</script>\n!;
|
2009-11-26 20:12:15 +00:00
|
|
|
} elsif (gitweb_check_feature('javascript-actions')) {
|
gitweb: Create links leading to 'blame_incremental' using JavaScript
The new 'blame_incremental' view requires JavaScript to run. Not all
web browsers implement JavaScript (e.g. text browsers such as Lynx),
and not all users have JavaScript enabled. Therefore instead of
unconditionally linking to 'blame_incremental' view, we use JavaScript
to convert those links to lead to view utilizing JavaScript, by adding
'js=1' to link.
Currently the only action that takes 'js=1' into account is 'blame',
which then acts as if it was called as 'blame_incremental' action.
Possible enhancement would be to do JavaScript redirect by setting
window.location instead of modifying $format and $action in
git_blame_common() subroutine.
The only JavaScript-aware/using view is currently 'blame_incremental'.
While at it move reading JavaScript to git_footer_html() subroutine.
Note that in this view we do not add 'js=1' currently (even though
perhaps we should; note that for consistency we should also add 'js=1'
in links added by JavaScript part of 'blame_incremental').
This idea was originally implemented by Petr Baudis in
http://article.gmane.org/gmane.comp.version-control.git/47614
but it added <script> element with fixBlameLinks() function in page
header, to be added as onload event using 'onload' attribute of HTML
'body' element: <body onload="fixBlameLinks();">. This version adds
script at then end of page (in the page footer), and uses JavaScript
'window.onload=fixLinks();'. Also in Petr version only links marked
with 'blamelink' class were modified, and they were modified by
replacing "a=blame" by "a=blame_incremental"... which doesn't work for
path_info links, and might replace wrong part if there is "a=blame" in
project name, ref name or file name.
Slightly different solution was implemented by Martin Koegler in
http://thread.gmane.org/gmane.comp.version-control.git/47902/focus=47905
Here GitAddLinks() function was in gitweb.js file, not as contents of
<script> element. It was also included in page header (in <head>
element) though, which means waiting for a script to load (and run).
It was smarter in that to "fix" (modify) link, it split URL, modified
value of 'a' parameter, and then recreated modified link. It avoids
trouble with "a=blame" as substring in project name or file name, but
it doesn't work with path_info URL/link in the way it was written.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:19 +00:00
|
|
|
print qq!<script type="text/javascript">\n!.
|
|
|
|
qq!window.onload = fixLinks;\n!.
|
|
|
|
qq!</script>\n!;
|
|
|
|
}
|
|
|
|
|
2006-10-03 12:49:03 +00:00
|
|
|
print "</body>\n" .
|
2006-07-31 19:22:15 +00:00
|
|
|
"</html>";
|
|
|
|
}
|
|
|
|
|
2010-02-07 20:51:18 +00:00
|
|
|
# die_error(<http_status_code>, <error_message>[, <detailed_html_description>])
|
2008-06-19 20:03:21 +00:00
|
|
|
# Example: die_error(404, 'Hash not found')
|
|
|
|
# By convention, use the following status codes (as defined in RFC 2616):
|
|
|
|
# 400: Invalid or missing CGI parameters, or
|
|
|
|
# requested object exists but has wrong type.
|
|
|
|
# 403: Requested feature (like "pickaxe" or "snapshot") not enabled on
|
|
|
|
# this server or project.
|
|
|
|
# 404: Requested object/revision/project doesn't exist.
|
|
|
|
# 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).
|
2010-01-30 22:30:39 +00:00
|
|
|
# 503: The server is currently unavailable (because it is overloaded,
|
|
|
|
# or down for maintenance). Generally, this is a temporary state.
|
2006-07-31 19:22:15 +00:00
|
|
|
sub die_error {
|
2008-06-19 20:03:21 +00:00
|
|
|
my $status = shift || 500;
|
2010-02-07 20:52:25 +00:00
|
|
|
my $error = esc_html(shift) || "Internal Server Error";
|
2010-01-30 22:30:44 +00:00
|
|
|
my $extra = shift;
|
2010-04-24 14:00:04 +00:00
|
|
|
my %opts = @_;
|
2008-06-19 20:03:21 +00:00
|
|
|
|
2010-01-30 22:30:39 +00:00
|
|
|
my %http_responses = (
|
|
|
|
400 => '400 Bad Request',
|
|
|
|
403 => '403 Forbidden',
|
|
|
|
404 => '404 Not Found',
|
|
|
|
500 => '500 Internal Server Error',
|
|
|
|
503 => '503 Service Unavailable',
|
|
|
|
);
|
2010-04-24 14:00:04 +00:00
|
|
|
git_header_html($http_responses{$status}, undef, %opts);
|
2006-08-22 21:42:53 +00:00
|
|
|
print <<EOF;
|
|
|
|
<div class="page_body">
|
|
|
|
<br /><br />
|
|
|
|
$status - $error
|
|
|
|
<br />
|
|
|
|
EOF
|
2010-01-30 22:30:44 +00:00
|
|
|
if (defined $extra) {
|
|
|
|
print "<hr />\n" .
|
|
|
|
"$extra\n";
|
|
|
|
}
|
|
|
|
print "</div>\n";
|
|
|
|
|
2005-08-07 18:21:04 +00:00
|
|
|
git_footer_html();
|
2010-04-24 14:00:04 +00:00
|
|
|
goto DONE_GITWEB
|
|
|
|
unless ($opts{'-error_handler'});
|
2005-08-07 17:49:46 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ----------------------------------------------------------------------
|
|
|
|
## functions printing or outputting HTML: navigation
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub git_print_page_nav {
|
2006-07-31 19:22:15 +00:00
|
|
|
my ($current, $suppress, $head, $treehead, $treebase, $extra) = @_;
|
|
|
|
$extra = '' if !defined $extra; # pager or formats
|
|
|
|
|
|
|
|
my @navs = qw(summary shortlog log commit commitdiff tree);
|
|
|
|
if ($suppress) {
|
|
|
|
@navs = grep { $_ ne $suppress } @navs;
|
|
|
|
}
|
|
|
|
|
2006-08-15 22:24:30 +00:00
|
|
|
my %arg = map { $_ => {action=>$_} } @navs;
|
2006-07-31 19:22:15 +00:00
|
|
|
if (defined $head) {
|
|
|
|
for (qw(commit commitdiff)) {
|
2007-04-01 20:22:21 +00:00
|
|
|
$arg{$_}{'hash'} = $head;
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
if ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {
|
|
|
|
for (qw(shortlog log)) {
|
2007-04-01 20:22:21 +00:00
|
|
|
$arg{$_}{'hash'} = $head;
|
2005-12-07 09:12:55 +00:00
|
|
|
}
|
2005-12-07 08:44:06 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-02 14:36:52 +00:00
|
|
|
|
2007-04-01 20:22:21 +00:00
|
|
|
$arg{'tree'}{'hash'} = $treehead if defined $treehead;
|
|
|
|
$arg{'tree'}{'hash_base'} = $treebase if defined $treebase;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2008-11-29 21:02:08 +00:00
|
|
|
my @actions = gitweb_get_feature('actions');
|
2008-10-11 22:02:32 +00:00
|
|
|
my %repl = (
|
|
|
|
'%' => '%',
|
|
|
|
'n' => $project, # project name
|
|
|
|
'f' => $git_dir, # project path within filesystem
|
|
|
|
'h' => $treehead || '', # current hash ('h' parameter)
|
|
|
|
'b' => $treebase || '', # hash base ('hb' parameter)
|
|
|
|
);
|
2008-10-02 14:36:52 +00:00
|
|
|
while (@actions) {
|
2008-10-11 22:02:32 +00:00
|
|
|
my ($label, $link, $pos) = splice(@actions,0,3);
|
|
|
|
# insert
|
2008-10-02 14:36:52 +00:00
|
|
|
@navs = map { $_ eq $pos ? ($_, $label) : $_ } @navs;
|
|
|
|
# munch munch
|
2008-10-11 22:02:32 +00:00
|
|
|
$link =~ s/%([%nfhb])/$repl{$1}/g;
|
2008-10-02 14:36:52 +00:00
|
|
|
$arg{$label}{'_href'} = $link;
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
print "<div class=\"page_nav\">\n" .
|
|
|
|
(join " | ",
|
2006-08-15 22:24:30 +00:00
|
|
|
map { $_ eq $current ?
|
2008-10-02 14:36:52 +00:00
|
|
|
$_ : $cgi->a({-href => ($arg{$_}{_href} ? $arg{$_}{_href} : href(%{$arg{$_}}))}, "$_")
|
2006-08-15 22:24:30 +00:00
|
|
|
} @navs);
|
2006-07-31 19:22:15 +00:00
|
|
|
print "<br/>\n$extra<br/>\n" .
|
|
|
|
"</div>\n";
|
2005-12-07 08:44:06 +00:00
|
|
|
}
|
|
|
|
|
2010-11-11 12:26:12 +00:00
|
|
|
# returns a submenu for the nagivation of the refs views (tags, heads,
|
|
|
|
# remotes) with the current view disabled and the remotes view only
|
|
|
|
# available if the feature is enabled
|
|
|
|
sub format_ref_views {
|
|
|
|
my ($current) = @_;
|
|
|
|
my @ref_views = qw{tags heads};
|
|
|
|
push @ref_views, 'remotes' if gitweb_check_feature('remote_heads');
|
|
|
|
return join " | ", map {
|
|
|
|
$_ eq $current ? $_ :
|
|
|
|
$cgi->a({-href => href(action=>$_)}, $_)
|
|
|
|
} @ref_views
|
|
|
|
}
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub format_paging_nav {
|
2009-11-13 01:02:14 +00:00
|
|
|
my ($action, $page, $has_next_link) = @_;
|
2006-07-31 19:22:15 +00:00
|
|
|
my $paging_nav;
|
2006-07-31 00:21:52 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
|
|
|
|
if ($page > 0) {
|
2009-11-13 01:02:14 +00:00
|
|
|
$paging_nav .=
|
|
|
|
$cgi->a({-href => href(-replay=>1, page=>undef)}, "first") .
|
|
|
|
" ⋅ " .
|
2007-11-01 12:06:28 +00:00
|
|
|
$cgi->a({-href => href(-replay=>1, page=>$page-1),
|
2006-08-10 10:38:47 +00:00
|
|
|
-accesskey => "p", -title => "Alt-p"}, "prev");
|
2006-07-31 19:22:15 +00:00
|
|
|
} else {
|
2009-11-13 01:02:14 +00:00
|
|
|
$paging_nav .= "first ⋅ prev";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
|
2008-05-27 23:25:42 +00:00
|
|
|
if ($has_next_link) {
|
2006-07-31 19:22:15 +00:00
|
|
|
$paging_nav .= " ⋅ " .
|
2007-11-01 12:06:28 +00:00
|
|
|
$cgi->a({-href => href(-replay=>1, page=>$page+1),
|
2006-08-10 10:38:47 +00:00
|
|
|
-accesskey => "n", -title => "Alt-n"}, "next");
|
2006-07-31 19:22:15 +00:00
|
|
|
} else {
|
|
|
|
$paging_nav .= " ⋅ next";
|
2006-07-31 00:21:52 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
|
|
|
|
return $paging_nav;
|
2006-07-31 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ......................................................................
|
|
|
|
## functions printing or outputting HTML: div
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
sub git_print_header_div {
|
2006-07-31 19:22:15 +00:00
|
|
|
my ($action, $title, $hash, $hash_base) = @_;
|
2006-08-15 22:24:30 +00:00
|
|
|
my %args = ();
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2007-04-01 20:22:21 +00:00
|
|
|
$args{'action'} = $action;
|
|
|
|
$args{'hash'} = $hash if $hash;
|
|
|
|
$args{'hash_base'} = $hash_base if $hash_base;
|
2006-07-31 19:22:15 +00:00
|
|
|
|
|
|
|
print "<div class=\"header\">\n" .
|
2006-08-15 22:24:30 +00:00
|
|
|
$cgi->a({-href => href(%args), -class => "title"},
|
|
|
|
$title ? $title : $action) .
|
|
|
|
"\n</div>\n";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
2005-08-07 18:23:12 +00:00
|
|
|
|
2010-11-11 12:26:15 +00:00
|
|
|
sub format_repo_url {
|
|
|
|
my ($name, $url) = @_;
|
|
|
|
return "<tr class=\"metadata_url\"><td>$name</td><td>$url</td></tr>\n";
|
|
|
|
}
|
|
|
|
|
2010-11-11 12:26:16 +00:00
|
|
|
# Group output by placing it in a DIV element and adding a header.
|
|
|
|
# Options for start_div() can be provided by passing a hash reference as the
|
|
|
|
# first parameter to the function.
|
|
|
|
# Options to git_print_header_div() can be provided by passing an array
|
|
|
|
# reference. This must follow the options to start_div if they are present.
|
|
|
|
# The content can be a scalar, which is output as-is, a scalar reference, which
|
|
|
|
# is output after html escaping, an IO handle passed either as *handle or
|
|
|
|
# *handle{IO}, or a function reference. In the latter case all following
|
|
|
|
# parameters will be taken as argument to the content function call.
|
|
|
|
sub git_print_section {
|
|
|
|
my ($div_args, $header_args, $content);
|
|
|
|
my $arg = shift;
|
|
|
|
if (ref($arg) eq 'HASH') {
|
|
|
|
$div_args = $arg;
|
|
|
|
$arg = shift;
|
|
|
|
}
|
|
|
|
if (ref($arg) eq 'ARRAY') {
|
|
|
|
$header_args = $arg;
|
|
|
|
$arg = shift;
|
|
|
|
}
|
|
|
|
$content = $arg;
|
|
|
|
|
|
|
|
print $cgi->start_div($div_args);
|
|
|
|
git_print_header_div(@$header_args);
|
|
|
|
|
|
|
|
if (ref($content) eq 'CODE') {
|
|
|
|
$content->(@_);
|
|
|
|
} elsif (ref($content) eq 'SCALAR') {
|
|
|
|
print esc_html($$content);
|
|
|
|
} elsif (ref($content) eq 'GLOB' or ref($content) eq 'IO::Handle') {
|
|
|
|
print <$content>;
|
|
|
|
} elsif (!ref($content) && defined($content)) {
|
|
|
|
print $content;
|
|
|
|
}
|
|
|
|
|
|
|
|
print $cgi->end_div;
|
|
|
|
}
|
|
|
|
|
2009-06-29 22:00:48 +00:00
|
|
|
sub print_local_time {
|
2010-01-30 22:30:42 +00:00
|
|
|
print format_local_time(@_);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub format_local_time {
|
|
|
|
my $localtime = '';
|
2009-06-29 22:00:48 +00:00
|
|
|
my %date = @_;
|
|
|
|
if ($date{'hour_local'} < 6) {
|
2010-01-30 22:30:42 +00:00
|
|
|
$localtime .= sprintf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
|
2009-06-29 22:00:48 +00:00
|
|
|
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
|
|
|
|
} else {
|
2010-01-30 22:30:42 +00:00
|
|
|
$localtime .= sprintf(" (%02d:%02d %s)",
|
2009-06-29 22:00:48 +00:00
|
|
|
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
|
|
|
|
}
|
2010-01-30 22:30:42 +00:00
|
|
|
|
|
|
|
return $localtime;
|
2009-06-29 22:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Outputs the author name and date in long form
|
2006-08-28 12:48:12 +00:00
|
|
|
sub git_print_authorship {
|
|
|
|
my $co = shift;
|
2009-06-29 22:00:48 +00:00
|
|
|
my %opts = @_;
|
|
|
|
my $tag = $opts{-tag} || 'div';
|
2009-10-16 04:14:59 +00:00
|
|
|
my $author = $co->{'author_name'};
|
2006-08-28 12:48:12 +00:00
|
|
|
|
2006-08-28 21:17:31 +00:00
|
|
|
my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'});
|
2009-06-29 22:00:48 +00:00
|
|
|
print "<$tag class=\"author_date\">" .
|
2009-10-16 04:14:59 +00:00
|
|
|
format_search_author($author, "author", esc_html($author)) .
|
2006-08-28 21:17:31 +00:00
|
|
|
" [$ad{'rfc2822'}";
|
2009-06-29 22:00:48 +00:00
|
|
|
print_local_time(%ad) if ($opts{-localtime});
|
2009-06-29 22:00:51 +00:00
|
|
|
print "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1)
|
|
|
|
. "</$tag>\n";
|
2009-06-29 22:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Outputs table rows containing the full author or committer information,
|
2010-08-22 11:12:12 +00:00
|
|
|
# in the format expected for 'commit' view (& similar).
|
2009-06-29 22:00:48 +00:00
|
|
|
# Parameters are a commit hash reference, followed by the list of people
|
2010-08-22 11:12:12 +00:00
|
|
|
# to output information for. If the list is empty it defaults to both
|
2009-06-29 22:00:48 +00:00
|
|
|
# author and committer.
|
|
|
|
sub git_print_authorship_rows {
|
|
|
|
my $co = shift;
|
|
|
|
# too bad we can't use @people = @_ || ('author', 'committer')
|
|
|
|
my @people = @_;
|
|
|
|
@people = ('author', 'committer') unless @people;
|
|
|
|
foreach my $who (@people) {
|
|
|
|
my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"});
|
2009-10-16 04:14:59 +00:00
|
|
|
print "<tr><td>$who</td><td>" .
|
|
|
|
format_search_author($co->{"${who}_name"}, $who,
|
|
|
|
esc_html($co->{"${who}_name"})) . " " .
|
|
|
|
format_search_author($co->{"${who}_email"}, $who,
|
|
|
|
esc_html("<" . $co->{"${who}_email"} . ">")) .
|
|
|
|
"</td><td rowspan=\"2\">" .
|
2009-06-29 22:00:51 +00:00
|
|
|
git_get_avatar($co->{"${who}_email"}, -size => 'double') .
|
|
|
|
"</td></tr>\n" .
|
2009-06-29 22:00:48 +00:00
|
|
|
"<tr>" .
|
|
|
|
"<td></td><td> $wd{'rfc2822'}";
|
|
|
|
print_local_time(%wd);
|
|
|
|
print "</td>" .
|
|
|
|
"</tr>\n";
|
2006-08-28 21:17:31 +00:00
|
|
|
}
|
2006-08-28 12:48:12 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub git_print_page_path {
|
|
|
|
my $name = shift;
|
|
|
|
my $type = shift;
|
2006-08-17 17:39:29 +00:00
|
|
|
my $hb = shift;
|
2005-08-07 18:23:12 +00:00
|
|
|
|
2006-10-21 15:53:55 +00:00
|
|
|
|
|
|
|
print "<div class=\"page_path\">";
|
|
|
|
print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
|
2007-06-03 15:42:44 +00:00
|
|
|
-title => 'tree root'}, to_utf8("[$project]"));
|
2006-10-21 15:53:55 +00:00
|
|
|
print " / ";
|
|
|
|
if (defined $name) {
|
2006-09-04 16:17:58 +00:00
|
|
|
my @dirname = split '/', $name;
|
|
|
|
my $basename = pop @dirname;
|
|
|
|
my $fullname = '';
|
|
|
|
|
|
|
|
foreach my $dir (@dirname) {
|
2006-09-21 00:05:50 +00:00
|
|
|
$fullname .= ($fullname ? '/' : '') . $dir;
|
2006-09-04 16:17:58 +00:00
|
|
|
print $cgi->a({-href => href(action=>"tree", file_name=>$fullname,
|
|
|
|
hash_base=>$hb),
|
2007-03-07 01:21:25 +00:00
|
|
|
-title => $fullname}, esc_path($dir));
|
2006-09-22 23:00:12 +00:00
|
|
|
print " / ";
|
2006-09-04 16:17:58 +00:00
|
|
|
}
|
|
|
|
if (defined $type && $type eq 'blob') {
|
2006-08-22 14:52:50 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name,
|
2006-09-04 16:17:58 +00:00
|
|
|
hash_base=>$hb),
|
2007-03-07 01:21:25 +00:00
|
|
|
-title => $name}, esc_path($basename));
|
2006-09-04 16:17:58 +00:00
|
|
|
} elsif (defined $type && $type eq 'tree') {
|
|
|
|
print $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
|
|
|
|
hash_base=>$hb),
|
2007-03-07 01:21:25 +00:00
|
|
|
-title => $name}, esc_path($basename));
|
2006-10-21 15:53:55 +00:00
|
|
|
print " / ";
|
2006-08-17 17:39:29 +00:00
|
|
|
} else {
|
2006-11-08 10:48:56 +00:00
|
|
|
print esc_path($basename);
|
2006-08-17 17:39:29 +00:00
|
|
|
}
|
2005-08-07 18:23:12 +00:00
|
|
|
}
|
2006-10-21 15:53:55 +00:00
|
|
|
print "<br/></div>\n";
|
2005-08-07 18:23:12 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 17:11:29 +00:00
|
|
|
sub git_print_log {
|
2006-08-17 09:21:23 +00:00
|
|
|
my $log = shift;
|
2006-08-28 12:48:10 +00:00
|
|
|
my %opts = @_;
|
2006-08-17 09:21:23 +00:00
|
|
|
|
2006-08-28 12:48:10 +00:00
|
|
|
if ($opts{'-remove_title'}) {
|
|
|
|
# remove title, i.e. first line of log
|
|
|
|
shift @$log;
|
|
|
|
}
|
2006-08-17 09:21:23 +00:00
|
|
|
# remove leading empty lines
|
|
|
|
while (defined $log->[0] && $log->[0] eq "") {
|
|
|
|
shift @$log;
|
|
|
|
}
|
|
|
|
|
|
|
|
# print log
|
|
|
|
my $signoff = 0;
|
|
|
|
my $empty = 0;
|
|
|
|
foreach my $line (@$log) {
|
2006-08-28 12:48:10 +00:00
|
|
|
if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) {
|
|
|
|
$signoff = 1;
|
2006-08-28 12:48:13 +00:00
|
|
|
$empty = 0;
|
2006-08-28 12:48:10 +00:00
|
|
|
if (! $opts{'-remove_signoff'}) {
|
|
|
|
print "<span class=\"signoff\">" . esc_html($line) . "</span><br/>\n";
|
|
|
|
next;
|
|
|
|
} else {
|
|
|
|
# remove signoff lines
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$signoff = 0;
|
|
|
|
}
|
|
|
|
|
2006-08-17 09:21:23 +00:00
|
|
|
# print only one empty line
|
|
|
|
# do not print empty line after signoff
|
|
|
|
if ($line eq "") {
|
|
|
|
next if ($empty || $signoff);
|
|
|
|
$empty = 1;
|
|
|
|
} else {
|
|
|
|
$empty = 0;
|
|
|
|
}
|
2006-08-28 12:48:10 +00:00
|
|
|
|
|
|
|
print format_log_line_html($line) . "<br/>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($opts{'-final_empty_line'}) {
|
|
|
|
# end with single empty line
|
|
|
|
print "<br/>\n" unless $empty;
|
2006-08-17 09:21:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-10 12:25:46 +00:00
|
|
|
# return link target (what link points to)
|
|
|
|
sub git_get_link_target {
|
|
|
|
my $hash = shift;
|
|
|
|
my $link_target;
|
|
|
|
|
|
|
|
# read link
|
|
|
|
open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
|
|
|
|
or return;
|
|
|
|
{
|
2009-05-11 01:29:40 +00:00
|
|
|
local $/ = undef;
|
2006-12-10 12:25:46 +00:00
|
|
|
$link_target = <$fd>;
|
|
|
|
}
|
|
|
|
close $fd
|
|
|
|
or return;
|
|
|
|
|
|
|
|
return $link_target;
|
|
|
|
}
|
|
|
|
|
2006-12-10 12:25:48 +00:00
|
|
|
# given link target, and the directory (basedir) the link is in,
|
|
|
|
# return target of link relative to top directory (top tree);
|
|
|
|
# return undef if it is not possible (including absolute links).
|
|
|
|
sub normalize_link_target {
|
2009-05-11 17:45:11 +00:00
|
|
|
my ($link_target, $basedir) = @_;
|
2006-12-10 12:25:48 +00:00
|
|
|
|
|
|
|
# absolute symlinks (beginning with '/') cannot be normalized
|
|
|
|
return if (substr($link_target, 0, 1) eq '/');
|
|
|
|
|
|
|
|
# normalize link target to path from top (root) tree (dir)
|
|
|
|
my $path;
|
|
|
|
if ($basedir) {
|
|
|
|
$path = $basedir . '/' . $link_target;
|
|
|
|
} else {
|
|
|
|
# we are in top (root) tree (dir)
|
|
|
|
$path = $link_target;
|
|
|
|
}
|
|
|
|
|
|
|
|
# remove //, /./, and /../
|
|
|
|
my @path_parts;
|
|
|
|
foreach my $part (split('/', $path)) {
|
|
|
|
# discard '.' and ''
|
|
|
|
next if (!$part || $part eq '.');
|
|
|
|
# handle '..'
|
|
|
|
if ($part eq '..') {
|
|
|
|
if (@path_parts) {
|
|
|
|
pop @path_parts;
|
|
|
|
} else {
|
|
|
|
# link leads outside repository (outside top dir)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
push @path_parts, $part;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$path = join('/', @path_parts);
|
|
|
|
|
|
|
|
return $path;
|
|
|
|
}
|
2006-12-10 12:25:46 +00:00
|
|
|
|
2006-08-30 22:35:07 +00:00
|
|
|
# print tree entry (row of git_tree), but without encompassing <tr> element
|
|
|
|
sub git_print_tree_entry {
|
|
|
|
my ($t, $basedir, $hash_base, $have_blame) = @_;
|
|
|
|
|
|
|
|
my %base_key = ();
|
2006-12-10 12:25:46 +00:00
|
|
|
$base_key{'hash_base'} = $hash_base if defined $hash_base;
|
2006-08-30 22:35:07 +00:00
|
|
|
|
2006-09-26 05:38:16 +00:00
|
|
|
# The format of a table row is: mode list link. Where mode is
|
|
|
|
# the mode of the entry, list is the name of the entry, an href,
|
|
|
|
# and link is the action links of the entry.
|
|
|
|
|
2006-08-30 22:35:07 +00:00
|
|
|
print "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n";
|
2009-09-07 12:40:00 +00:00
|
|
|
if (exists $t->{'size'}) {
|
|
|
|
print "<td class=\"size\">$t->{'size'}</td>\n";
|
|
|
|
}
|
2006-08-30 22:35:07 +00:00
|
|
|
if ($t->{'type'} eq "blob") {
|
|
|
|
print "<td class=\"list\">" .
|
2006-09-26 05:38:16 +00:00
|
|
|
$cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
|
2006-10-21 15:52:19 +00:00
|
|
|
file_name=>"$basedir$t->{'name'}", %base_key),
|
2006-12-10 12:25:46 +00:00
|
|
|
-class => "list"}, esc_path($t->{'name'}));
|
|
|
|
if (S_ISLNK(oct $t->{'mode'})) {
|
|
|
|
my $link_target = git_get_link_target($t->{'hash'});
|
|
|
|
if ($link_target) {
|
2009-05-11 17:45:11 +00:00
|
|
|
my $norm_target = normalize_link_target($link_target, $basedir);
|
2006-12-10 12:25:48 +00:00
|
|
|
if (defined $norm_target) {
|
|
|
|
print " -> " .
|
|
|
|
$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);
|
|
|
|
}
|
2006-12-10 12:25:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
print "</td>\n";
|
2006-09-26 05:38:16 +00:00
|
|
|
print "<td class=\"link\">";
|
2006-10-24 03:36:10 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
|
2006-12-10 12:25:46 +00:00
|
|
|
file_name=>"$basedir$t->{'name'}", %base_key)},
|
|
|
|
"blob");
|
2006-08-30 22:35:07 +00:00
|
|
|
if ($have_blame) {
|
2006-10-24 03:36:10 +00:00
|
|
|
print " | " .
|
|
|
|
$cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'},
|
2006-12-10 12:25:46 +00:00
|
|
|
file_name=>"$basedir$t->{'name'}", %base_key)},
|
|
|
|
"blame");
|
2006-08-30 22:35:07 +00:00
|
|
|
}
|
|
|
|
if (defined $hash_base) {
|
2006-10-24 03:36:10 +00:00
|
|
|
print " | " .
|
|
|
|
$cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
|
2006-08-30 22:35:07 +00:00
|
|
|
hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}")},
|
|
|
|
"history");
|
|
|
|
}
|
|
|
|
print " | " .
|
2006-09-29 16:57:43 +00:00
|
|
|
$cgi->a({-href => href(action=>"blob_plain", hash_base=>$hash_base,
|
2006-10-21 15:52:19 +00:00
|
|
|
file_name=>"$basedir$t->{'name'}")},
|
|
|
|
"raw");
|
2006-09-26 05:38:16 +00:00
|
|
|
print "</td>\n";
|
2006-08-30 22:35:07 +00:00
|
|
|
|
|
|
|
} elsif ($t->{'type'} eq "tree") {
|
2006-09-26 19:45:37 +00:00
|
|
|
print "<td class=\"list\">";
|
|
|
|
print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
|
2009-09-07 12:40:00 +00:00
|
|
|
file_name=>"$basedir$t->{'name'}",
|
|
|
|
%base_key)},
|
2006-11-08 10:48:56 +00:00
|
|
|
esc_path($t->{'name'}));
|
2006-09-26 19:45:37 +00:00
|
|
|
print "</td>\n";
|
|
|
|
print "<td class=\"link\">";
|
2006-10-24 03:36:10 +00:00
|
|
|
print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
|
2009-09-07 12:40:00 +00:00
|
|
|
file_name=>"$basedir$t->{'name'}",
|
|
|
|
%base_key)},
|
2006-12-10 12:25:46 +00:00
|
|
|
"tree");
|
2006-08-30 22:35:07 +00:00
|
|
|
if (defined $hash_base) {
|
2006-10-24 03:36:10 +00:00
|
|
|
print " | " .
|
|
|
|
$cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
|
2006-08-30 22:35:07 +00:00
|
|
|
file_name=>"$basedir$t->{'name'}")},
|
2007-07-28 14:27:31 +00:00
|
|
|
"history");
|
|
|
|
}
|
|
|
|
print "</td>\n";
|
|
|
|
} else {
|
|
|
|
# unknown object: we can only present history for it
|
|
|
|
# (this includes 'commit' object, i.e. submodule support)
|
|
|
|
print "<td class=\"list\">" .
|
|
|
|
esc_path($t->{'name'}) .
|
|
|
|
"</td>\n";
|
|
|
|
print "<td class=\"link\">";
|
|
|
|
if (defined $hash_base) {
|
|
|
|
print $cgi->a({-href => href(action=>"history",
|
|
|
|
hash_base=>$hash_base,
|
|
|
|
file_name=>"$basedir$t->{'name'}")},
|
2006-08-30 22:35:07 +00:00
|
|
|
"history");
|
|
|
|
}
|
|
|
|
print "</td>\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ......................................................................
|
|
|
|
## functions printing large fragments of HTML
|
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# get pre-image filenames for merge (combined) diff
|
2007-05-06 23:10:05 +00:00
|
|
|
sub fill_from_file_info {
|
|
|
|
my ($diff, @parents) = @_;
|
|
|
|
|
|
|
|
$diff->{'from_file'} = [ ];
|
|
|
|
$diff->{'from_file'}[$diff->{'nparents'} - 1] = undef;
|
|
|
|
for (my $i = 0; $i < $diff->{'nparents'}; $i++) {
|
|
|
|
if ($diff->{'status'}[$i] eq 'R' ||
|
|
|
|
$diff->{'status'}[$i] eq 'C') {
|
|
|
|
$diff->{'from_file'}[$i] =
|
|
|
|
git_get_path_by_hash($parents[$i], $diff->{'from_id'}[$i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $diff;
|
|
|
|
}
|
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# is current raw difftree line of file deletion
|
2007-06-08 11:27:42 +00:00
|
|
|
sub is_deleted {
|
|
|
|
my $diffinfo = shift;
|
|
|
|
|
2008-04-05 20:13:24 +00:00
|
|
|
return $diffinfo->{'to_id'} eq ('0' x 40);
|
2007-06-08 11:27:42 +00:00
|
|
|
}
|
2007-05-06 23:10:05 +00:00
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# does patch correspond to [previous] difftree raw line
|
|
|
|
# $diffinfo - hashref of parsed raw diff format
|
|
|
|
# $patchinfo - hashref of parsed patch diff format
|
|
|
|
# (the same keys as in $diffinfo)
|
|
|
|
sub is_patch_split {
|
|
|
|
my ($diffinfo, $patchinfo) = @_;
|
|
|
|
|
|
|
|
return defined $diffinfo && defined $patchinfo
|
2007-11-01 11:38:08 +00:00
|
|
|
&& $diffinfo->{'to_file'} eq $patchinfo->{'to_file'};
|
2007-10-30 00:35:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-14 00:18:33 +00:00
|
|
|
sub git_difftree_body {
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
my ($difftree, $hash, @parents) = @_;
|
|
|
|
my ($parent) = $parents[0];
|
2008-11-29 21:07:29 +00:00
|
|
|
my $have_blame = gitweb_check_feature('blame');
|
2006-08-14 00:18:33 +00:00
|
|
|
print "<div class=\"list_head\">\n";
|
|
|
|
if ($#{$difftree} > 10) {
|
|
|
|
print(($#{$difftree} + 1) . " files changed:\n");
|
|
|
|
}
|
|
|
|
print "</div>\n";
|
|
|
|
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
print "<table class=\"" .
|
|
|
|
(@parents > 1 ? "combined " : "") .
|
|
|
|
"diff_tree\">\n";
|
2007-06-08 11:24:56 +00:00
|
|
|
|
|
|
|
# header only for combined diff in 'commitdiff' view
|
2007-09-08 19:54:28 +00:00
|
|
|
my $has_header = @$difftree && @parents > 1 && $action eq 'commitdiff';
|
2007-06-08 11:24:56 +00:00
|
|
|
if ($has_header) {
|
|
|
|
# table header
|
|
|
|
print "<thead><tr>\n" .
|
|
|
|
"<th></th><th></th>\n"; # filename, patchN link
|
|
|
|
for (my $i = 0; $i < @parents; $i++) {
|
|
|
|
my $par = $parents[$i];
|
|
|
|
print "<th>" .
|
|
|
|
$cgi->a({-href => href(action=>"commitdiff",
|
|
|
|
hash=>$hash, hash_parent=>$par),
|
|
|
|
-title => 'commitdiff to parent number ' .
|
|
|
|
($i+1) . ': ' . substr($par,0,7)},
|
|
|
|
$i+1) .
|
|
|
|
" </th>\n";
|
|
|
|
}
|
|
|
|
print "</tr></thead>\n<tbody>\n";
|
|
|
|
}
|
|
|
|
|
gitweb: "alternate" starts with shade (i.e. 1)
When displaying a list of rows (difftree, shortlog, etc),
the first entry is now printed shaded, i.e. alternate is
initialized to 1, as opposed to non-shaded (alternate
initialized to 0).
This solves the problem when there is only one row to
display -- it is displayed shaded to visually indicate that
it is "active", part of a "list", etc.
(Compare this to the trivial case of more than one entry,
where the rows have alternating shade, thus suggesting
being part of a "list" of "active" entries, etc.)
Signed-off-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-28 23:47:50 +00:00
|
|
|
my $alternate = 1;
|
2006-08-28 12:48:14 +00:00
|
|
|
my $patchno = 0;
|
2006-08-14 00:18:33 +00:00
|
|
|
foreach my $line (@{$difftree}) {
|
2007-10-30 00:35:05 +00:00
|
|
|
my $diff = parsed_difftree_line($line);
|
2006-08-14 00:18:33 +00:00
|
|
|
|
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
|
|
|
|
2007-05-06 23:10:06 +00:00
|
|
|
if (exists $diff->{'nparents'}) { # combined diff
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
|
2007-05-06 23:10:06 +00:00
|
|
|
fill_from_file_info($diff, @parents)
|
|
|
|
unless exists $diff->{'from_file'};
|
2007-05-06 23:10:05 +00:00
|
|
|
|
2007-06-08 11:27:42 +00:00
|
|
|
if (!is_deleted($diff)) {
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
# file exists in the result (child) commit
|
|
|
|
print "<td>" .
|
2007-05-06 23:10:06 +00:00
|
|
|
$cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
|
|
|
|
file_name=>$diff->{'to_file'},
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
hash_base=>$hash),
|
2007-05-06 23:10:06 +00:00
|
|
|
-class => "list"}, esc_path($diff->{'to_file'})) .
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
"</td>\n";
|
|
|
|
} else {
|
|
|
|
print "<td>" .
|
2007-05-06 23:10:06 +00:00
|
|
|
esc_path($diff->{'to_file'}) .
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
"</td>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($action eq 'commitdiff') {
|
|
|
|
# link to patch
|
|
|
|
$patchno++;
|
|
|
|
print "<td class=\"link\">" .
|
|
|
|
$cgi->a({-href => "#patch$patchno"}, "patch") .
|
|
|
|
" | " .
|
|
|
|
"</td>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
my $has_history = 0;
|
|
|
|
my $not_deleted = 0;
|
2007-05-06 23:10:06 +00:00
|
|
|
for (my $i = 0; $i < $diff->{'nparents'}; $i++) {
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
my $hash_parent = $parents[$i];
|
2007-05-06 23:10:06 +00:00
|
|
|
my $from_hash = $diff->{'from_id'}[$i];
|
|
|
|
my $from_path = $diff->{'from_file'}[$i];
|
|
|
|
my $status = $diff->{'status'}[$i];
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
|
|
|
|
$has_history ||= ($status ne 'A');
|
|
|
|
$not_deleted ||= ($status ne 'D');
|
|
|
|
|
|
|
|
if ($status eq 'A') {
|
|
|
|
print "<td class=\"link\" align=\"right\"> | </td>\n";
|
|
|
|
} elsif ($status eq 'D') {
|
|
|
|
print "<td class=\"link\">" .
|
|
|
|
$cgi->a({-href => href(action=>"blob",
|
|
|
|
hash_base=>$hash,
|
|
|
|
hash=>$from_hash,
|
|
|
|
file_name=>$from_path)},
|
|
|
|
"blob" . ($i+1)) .
|
|
|
|
" | </td>\n";
|
|
|
|
} else {
|
2007-05-06 23:10:06 +00:00
|
|
|
if ($diff->{'to_id'} eq $from_hash) {
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
print "<td class=\"link nochange\">";
|
|
|
|
} else {
|
|
|
|
print "<td class=\"link\">";
|
|
|
|
}
|
|
|
|
print $cgi->a({-href => href(action=>"blobdiff",
|
2007-05-06 23:10:06 +00:00
|
|
|
hash=>$diff->{'to_id'},
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
hash_parent=>$from_hash,
|
|
|
|
hash_base=>$hash,
|
|
|
|
hash_parent_base=>$hash_parent,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'to_file'},
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
file_parent=>$from_path)},
|
|
|
|
"diff" . ($i+1)) .
|
|
|
|
" | </td>\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
print "<td class=\"link\">";
|
|
|
|
if ($not_deleted) {
|
|
|
|
print $cgi->a({-href => href(action=>"blob",
|
2007-05-06 23:10:06 +00:00
|
|
|
hash=>$diff->{'to_id'},
|
|
|
|
file_name=>$diff->{'to_file'},
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
hash_base=>$hash)},
|
|
|
|
"blob");
|
|
|
|
print " | " if ($has_history);
|
|
|
|
}
|
|
|
|
if ($has_history) {
|
|
|
|
print $cgi->a({-href => href(action=>"history",
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'to_file'},
|
gitweb: Add combined diff support to git_difftree_body
You have to pass all parents as final parameters of git_difftree_body
subroutine; the number of parents of a diff must be equal to the
number derived from parsing git-diff-tree output, raw combined diff
for git_difftree_body to display combined diff correctly (but it is
not checked).
Currently the possibility of displaying diffree of combined diff is
not used in gitweb code; git_difftree_body is always caled for
ordinary diff, and with only one parent.
Description of output for combined diff:
----------------------------------------
The difftree table for combined diff starts with a cell with pathname
of changed blob (changed file), which if possible is hidden link
(class="list") to the 'blob' view of final version (if it exists),
like for difftree for ordinary diff. If file was deleted in the final
commit then filename is not hyperlinked.
There is no cell with single file status (new, deleted, mode change,
rename), as for combined diff as there is no single status: different
parents might have different status.
If git_difftree_body was called from git_commitdiff (for 'commitdiff'
action) there is inner link to anchor to appropriate fragment (patch)
in patchset body; the "patch" link does not replace "diff" link like
for ordinary diff.
Each of "diff" links is in separate cell, contrary to output for
ordinary diff in which all links are (at least for now) in a single
cell.
For each parent, if file was not present we leave cell empty. If file
was deleted in the result, we provide link to 'blob' view. Otherwise
we provide link to 'commitdiff' view, even if patch (diff) consist
only of extended diff header, and contents is not changed (pure
rename, pure mode change). The only difference is that link to
"blobdiff" view with no contents change is with 'nochange' class.
At last, there is provided link to current version of file as "blob"
link, if the file was not deleted in the result, and lik to history of
a file, if there exists one. (The link to file history might be
confused, at least for now, by renames.)
Note that git-diff-tree raw output dor combined diff does not provide
filename before change for renames and copies; we use
git_get_path_by_hash to get "src" filename for renames (this means
additional call to git-ls-tree for a _whole_ tree).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-06 23:10:04 +00:00
|
|
|
hash_base=>$hash)},
|
|
|
|
"history");
|
|
|
|
}
|
|
|
|
print "</td>\n";
|
|
|
|
|
|
|
|
print "</tr>\n";
|
|
|
|
next; # instead of 'else' clause, to avoid extra indent
|
|
|
|
}
|
|
|
|
# else ordinary diff
|
|
|
|
|
2006-08-21 21:08:52 +00:00
|
|
|
my ($to_mode_oct, $to_mode_str, $to_file_type);
|
|
|
|
my ($from_mode_oct, $from_mode_str, $from_file_type);
|
2007-05-06 23:10:06 +00:00
|
|
|
if ($diff->{'to_mode'} ne ('0' x 6)) {
|
|
|
|
$to_mode_oct = oct $diff->{'to_mode'};
|
2006-08-21 21:08:52 +00:00
|
|
|
if (S_ISREG($to_mode_oct)) { # only for regular file
|
|
|
|
$to_mode_str = sprintf("%04o", $to_mode_oct & 0777); # permission bits
|
|
|
|
}
|
2007-05-06 23:10:06 +00:00
|
|
|
$to_file_type = file_type($diff->{'to_mode'});
|
2006-08-21 21:08:52 +00:00
|
|
|
}
|
2007-05-06 23:10:06 +00:00
|
|
|
if ($diff->{'from_mode'} ne ('0' x 6)) {
|
|
|
|
$from_mode_oct = oct $diff->{'from_mode'};
|
2011-02-19 15:27:42 +00:00
|
|
|
if (S_ISREG($from_mode_oct)) { # only for regular file
|
2006-08-21 21:08:52 +00:00
|
|
|
$from_mode_str = sprintf("%04o", $from_mode_oct & 0777); # permission bits
|
2006-08-14 00:18:33 +00:00
|
|
|
}
|
2007-05-06 23:10:06 +00:00
|
|
|
$from_file_type = file_type($diff->{'from_mode'});
|
2006-08-21 21:08:52 +00:00
|
|
|
}
|
|
|
|
|
2007-05-06 23:10:06 +00:00
|
|
|
if ($diff->{'status'} eq "A") { # created
|
2006-08-21 21:08:52 +00:00
|
|
|
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>";
|
2006-09-28 00:23:25 +00:00
|
|
|
print "<td>";
|
2007-05-06 23:10:06 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
|
|
|
|
hash_base=>$hash, file_name=>$diff->{'file'}),
|
|
|
|
-class => "list"}, esc_path($diff->{'file'}));
|
2006-09-28 00:23:25 +00:00
|
|
|
print "</td>\n";
|
|
|
|
print "<td>$mode_chng</td>\n";
|
|
|
|
print "<td class=\"link\">";
|
2006-09-04 16:19:58 +00:00
|
|
|
if ($action eq 'commitdiff') {
|
2006-08-28 12:48:14 +00:00
|
|
|
# link to patch
|
|
|
|
$patchno++;
|
2006-09-28 00:23:25 +00:00
|
|
|
print $cgi->a({-href => "#patch$patchno"}, "patch");
|
2006-11-19 21:51:39 +00:00
|
|
|
print " | ";
|
2006-08-28 12:48:14 +00:00
|
|
|
}
|
2007-05-06 23:10:06 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
|
|
|
|
hash_base=>$hash, file_name=>$diff->{'file'})},
|
2007-01-08 01:10:42 +00:00
|
|
|
"blob");
|
2006-08-28 12:48:14 +00:00
|
|
|
print "</td>\n";
|
2006-08-14 00:18:33 +00:00
|
|
|
|
2007-05-06 23:10:06 +00:00
|
|
|
} elsif ($diff->{'status'} eq "D") { # deleted
|
2006-08-21 21:08:52 +00:00
|
|
|
my $mode_chng = "<span class=\"file_status deleted\">[deleted $from_file_type]</span>";
|
2006-09-28 00:23:25 +00:00
|
|
|
print "<td>";
|
2007-05-06 23:10:06 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'},
|
|
|
|
hash_base=>$parent, file_name=>$diff->{'file'}),
|
|
|
|
-class => "list"}, esc_path($diff->{'file'}));
|
2006-09-28 00:23:25 +00:00
|
|
|
print "</td>\n";
|
|
|
|
print "<td>$mode_chng</td>\n";
|
|
|
|
print "<td class=\"link\">";
|
2006-09-04 16:19:58 +00:00
|
|
|
if ($action eq 'commitdiff') {
|
2006-08-28 12:48:14 +00:00
|
|
|
# link to patch
|
|
|
|
$patchno++;
|
2006-09-28 00:23:25 +00:00
|
|
|
print $cgi->a({-href => "#patch$patchno"}, "patch");
|
|
|
|
print " | ";
|
2006-08-28 12:48:14 +00:00
|
|
|
}
|
2007-05-06 23:10:06 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'},
|
|
|
|
hash_base=>$parent, file_name=>$diff->{'file'})},
|
2006-11-19 21:51:39 +00:00
|
|
|
"blob") . " | ";
|
2006-11-08 20:22:04 +00:00
|
|
|
if ($have_blame) {
|
2006-11-19 21:51:39 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blame", hash_base=>$parent,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'file'})},
|
2006-11-19 21:51:39 +00:00
|
|
|
"blame") . " | ";
|
2006-11-08 20:22:04 +00:00
|
|
|
}
|
2006-08-28 12:48:14 +00:00
|
|
|
print $cgi->a({-href => href(action=>"history", hash_base=>$parent,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'file'})},
|
2006-10-21 15:52:19 +00:00
|
|
|
"history");
|
2006-09-28 00:23:25 +00:00
|
|
|
print "</td>\n";
|
2006-08-14 00:18:33 +00:00
|
|
|
|
2007-05-06 23:10:06 +00:00
|
|
|
} elsif ($diff->{'status'} eq "M" || $diff->{'status'} eq "T") { # modified, or type changed
|
2006-08-14 00:18:33 +00:00
|
|
|
my $mode_chnge = "";
|
2007-05-06 23:10:06 +00:00
|
|
|
if ($diff->{'from_mode'} != $diff->{'to_mode'}) {
|
2006-08-21 21:08:52 +00:00
|
|
|
$mode_chnge = "<span class=\"file_status mode_chnge\">[changed";
|
2007-01-03 19:47:24 +00:00
|
|
|
if ($from_file_type ne $to_file_type) {
|
2006-08-21 21:08:52 +00:00
|
|
|
$mode_chnge .= " from $from_file_type to $to_file_type";
|
2006-08-14 00:18:33 +00:00
|
|
|
}
|
2006-08-21 21:08:52 +00:00
|
|
|
if (($from_mode_oct & 0777) != ($to_mode_oct & 0777)) {
|
|
|
|
if ($from_mode_str && $to_mode_str) {
|
|
|
|
$mode_chnge .= " mode: $from_mode_str->$to_mode_str";
|
|
|
|
} elsif ($to_mode_str) {
|
|
|
|
$mode_chnge .= " mode: $to_mode_str";
|
2006-08-14 00:18:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
$mode_chnge .= "]</span>\n";
|
|
|
|
}
|
|
|
|
print "<td>";
|
2007-05-06 23:10:06 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
|
|
|
|
hash_base=>$hash, file_name=>$diff->{'file'}),
|
|
|
|
-class => "list"}, esc_path($diff->{'file'}));
|
2006-09-28 00:23:25 +00:00
|
|
|
print "</td>\n";
|
|
|
|
print "<td>$mode_chnge</td>\n";
|
|
|
|
print "<td class=\"link\">";
|
2006-10-31 16:36:27 +00:00
|
|
|
if ($action eq 'commitdiff') {
|
|
|
|
# link to patch
|
|
|
|
$patchno++;
|
|
|
|
print $cgi->a({-href => "#patch$patchno"}, "patch") .
|
|
|
|
" | ";
|
2007-05-06 23:10:06 +00:00
|
|
|
} elsif ($diff->{'to_id'} ne $diff->{'from_id'}) {
|
2006-10-31 16:36:27 +00:00
|
|
|
# "commit" view and modified file (not onlu mode changed)
|
|
|
|
print $cgi->a({-href => href(action=>"blobdiff",
|
2007-05-06 23:10:06 +00:00
|
|
|
hash=>$diff->{'to_id'}, hash_parent=>$diff->{'from_id'},
|
2006-10-31 16:36:27 +00:00
|
|
|
hash_base=>$hash, hash_parent_base=>$parent,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'file'})},
|
2006-10-31 16:36:27 +00:00
|
|
|
"diff") .
|
|
|
|
" | ";
|
2006-08-14 00:18:33 +00:00
|
|
|
}
|
2007-05-06 23:10:06 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
|
|
|
|
hash_base=>$hash, file_name=>$diff->{'file'})},
|
2006-11-19 21:51:39 +00:00
|
|
|
"blob") . " | ";
|
2006-11-08 20:22:04 +00:00
|
|
|
if ($have_blame) {
|
2006-11-19 21:51:39 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blame", hash_base=>$hash,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'file'})},
|
2006-11-19 21:51:39 +00:00
|
|
|
"blame") . " | ";
|
2006-11-08 20:22:04 +00:00
|
|
|
}
|
2006-09-28 00:24:49 +00:00
|
|
|
print $cgi->a({-href => href(action=>"history", hash_base=>$hash,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'file'})},
|
2006-10-21 15:52:19 +00:00
|
|
|
"history");
|
2006-08-14 00:18:33 +00:00
|
|
|
print "</td>\n";
|
|
|
|
|
2007-05-06 23:10:06 +00:00
|
|
|
} elsif ($diff->{'status'} eq "R" || $diff->{'status'} eq "C") { # renamed or copied
|
2006-08-21 21:08:52 +00:00
|
|
|
my %status_name = ('R' => 'moved', 'C' => 'copied');
|
2007-05-06 23:10:06 +00:00
|
|
|
my $nstatus = $status_name{$diff->{'status'}};
|
2006-08-14 00:18:33 +00:00
|
|
|
my $mode_chng = "";
|
2007-05-06 23:10:06 +00:00
|
|
|
if ($diff->{'from_mode'} != $diff->{'to_mode'}) {
|
2006-08-21 21:08:52 +00:00
|
|
|
# mode also for directories, so we cannot use $to_mode_str
|
|
|
|
$mode_chng = sprintf(", mode: %04o", $to_mode_oct & 0777);
|
2006-08-14 00:18:33 +00:00
|
|
|
}
|
|
|
|
print "<td>" .
|
2006-08-21 21:08:52 +00:00
|
|
|
$cgi->a({-href => href(action=>"blob", hash_base=>$hash,
|
2007-05-06 23:10:06 +00:00
|
|
|
hash=>$diff->{'to_id'}, file_name=>$diff->{'to_file'}),
|
|
|
|
-class => "list"}, esc_path($diff->{'to_file'})) . "</td>\n" .
|
2006-08-21 21:08:52 +00:00
|
|
|
"<td><span class=\"file_status $nstatus\">[$nstatus from " .
|
|
|
|
$cgi->a({-href => href(action=>"blob", hash_base=>$parent,
|
2007-05-06 23:10:06 +00:00
|
|
|
hash=>$diff->{'from_id'}, file_name=>$diff->{'from_file'}),
|
|
|
|
-class => "list"}, esc_path($diff->{'from_file'})) .
|
|
|
|
" with " . (int $diff->{'similarity'}) . "% similarity$mode_chng]</span></td>\n" .
|
2006-09-28 00:23:25 +00:00
|
|
|
"<td class=\"link\">";
|
2006-10-31 16:36:27 +00:00
|
|
|
if ($action eq 'commitdiff') {
|
|
|
|
# link to patch
|
|
|
|
$patchno++;
|
|
|
|
print $cgi->a({-href => "#patch$patchno"}, "patch") .
|
|
|
|
" | ";
|
2007-05-06 23:10:06 +00:00
|
|
|
} elsif ($diff->{'to_id'} ne $diff->{'from_id'}) {
|
2006-10-31 16:36:27 +00:00
|
|
|
# "commit" view and modified file (not only pure rename or copy)
|
|
|
|
print $cgi->a({-href => href(action=>"blobdiff",
|
2007-05-06 23:10:06 +00:00
|
|
|
hash=>$diff->{'to_id'}, hash_parent=>$diff->{'from_id'},
|
2006-10-31 16:36:27 +00:00
|
|
|
hash_base=>$hash, hash_parent_base=>$parent,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'to_file'}, file_parent=>$diff->{'from_file'})},
|
2006-10-31 16:36:27 +00:00
|
|
|
"diff") .
|
|
|
|
" | ";
|
2006-08-14 00:18:33 +00:00
|
|
|
}
|
2007-05-06 23:10:06 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
|
|
|
|
hash_base=>$parent, file_name=>$diff->{'to_file'})},
|
2006-11-19 21:51:39 +00:00
|
|
|
"blob") . " | ";
|
2006-11-08 20:22:04 +00:00
|
|
|
if ($have_blame) {
|
2006-11-19 21:51:39 +00:00
|
|
|
print $cgi->a({-href => href(action=>"blame", hash_base=>$hash,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'to_file'})},
|
2006-11-19 21:51:39 +00:00
|
|
|
"blame") . " | ";
|
2006-11-08 20:22:04 +00:00
|
|
|
}
|
2006-11-19 21:51:39 +00:00
|
|
|
print $cgi->a({-href => href(action=>"history", hash_base=>$hash,
|
2007-05-06 23:10:06 +00:00
|
|
|
file_name=>$diff->{'to_file'})},
|
2006-10-21 15:52:19 +00:00
|
|
|
"history");
|
2006-08-14 00:18:33 +00:00
|
|
|
print "</td>\n";
|
2006-08-21 21:08:52 +00:00
|
|
|
|
2006-08-14 00:18:33 +00:00
|
|
|
} # we should not encounter Unmerged (U) or Unknown (X) status
|
|
|
|
print "</tr>\n";
|
|
|
|
}
|
2007-06-08 11:24:56 +00:00
|
|
|
print "</tbody>" if $has_header;
|
2006-08-14 00:18:33 +00:00
|
|
|
print "</table>\n";
|
|
|
|
}
|
|
|
|
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
sub git_patchset_body {
|
2007-05-06 23:10:05 +00:00
|
|
|
my ($fd, $difftree, $hash, @hash_parents) = @_;
|
|
|
|
my ($hash_parent) = $hash_parents[0];
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
my $is_combined = (@hash_parents > 1);
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
my $patch_idx = 0;
|
2007-04-23 05:49:25 +00:00
|
|
|
my $patch_number = 0;
|
2006-11-18 22:35:39 +00:00
|
|
|
my $patch_line;
|
2006-08-25 18:59:39 +00:00
|
|
|
my $diffinfo;
|
2007-10-30 00:35:05 +00:00
|
|
|
my $to_name;
|
2006-11-08 16:59:41 +00:00
|
|
|
my (%from, %to);
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
|
|
|
print "<div class=\"patchset\">\n";
|
|
|
|
|
2006-11-18 22:35:39 +00:00
|
|
|
# skip to first patch
|
|
|
|
while ($patch_line = <$fd>) {
|
2006-08-24 17:34:36 +00:00
|
|
|
chomp $patch_line;
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
2006-11-18 22:35:39 +00:00
|
|
|
last if ($patch_line =~ m/^diff /);
|
|
|
|
}
|
|
|
|
|
|
|
|
PATCH:
|
|
|
|
while ($patch_line) {
|
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# parse "git diff" header line
|
|
|
|
if ($patch_line =~ m/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/) {
|
|
|
|
# $1 is from_name, which we do not use
|
|
|
|
$to_name = unquote($2);
|
|
|
|
$to_name =~ s!^b/!!;
|
|
|
|
} elsif ($patch_line =~ m/^diff --(cc|combined) ("?.*"?)$/) {
|
|
|
|
# $1 is 'cc' or 'combined', which we do not use
|
|
|
|
$to_name = unquote($2);
|
|
|
|
} else {
|
|
|
|
$to_name = undef;
|
2006-11-18 22:35:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# check if current patch belong to current raw line
|
|
|
|
# and parse raw git-diff line if needed
|
2007-10-30 00:35:05 +00:00
|
|
|
if (is_patch_split($diffinfo, { 'to_file' => $to_name })) {
|
2007-05-12 10:42:32 +00:00
|
|
|
# this is continuation of a split patch
|
2006-11-18 22:35:39 +00:00
|
|
|
print "<div class=\"patch cont\">\n";
|
|
|
|
} else {
|
|
|
|
# advance raw git-diff output if needed
|
|
|
|
$patch_idx++ if defined $diffinfo;
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# read and prepare patch information
|
|
|
|
$diffinfo = parsed_difftree_line($difftree->[$patch_idx]);
|
2007-06-08 11:33:28 +00:00
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# compact combined diff output can have some patches skipped
|
|
|
|
# find which patch (using pathname of result) we are at now;
|
|
|
|
if ($is_combined) {
|
|
|
|
while ($to_name ne $diffinfo->{'to_file'}) {
|
2007-06-08 11:33:28 +00:00
|
|
|
print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
|
|
|
|
format_diff_cc_simplified($diffinfo, @hash_parents) .
|
|
|
|
"</div>\n"; # class="patch"
|
|
|
|
|
|
|
|
$patch_idx++;
|
|
|
|
$patch_number++;
|
2007-10-30 00:35:05 +00:00
|
|
|
|
|
|
|
last if $patch_idx > $#$difftree;
|
|
|
|
$diffinfo = parsed_difftree_line($difftree->[$patch_idx]);
|
2007-06-08 11:33:28 +00:00
|
|
|
}
|
2007-10-30 00:35:05 +00:00
|
|
|
}
|
2007-09-08 19:49:11 +00:00
|
|
|
|
2007-06-08 11:27:42 +00:00
|
|
|
# modifies %from, %to hashes
|
|
|
|
parse_from_to_diffinfo($diffinfo, \%from, \%to, @hash_parents);
|
2007-05-17 20:54:28 +00:00
|
|
|
|
2006-11-18 22:35:39 +00:00
|
|
|
# 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";
|
2006-11-08 16:59:41 +00:00
|
|
|
}
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
# git diff header
|
|
|
|
#assert($patch_line =~ m/^diff /) if DEBUG;
|
|
|
|
#assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed
|
|
|
|
$patch_number++;
|
2006-11-18 22:35:39 +00:00
|
|
|
# print "git diff" header
|
2007-06-08 11:27:42 +00:00
|
|
|
print format_git_diff_header_line($patch_line, $diffinfo,
|
|
|
|
\%from, \%to);
|
2006-11-18 22:35:39 +00:00
|
|
|
|
|
|
|
# print extended diff header
|
2007-10-30 00:35:05 +00:00
|
|
|
print "<div class=\"diff extended_header\">\n";
|
2006-11-18 22:35:39 +00:00
|
|
|
EXTENDED_HEADER:
|
2007-10-30 00:35:05 +00:00
|
|
|
while ($patch_line = <$fd>) {
|
|
|
|
chomp $patch_line;
|
|
|
|
|
|
|
|
last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /);
|
|
|
|
|
2007-06-08 11:27:42 +00:00
|
|
|
print format_extended_diff_header_line($patch_line, $diffinfo,
|
|
|
|
\%from, \%to);
|
2006-11-18 22:35:39 +00:00
|
|
|
}
|
2007-10-30 00:35:05 +00:00
|
|
|
print "</div>\n"; # class="diff extended_header"
|
2006-11-18 22:35:39 +00:00
|
|
|
|
|
|
|
# from-file/to-file diff header
|
2007-01-09 23:07:43 +00:00
|
|
|
if (! $patch_line) {
|
|
|
|
print "</div>\n"; # class="patch"
|
|
|
|
last PATCH;
|
|
|
|
}
|
2007-01-07 01:52:25 +00:00
|
|
|
next PATCH if ($patch_line =~ m/^diff /);
|
2006-11-18 22:35:39 +00:00
|
|
|
#assert($patch_line =~ m/^---/) if DEBUG;
|
2006-11-08 16:59:41 +00:00
|
|
|
|
2007-10-30 00:35:05 +00:00
|
|
|
my $last_patch_line = $patch_line;
|
2006-11-18 22:35:39 +00:00
|
|
|
$patch_line = <$fd>;
|
|
|
|
chomp $patch_line;
|
2007-06-08 11:27:42 +00:00
|
|
|
#assert($patch_line =~ m/^\+\+\+/) if DEBUG;
|
2006-08-25 19:04:13 +00:00
|
|
|
|
2007-06-08 11:27:42 +00:00
|
|
|
print format_diff_from_to_header($last_patch_line, $patch_line,
|
2007-06-08 11:32:44 +00:00
|
|
|
$diffinfo, \%from, \%to,
|
|
|
|
@hash_parents);
|
2006-08-25 19:04:13 +00:00
|
|
|
|
2006-11-18 22:35:39 +00:00
|
|
|
# the patch itself
|
|
|
|
LINE:
|
|
|
|
while ($patch_line = <$fd>) {
|
|
|
|
chomp $patch_line;
|
2006-08-25 19:04:13 +00:00
|
|
|
|
2006-11-18 22:35:39 +00:00
|
|
|
next PATCH if ($patch_line =~ m/^diff /);
|
2006-08-25 19:04:13 +00:00
|
|
|
|
2006-11-18 22:35:40 +00:00
|
|
|
print format_diff_line($patch_line, \%from, \%to);
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
|
|
|
|
2006-11-18 22:35:39 +00:00
|
|
|
} continue {
|
|
|
|
print "</div>\n"; # class="patch"
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
2007-05-16 22:05:55 +00:00
|
|
|
|
2010-08-22 11:12:12 +00:00
|
|
|
# for compact combined (--cc) format, with chunk and patch simplification
|
|
|
|
# the patchset might be empty, but there might be unprocessed raw lines
|
2007-10-30 00:35:05 +00:00
|
|
|
for (++$patch_idx if $patch_number > 0;
|
2007-06-08 11:33:28 +00:00
|
|
|
$patch_idx < @$difftree;
|
2007-10-30 00:35:05 +00:00
|
|
|
++$patch_idx) {
|
2007-06-08 11:33:28 +00:00
|
|
|
# read and prepare patch information
|
2007-10-30 00:35:05 +00:00
|
|
|
$diffinfo = parsed_difftree_line($difftree->[$patch_idx]);
|
2007-06-08 11:33:28 +00:00
|
|
|
|
|
|
|
# generate anchor for "patch" links in difftree / whatchanged part
|
|
|
|
print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
|
|
|
|
format_diff_cc_simplified($diffinfo, @hash_parents) .
|
|
|
|
"</div>\n"; # class="patch"
|
|
|
|
|
|
|
|
$patch_number++;
|
|
|
|
}
|
|
|
|
|
2007-05-16 22:05:55 +00:00
|
|
|
if ($patch_number == 0) {
|
|
|
|
if (@hash_parents > 1) {
|
|
|
|
print "<div class=\"diff nodifferences\">Trivial merge</div>\n";
|
|
|
|
} else {
|
|
|
|
print "<div class=\"diff nodifferences\">No differences found</div>\n";
|
|
|
|
}
|
|
|
|
}
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
|
|
|
print "</div>\n"; # class="patchset"
|
|
|
|
}
|
|
|
|
|
|
|
|
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
|
|
|
|
2008-06-10 17:21:01 +00:00
|
|
|
# fills project list info (age, description, owner, forks) for each
|
|
|
|
# project in the list, removing invalid projects from returned list
|
|
|
|
# NOTE: modifies $projlist, but does not remove entries from it
|
|
|
|
sub fill_project_list_info {
|
|
|
|
my ($projlist, $check_forks) = @_;
|
2006-10-24 03:33:17 +00:00
|
|
|
my @projects;
|
2008-06-10 17:21:01 +00:00
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
my $show_ctags = gitweb_check_feature('ctags');
|
2008-06-10 17:21:01 +00:00
|
|
|
PROJECT:
|
2006-10-24 03:33:17 +00:00
|
|
|
foreach my $pr (@$projlist) {
|
2008-06-10 17:21:01 +00:00
|
|
|
my (@activity) = git_get_last_activity($pr->{'path'});
|
|
|
|
unless (@activity) {
|
|
|
|
next PROJECT;
|
2006-10-24 03:33:17 +00:00
|
|
|
}
|
2008-06-10 17:21:01 +00:00
|
|
|
($pr->{'age'}, $pr->{'age_string'}) = @activity;
|
2006-10-24 03:33:17 +00:00
|
|
|
if (!defined $pr->{'descr'}) {
|
|
|
|
my $descr = git_get_project_description($pr->{'path'}) || "";
|
2008-06-10 17:21:01 +00:00
|
|
|
$descr = to_utf8($descr);
|
|
|
|
$pr->{'descr_long'} = $descr;
|
2007-07-05 00:36:48 +00:00
|
|
|
$pr->{'descr'} = chop_str($descr, $projects_list_description_width, 5);
|
2006-10-24 03:33:17 +00:00
|
|
|
}
|
|
|
|
if (!defined $pr->{'owner'}) {
|
2007-07-03 22:11:23 +00:00
|
|
|
$pr->{'owner'} = git_get_project_owner("$pr->{'path'}") || "";
|
2006-10-24 03:33:17 +00:00
|
|
|
}
|
|
|
|
if ($check_forks) {
|
|
|
|
my $pname = $pr->{'path'};
|
2006-11-08 06:37:17 +00:00
|
|
|
if (($pname =~ s/\.git$//) &&
|
|
|
|
($pname !~ /\/$/) &&
|
|
|
|
(-d "$projectroot/$pname")) {
|
|
|
|
$pr->{'forks'} = "-d $projectroot/$pname";
|
2009-05-11 17:37:28 +00:00
|
|
|
} else {
|
2006-11-08 06:37:17 +00:00
|
|
|
$pr->{'forks'} = 0;
|
|
|
|
}
|
2006-10-24 03:33:17 +00:00
|
|
|
}
|
2008-10-02 15:13:02 +00:00
|
|
|
$show_ctags and $pr->{'ctags'} = git_get_project_ctags($pr->{'path'});
|
2006-10-24 03:33:17 +00:00
|
|
|
push @projects, $pr;
|
|
|
|
}
|
|
|
|
|
2008-06-10 17:21:01 +00:00
|
|
|
return @projects;
|
|
|
|
}
|
|
|
|
|
2008-09-25 16:48:37 +00:00
|
|
|
# print 'sort by' <th> element, generating 'sort by $name' replay link
|
|
|
|
# if that order is not selected
|
2008-06-10 17:21:44 +00:00
|
|
|
sub print_sort_th {
|
2010-01-30 22:30:43 +00:00
|
|
|
print format_sort_th(@_);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub format_sort_th {
|
2008-09-25 16:48:37 +00:00
|
|
|
my ($name, $order, $header) = @_;
|
2010-01-30 22:30:43 +00:00
|
|
|
my $sort_th = "";
|
2008-06-10 17:21:44 +00:00
|
|
|
$header ||= ucfirst($name);
|
|
|
|
|
|
|
|
if ($order eq $name) {
|
2010-01-30 22:30:43 +00:00
|
|
|
$sort_th .= "<th>$header</th>\n";
|
2008-06-10 17:21:44 +00:00
|
|
|
} else {
|
2010-01-30 22:30:43 +00:00
|
|
|
$sort_th .= "<th>" .
|
|
|
|
$cgi->a({-href => href(-replay=>1, order=>$name),
|
|
|
|
-class => "header"}, $header) .
|
|
|
|
"</th>\n";
|
2008-06-10 17:21:44 +00:00
|
|
|
}
|
2010-01-30 22:30:43 +00:00
|
|
|
|
|
|
|
return $sort_th;
|
2008-06-10 17:21:44 +00:00
|
|
|
}
|
|
|
|
|
2008-06-10 17:21:01 +00:00
|
|
|
sub git_project_list_body {
|
2008-10-02 15:17:01 +00:00
|
|
|
# actually uses global variable $project
|
2008-06-10 17:21:01 +00:00
|
|
|
my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
|
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
my $check_forks = gitweb_check_feature('forks');
|
2008-06-10 17:21:01 +00:00
|
|
|
my @projects = fill_project_list_info($projlist, $check_forks);
|
|
|
|
|
2007-04-06 21:58:24 +00:00
|
|
|
$order ||= $default_projects_order;
|
2006-10-24 03:33:17 +00:00
|
|
|
$from = 0 unless defined $from;
|
|
|
|
$to = $#projects if (!defined $to || $#projects < $to);
|
|
|
|
|
2008-09-25 16:48:37 +00:00
|
|
|
my %order_info = (
|
|
|
|
project => { key => 'path', type => 'str' },
|
|
|
|
descr => { key => 'descr_long', type => 'str' },
|
|
|
|
owner => { key => 'owner', type => 'str' },
|
|
|
|
age => { key => 'age', type => 'num' }
|
|
|
|
);
|
|
|
|
my $oi = $order_info{$order};
|
|
|
|
if ($oi->{'type'} eq 'str') {
|
|
|
|
@projects = sort {$a->{$oi->{'key'}} cmp $b->{$oi->{'key'}}} @projects;
|
|
|
|
} else {
|
|
|
|
@projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @projects;
|
|
|
|
}
|
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
my $show_ctags = gitweb_check_feature('ctags');
|
2008-10-02 15:13:02 +00:00
|
|
|
if ($show_ctags) {
|
|
|
|
my %ctags;
|
|
|
|
foreach my $p (@projects) {
|
|
|
|
foreach my $ct (keys %{$p->{'ctags'}}) {
|
|
|
|
$ctags{$ct} += $p->{'ctags'}->{$ct};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
my $cloud = git_populate_project_tagcloud(\%ctags);
|
|
|
|
print git_show_project_tagcloud($cloud, 64);
|
|
|
|
}
|
|
|
|
|
2006-10-24 03:33:17 +00:00
|
|
|
print "<table class=\"project_list\">\n";
|
|
|
|
unless ($no_header) {
|
|
|
|
print "<tr>\n";
|
|
|
|
if ($check_forks) {
|
|
|
|
print "<th></th>\n";
|
|
|
|
}
|
2008-09-25 16:48:37 +00:00
|
|
|
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');
|
2008-06-10 17:21:44 +00:00
|
|
|
print "<th></th>\n" . # for links
|
2006-10-24 03:33:17 +00:00
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
my $alternate = 1;
|
2008-10-02 15:13:02 +00:00
|
|
|
my $tagfilter = $cgi->param('by_tag');
|
2006-10-24 03:33:17 +00:00
|
|
|
for (my $i = $from; $i <= $to; $i++) {
|
|
|
|
my $pr = $projects[$i];
|
2008-10-02 15:17:01 +00:00
|
|
|
|
2008-10-02 15:13:02 +00:00
|
|
|
next if $tagfilter and $show_ctags and not grep { lc $_ eq lc $tagfilter } keys %{$pr->{'ctags'}};
|
2008-10-03 07:29:45 +00:00
|
|
|
next if $searchtext and not $pr->{'path'} =~ /$searchtext/
|
|
|
|
and not $pr->{'descr_long'} =~ /$searchtext/;
|
|
|
|
# Weed out forks or non-matching entries of search
|
2008-10-02 15:17:01 +00:00
|
|
|
if ($check_forks) {
|
|
|
|
my $forkbase = $project; $forkbase ||= ''; $forkbase =~ s#\.git$#/#;
|
|
|
|
$forkbase="^$forkbase" if $forkbase;
|
2008-10-03 07:29:45 +00:00
|
|
|
next if not $searchtext and not $tagfilter and $show_ctags
|
|
|
|
and $pr->{'path'} =~ m#$forkbase.*/.*#; # regexp-safe
|
2008-10-02 15:17:01 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 03:33:17 +00:00
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
|
|
|
if ($check_forks) {
|
|
|
|
print "<td>";
|
|
|
|
if ($pr->{'forks'}) {
|
2006-11-08 06:37:17 +00:00
|
|
|
print "<!-- $pr->{'forks'} -->\n";
|
2006-10-24 03:33:17 +00:00
|
|
|
print $cgi->a({-href => href(project=>$pr->{'path'}, action=>"forks")}, "+");
|
|
|
|
}
|
|
|
|
print "</td>\n";
|
|
|
|
}
|
|
|
|
print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
|
|
|
|
-class => "list"}, esc_html($pr->{'path'})) . "</td>\n" .
|
2006-11-26 01:18:26 +00:00
|
|
|
"<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
|
|
|
|
-class => "list", -title => $pr->{'descr_long'}},
|
|
|
|
esc_html($pr->{'descr'})) . "</td>\n" .
|
2007-10-23 01:31:23 +00:00
|
|
|
"<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
|
2006-10-24 03:33:17 +00:00
|
|
|
print "<td class=\"". age_class($pr->{'age'}) . "\">" .
|
2007-05-13 10:39:22 +00:00
|
|
|
(defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
|
2006-10-24 03:33:17 +00:00
|
|
|
"<td class=\"link\">" .
|
|
|
|
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " .
|
2006-11-15 20:37:50 +00:00
|
|
|
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " .
|
2006-10-24 03:33:17 +00:00
|
|
|
$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") : '') .
|
|
|
|
"</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
if (defined $extra) {
|
|
|
|
print "<tr>\n";
|
|
|
|
if ($check_forks) {
|
|
|
|
print "<td></td>\n";
|
|
|
|
}
|
|
|
|
print "<td colspan=\"5\">$extra</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
}
|
|
|
|
|
2009-11-13 01:02:12 +00:00
|
|
|
sub git_log_body {
|
|
|
|
# uses global variable $project
|
|
|
|
my ($commitlist, $from, $to, $refs, $extra) = @_;
|
|
|
|
|
|
|
|
$from = 0 unless defined $from;
|
|
|
|
$to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to);
|
|
|
|
|
|
|
|
for (my $i = 0; $i <= $to; $i++) {
|
|
|
|
my %co = %{$commitlist->[$i]};
|
|
|
|
next if !%co;
|
|
|
|
my $commit = $co{'id'};
|
|
|
|
my $ref = format_ref_marker($refs, $commit);
|
|
|
|
git_print_header_div('commit',
|
|
|
|
"<span class=\"age\">$co{'age_string'}</span>" .
|
|
|
|
esc_html($co{'title'}) . $ref,
|
|
|
|
$commit);
|
|
|
|
print "<div class=\"title_text\">\n" .
|
|
|
|
"<div class=\"log_link\">\n" .
|
|
|
|
$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") .
|
|
|
|
"<br/>\n" .
|
|
|
|
"</div>\n";
|
|
|
|
git_print_authorship(\%co, -tag => 'span');
|
|
|
|
print "<br/>\n</div>\n";
|
|
|
|
|
|
|
|
print "<div class=\"log_body\">\n";
|
|
|
|
git_print_log($co{'comment'}, -final_empty_line=> 1);
|
|
|
|
print "</div>\n";
|
|
|
|
}
|
|
|
|
if ($extra) {
|
|
|
|
print "<div class=\"page_nav\">\n";
|
|
|
|
print "$extra\n";
|
|
|
|
print "</div>\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-31 09:22:13 +00:00
|
|
|
sub git_shortlog_body {
|
|
|
|
# uses global variable $project
|
2006-12-24 14:31:44 +00:00
|
|
|
my ($commitlist, $from, $to, $refs, $extra) = @_;
|
2006-08-20 06:23:04 +00:00
|
|
|
|
2006-07-31 09:22:13 +00:00
|
|
|
$from = 0 unless defined $from;
|
2006-12-24 14:31:44 +00:00
|
|
|
$to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to);
|
2006-07-31 09:22:13 +00:00
|
|
|
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"shortlog\">\n";
|
gitweb: "alternate" starts with shade (i.e. 1)
When displaying a list of rows (difftree, shortlog, etc),
the first entry is now printed shaded, i.e. alternate is
initialized to 1, as opposed to non-shaded (alternate
initialized to 0).
This solves the problem when there is only one row to
display -- it is displayed shaded to visually indicate that
it is "active", part of a "list", etc.
(Compare this to the trivial case of more than one entry,
where the rows have alternating shade, thus suggesting
being part of a "list" of "active" entries, etc.)
Signed-off-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-28 23:47:50 +00:00
|
|
|
my $alternate = 1;
|
2006-07-31 09:22:13 +00:00
|
|
|
for (my $i = $from; $i <= $to; $i++) {
|
2006-12-24 14:31:44 +00:00
|
|
|
my %co = %{$commitlist->[$i]};
|
|
|
|
my $commit = $co{'id'};
|
2006-08-14 00:05:47 +00:00
|
|
|
my $ref = format_ref_marker($refs, $commit);
|
2006-07-31 09:22:13 +00:00
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<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" .
|
2009-06-29 22:00:48 +00:00
|
|
|
format_author_html('td', \%co, 10) . "<td>";
|
2006-08-22 14:52:50 +00:00
|
|
|
print format_subject_html($co{'title'}, $co{'title_short'},
|
|
|
|
href(action=>"commit", hash=>$commit), $ref);
|
2006-07-31 09:22:13 +00:00
|
|
|
print "</td>\n" .
|
|
|
|
"<td class=\"link\">" .
|
2006-10-24 03:36:10 +00:00
|
|
|
$cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") . " | " .
|
2006-09-22 01:19:44 +00:00
|
|
|
$cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") . " | " .
|
2006-10-06 13:57:52 +00:00
|
|
|
$cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree");
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
my $snapshot_links = format_snapshot_links($commit);
|
|
|
|
if (defined $snapshot_links) {
|
|
|
|
print " | " . $snapshot_links;
|
2006-10-06 13:57:52 +00:00
|
|
|
}
|
2006-08-17 15:29:46 +00:00
|
|
|
print "</td>\n" .
|
2006-07-31 09:22:13 +00:00
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
if (defined $extra) {
|
|
|
|
print "<tr>\n" .
|
|
|
|
"<td colspan=\"4\">$extra</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
}
|
|
|
|
|
2006-08-14 00:09:08 +00:00
|
|
|
sub git_history_body {
|
|
|
|
# Warning: assumes constant type (blob or tree) during history
|
2009-11-13 01:02:14 +00:00
|
|
|
my ($commitlist, $from, $to, $refs, $extra,
|
|
|
|
$file_name, $file_hash, $ftype) = @_;
|
2006-09-10 22:36:04 +00:00
|
|
|
|
|
|
|
$from = 0 unless defined $from;
|
2006-12-24 14:31:48 +00:00
|
|
|
$to = $#{$commitlist} unless (defined $to && $to <= $#{$commitlist});
|
2006-08-14 00:09:08 +00:00
|
|
|
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"history\">\n";
|
gitweb: "alternate" starts with shade (i.e. 1)
When displaying a list of rows (difftree, shortlog, etc),
the first entry is now printed shaded, i.e. alternate is
initialized to 1, as opposed to non-shaded (alternate
initialized to 0).
This solves the problem when there is only one row to
display -- it is displayed shaded to visually indicate that
it is "active", part of a "list", etc.
(Compare this to the trivial case of more than one entry,
where the rows have alternating shade, thus suggesting
being part of a "list" of "active" entries, etc.)
Signed-off-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-28 23:47:50 +00:00
|
|
|
my $alternate = 1;
|
2006-09-10 22:36:04 +00:00
|
|
|
for (my $i = $from; $i <= $to; $i++) {
|
2006-12-24 14:31:48 +00:00
|
|
|
my %co = %{$commitlist->[$i]};
|
2006-08-14 00:09:08 +00:00
|
|
|
if (!%co) {
|
|
|
|
next;
|
|
|
|
}
|
2006-12-24 14:31:48 +00:00
|
|
|
my $commit = $co{'id'};
|
2006-08-14 00:09:08 +00:00
|
|
|
|
|
|
|
my $ref = format_ref_marker($refs, $commit);
|
|
|
|
|
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
|
|
|
print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
|
2009-06-29 22:00:48 +00:00
|
|
|
# shortlog: format_author_html('td', \%co, 10)
|
|
|
|
format_author_html('td', \%co, 15, 3) . "<td>";
|
2006-08-14 00:09:08 +00:00
|
|
|
# originally git_history used chop_str($co{'title'}, 50)
|
2006-08-22 14:52:50 +00:00
|
|
|
print format_subject_html($co{'title'}, $co{'title_short'},
|
|
|
|
href(action=>"commit", hash=>$commit), $ref);
|
2006-08-14 00:09:08 +00:00
|
|
|
print "</td>\n" .
|
|
|
|
"<td class=\"link\">" .
|
2006-09-29 00:21:07 +00:00
|
|
|
$cgi->a({-href => href(action=>$ftype, hash_base=>$commit, file_name=>$file_name)}, $ftype) . " | " .
|
|
|
|
$cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff");
|
2006-08-14 00:09:08 +00:00
|
|
|
|
|
|
|
if ($ftype eq 'blob') {
|
2009-11-13 01:02:14 +00:00
|
|
|
my $blob_current = $file_hash;
|
2006-08-14 00:09:08 +00:00
|
|
|
my $blob_parent = git_get_hash_by_path($commit, $file_name);
|
|
|
|
if (defined $blob_current && defined $blob_parent &&
|
|
|
|
$blob_current ne $blob_parent) {
|
|
|
|
print " | " .
|
2006-08-24 21:53:54 +00:00
|
|
|
$cgi->a({-href => href(action=>"blobdiff",
|
|
|
|
hash=>$blob_current, hash_parent=>$blob_parent,
|
|
|
|
hash_base=>$hash_base, hash_parent_base=>$commit,
|
|
|
|
file_name=>$file_name)},
|
2006-08-14 00:09:08 +00:00
|
|
|
"diff to current");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
print "</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
if (defined $extra) {
|
|
|
|
print "<tr>\n" .
|
|
|
|
"<td colspan=\"4\">$extra</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub git_tags_body {
|
|
|
|
# uses global variable $project
|
|
|
|
my ($taglist, $from, $to, $extra) = @_;
|
|
|
|
$from = 0 unless defined $from;
|
|
|
|
$to = $#{$taglist} if (!defined $to || $#{$taglist} < $to);
|
|
|
|
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"tags\">\n";
|
gitweb: "alternate" starts with shade (i.e. 1)
When displaying a list of rows (difftree, shortlog, etc),
the first entry is now printed shaded, i.e. alternate is
initialized to 1, as opposed to non-shaded (alternate
initialized to 0).
This solves the problem when there is only one row to
display -- it is displayed shaded to visually indicate that
it is "active", part of a "list", etc.
(Compare this to the trivial case of more than one entry,
where the rows have alternating shade, thus suggesting
being part of a "list" of "active" entries, etc.)
Signed-off-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-28 23:47:50 +00:00
|
|
|
my $alternate = 1;
|
2006-07-31 19:22:15 +00:00
|
|
|
for (my $i = $from; $i <= $to; $i++) {
|
|
|
|
my $entry = $taglist->[$i];
|
|
|
|
my %tag = %$entry;
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
my $comment = $tag{'subject'};
|
2006-07-31 19:22:15 +00:00
|
|
|
my $comment_short;
|
|
|
|
if (defined $comment) {
|
|
|
|
$comment_short = chop_str($comment, 30, 5);
|
|
|
|
}
|
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
2007-01-03 21:54:29 +00:00
|
|
|
if (defined $tag{'age'}) {
|
|
|
|
print "<td><i>$tag{'age'}</i></td>\n";
|
|
|
|
} else {
|
|
|
|
print "<td></td>\n";
|
|
|
|
}
|
|
|
|
print "<td>" .
|
2006-08-15 22:24:30 +00:00
|
|
|
$cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'}),
|
2006-08-22 10:38:59 +00:00
|
|
|
-class => "list name"}, esc_html($tag{'name'})) .
|
2006-07-31 19:22:15 +00:00
|
|
|
"</td>\n" .
|
|
|
|
"<td>";
|
|
|
|
if (defined $comment) {
|
2006-08-22 14:52:50 +00:00
|
|
|
print format_subject_html($comment, $comment_short,
|
|
|
|
href(action=>"tag", hash=>$tag{'id'}));
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
print "</td>\n" .
|
|
|
|
"<td class=\"selflink\">";
|
|
|
|
if ($tag{'type'} eq "tag") {
|
2006-08-15 22:24:30 +00:00
|
|
|
print $cgi->a({-href => href(action=>"tag", hash=>$tag{'id'})}, "tag");
|
2006-07-31 19:22:15 +00:00
|
|
|
} else {
|
|
|
|
print " ";
|
|
|
|
}
|
|
|
|
print "</td>\n" .
|
|
|
|
"<td class=\"link\">" . " | " .
|
2006-08-15 22:24:30 +00:00
|
|
|
$cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'})}, $tag{'reftype'});
|
2006-07-31 19:22:15 +00:00
|
|
|
if ($tag{'reftype'} eq "commit") {
|
2007-12-15 14:40:28 +00:00
|
|
|
print " | " . $cgi->a({-href => href(action=>"shortlog", hash=>$tag{'fullname'})}, "shortlog") .
|
|
|
|
" | " . $cgi->a({-href => href(action=>"log", hash=>$tag{'fullname'})}, "log");
|
2006-07-31 19:22:15 +00:00
|
|
|
} elsif ($tag{'reftype'} eq "blob") {
|
2006-08-15 22:24:30 +00:00
|
|
|
print " | " . $cgi->a({-href => href(action=>"blob_plain", hash=>$tag{'refid'})}, "raw");
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
print "</td>\n" .
|
|
|
|
"</tr>";
|
|
|
|
}
|
|
|
|
if (defined $extra) {
|
|
|
|
print "<tr>\n" .
|
|
|
|
"<td colspan=\"5\">$extra</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_heads_body {
|
|
|
|
# uses global variable $project
|
2006-09-19 12:33:22 +00:00
|
|
|
my ($headlist, $head, $from, $to, $extra) = @_;
|
2006-07-31 19:22:15 +00:00
|
|
|
$from = 0 unless defined $from;
|
2006-09-19 12:33:22 +00:00
|
|
|
$to = $#{$headlist} if (!defined $to || $#{$headlist} < $to);
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"heads\">\n";
|
gitweb: "alternate" starts with shade (i.e. 1)
When displaying a list of rows (difftree, shortlog, etc),
the first entry is now printed shaded, i.e. alternate is
initialized to 1, as opposed to non-shaded (alternate
initialized to 0).
This solves the problem when there is only one row to
display -- it is displayed shaded to visually indicate that
it is "active", part of a "list", etc.
(Compare this to the trivial case of more than one entry,
where the rows have alternating shade, thus suggesting
being part of a "list" of "active" entries, etc.)
Signed-off-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-28 23:47:50 +00:00
|
|
|
my $alternate = 1;
|
2006-07-31 19:22:15 +00:00
|
|
|
for (my $i = $from; $i <= $to; $i++) {
|
2006-09-19 12:33:22 +00:00
|
|
|
my $entry = $headlist->[$i];
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
my %ref = %$entry;
|
|
|
|
my $curr = $ref{'id'} eq $head;
|
2006-07-31 19:22:15 +00:00
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
print "<td><i>$ref{'age'}</i></td>\n" .
|
|
|
|
($curr ? "<td class=\"current_head\">" : "<td>") .
|
2007-12-15 14:40:28 +00:00
|
|
|
$cgi->a({-href => href(action=>"shortlog", hash=>$ref{'fullname'}),
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
-class => "list name"},esc_html($ref{'name'})) .
|
2006-07-31 19:22:15 +00:00
|
|
|
"</td>\n" .
|
|
|
|
"<td class=\"link\">" .
|
2007-12-15 14:40:28 +00:00
|
|
|
$cgi->a({-href => href(action=>"shortlog", hash=>$ref{'fullname'})}, "shortlog") . " | " .
|
|
|
|
$cgi->a({-href => href(action=>"log", hash=>$ref{'fullname'})}, "log") . " | " .
|
2010-11-11 12:26:08 +00:00
|
|
|
$cgi->a({-href => href(action=>"tree", hash=>$ref{'fullname'}, hash_base=>$ref{'fullname'})}, "tree") .
|
2006-07-31 19:22:15 +00:00
|
|
|
"</td>\n" .
|
|
|
|
"</tr>";
|
|
|
|
}
|
|
|
|
if (defined $extra) {
|
|
|
|
print "<tr>\n" .
|
|
|
|
"<td colspan=\"3\">$extra</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
}
|
|
|
|
|
2010-11-11 12:26:17 +00:00
|
|
|
# Display a single remote block
|
|
|
|
sub git_remote_block {
|
|
|
|
my ($remote, $rdata, $limit, $head) = @_;
|
|
|
|
|
|
|
|
my $heads = $rdata->{'heads'};
|
|
|
|
my $fetch = $rdata->{'fetch'};
|
|
|
|
my $push = $rdata->{'push'};
|
|
|
|
|
|
|
|
my $urls_table = "<table class=\"projects_list\">\n" ;
|
|
|
|
|
|
|
|
if (defined $fetch) {
|
|
|
|
if ($fetch eq $push) {
|
|
|
|
$urls_table .= format_repo_url("URL", $fetch);
|
|
|
|
} else {
|
|
|
|
$urls_table .= format_repo_url("Fetch URL", $fetch);
|
|
|
|
$urls_table .= format_repo_url("Push URL", $push) if defined $push;
|
|
|
|
}
|
|
|
|
} elsif (defined $push) {
|
|
|
|
$urls_table .= format_repo_url("Push URL", $push);
|
|
|
|
} else {
|
|
|
|
$urls_table .= format_repo_url("", "No remote URL");
|
|
|
|
}
|
|
|
|
|
|
|
|
$urls_table .= "</table>\n";
|
|
|
|
|
|
|
|
my $dots;
|
|
|
|
if (defined $limit && $limit < @$heads) {
|
|
|
|
$dots = $cgi->a({-href => href(action=>"remotes", hash=>$remote)}, "...");
|
|
|
|
}
|
|
|
|
|
|
|
|
print $urls_table;
|
|
|
|
git_heads_body($heads, $head, 0, $limit, $dots);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Display a list of remote names with the respective fetch and push URLs
|
|
|
|
sub git_remotes_list {
|
|
|
|
my ($remotedata, $limit) = @_;
|
|
|
|
print "<table class=\"heads\">\n";
|
|
|
|
my $alternate = 1;
|
|
|
|
my @remotes = sort keys %$remotedata;
|
|
|
|
|
|
|
|
my $limited = $limit && $limit < @remotes;
|
|
|
|
|
|
|
|
$#remotes = $limit - 1 if $limited;
|
|
|
|
|
|
|
|
while (my $remote = shift @remotes) {
|
|
|
|
my $rdata = $remotedata->{$remote};
|
|
|
|
my $fetch = $rdata->{'fetch'};
|
|
|
|
my $push = $rdata->{'push'};
|
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
|
|
|
print "<td>" .
|
|
|
|
$cgi->a({-href=> href(action=>'remotes', hash=>$remote),
|
|
|
|
-class=> "list name"},esc_html($remote)) .
|
|
|
|
"</td>";
|
|
|
|
print "<td class=\"link\">" .
|
|
|
|
(defined $fetch ? $cgi->a({-href=> $fetch}, "fetch") : "fetch") .
|
|
|
|
" | " .
|
|
|
|
(defined $push ? $cgi->a({-href=> $push}, "push") : "push") .
|
|
|
|
"</td>";
|
|
|
|
|
|
|
|
print "</tr>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($limited) {
|
|
|
|
print "<tr>\n" .
|
|
|
|
"<td colspan=\"3\">" .
|
|
|
|
$cgi->a({-href => href(action=>"remotes")}, "...") .
|
|
|
|
"</td>\n" . "</tr>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
print "</table>";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Display remote heads grouped by remote, unless there are too many
|
|
|
|
# remotes, in which case we only display the remote names
|
|
|
|
sub git_remotes_body {
|
|
|
|
my ($remotedata, $limit, $head) = @_;
|
|
|
|
if ($limit and $limit < keys %$remotedata) {
|
|
|
|
git_remotes_list($remotedata, $limit);
|
|
|
|
} else {
|
|
|
|
fill_remote_heads($remotedata);
|
|
|
|
while (my ($remote, $rdata) = each %$remotedata) {
|
|
|
|
git_print_section({-class=>"remote", -id=>$remote},
|
|
|
|
["remotes", $remote, $remote], sub {
|
|
|
|
git_remote_block($remote, $rdata, $limit, $head);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-23 14:57:12 +00:00
|
|
|
sub git_search_grep_body {
|
2006-12-24 14:31:46 +00:00
|
|
|
my ($commitlist, $from, $to, $extra) = @_;
|
2006-12-23 14:57:12 +00:00
|
|
|
$from = 0 unless defined $from;
|
2006-12-24 14:31:46 +00:00
|
|
|
$to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to);
|
2006-12-23 14:57:12 +00:00
|
|
|
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"commit_search\">\n";
|
2006-12-23 14:57:12 +00:00
|
|
|
my $alternate = 1;
|
|
|
|
for (my $i = $from; $i <= $to; $i++) {
|
2006-12-24 14:31:46 +00:00
|
|
|
my %co = %{$commitlist->[$i]};
|
2006-12-23 14:57:12 +00:00
|
|
|
if (!%co) {
|
|
|
|
next;
|
|
|
|
}
|
2006-12-24 14:31:46 +00:00
|
|
|
my $commit = $co{'id'};
|
2006-12-23 14:57:12 +00:00
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
|
|
|
print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
|
2009-06-29 22:00:48 +00:00
|
|
|
format_author_html('td', \%co, 15, 5) .
|
2006-12-23 14:57:12 +00:00
|
|
|
"<td>" .
|
2008-02-22 16:33:47 +00:00
|
|
|
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
|
|
|
|
-class => "list subject"},
|
|
|
|
chop_and_escape_str($co{'title'}, 50) . "<br/>");
|
2006-12-23 14:57:12 +00:00
|
|
|
my $comment = $co{'comment'};
|
|
|
|
foreach my $line (@$comment) {
|
2008-03-02 15:57:14 +00:00
|
|
|
if ($line =~ m/^(.*?)($search_regexp)(.*)$/i) {
|
2008-02-22 16:33:47 +00:00
|
|
|
my ($lead, $match, $trail) = ($1, $2, $3);
|
gitweb: Better cutting matched string and its context
Improve look of commit search output ('search' view) by better cutting
of matched string and its context in match info, as suggested by Junio.
For example, if you are looking for "very long search string" in the
following line:
Could somebody test this with very long search string, and see how
you would now see:
...this with <<very long ... string>>, and see...
instead of:
Could som... <<very long search...>>, and see...
(where <<something>> denotes emphasized / colored fragment; matched
fragment to be more exact).
For this feature, support for fourth [optional] parameter to chop_str
subroutine was added. This fourth parameter is used to denote where
to cut string to make it shorter. chop_str can now cut at the
beginning (from the _left_ side of the string), in the middle
(_center_ of the string), or at the end (from the _right_ side of
the string); cutting from right is the default:
chop_str(somestring, len, slop, 'left') -> ' ...string'
chop_str(somestring, len, slop, 'center') -> 'som ... ing'
chop_str(somestring, len, slop, 'right') -> 'somestr... '
If you want to use default slop (default additional length), use undef
as value for third parameter to chop_str.
While at it, return from chop_str early if given string is so short
that chop_str couldn't shorten it. Simplify also regexp used by
chop_str. Make ellipsis (dots) stick to shortened fragment for
cutting at ends, to better see which part got shortened.
Simplify passing all arguments to chop_str in chop_and_escape_str
subroutine. This was needed to pass additional options to chop_str.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-25 20:07:57 +00:00
|
|
|
$match = chop_str($match, 70, 5, 'center');
|
|
|
|
my $contextlen = int((80 - length($match))/2);
|
|
|
|
$contextlen = 30 if ($contextlen > 30);
|
|
|
|
$lead = chop_str($lead, $contextlen, 10, 'left');
|
|
|
|
$trail = chop_str($trail, $contextlen, 10, 'right');
|
2008-02-22 16:33:47 +00:00
|
|
|
|
|
|
|
$lead = esc_html($lead);
|
|
|
|
$match = esc_html($match);
|
|
|
|
$trail = esc_html($trail);
|
|
|
|
|
|
|
|
print "$lead<span class=\"match\">$match</span>$trail<br />";
|
2006-12-23 14:57:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
print "</td>\n" .
|
|
|
|
"<td class=\"link\">" .
|
|
|
|
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
|
|
|
|
" | " .
|
2007-11-26 12:42:06 +00:00
|
|
|
$cgi->a({-href => href(action=>"commitdiff", hash=>$co{'id'})}, "commitdiff") .
|
|
|
|
" | " .
|
2006-12-23 14:57:12 +00:00
|
|
|
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
|
|
|
|
print "</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
if (defined $extra) {
|
|
|
|
print "<tr>\n" .
|
|
|
|
"<td colspan=\"3\">$extra</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
## ======================================================================
|
|
|
|
## ======================================================================
|
|
|
|
## actions
|
|
|
|
|
|
|
|
sub git_project_list {
|
2008-10-10 18:42:26 +00:00
|
|
|
my $order = $input_params{'order'};
|
2007-04-06 21:58:24 +00:00
|
|
|
if (defined $order && $order !~ m/none|project|descr|owner|age/) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Unknown order parameter");
|
2006-08-01 00:59:12 +00:00
|
|
|
}
|
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
my @list = git_get_projects_list();
|
2006-07-31 19:22:15 +00:00
|
|
|
if (!@list) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(404, "No projects found");
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
2006-08-01 00:59:12 +00:00
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
git_header_html();
|
2010-01-30 22:30:41 +00:00
|
|
|
if (defined $home_text && -f $home_text) {
|
2006-07-31 19:22:15 +00:00
|
|
|
print "<div class=\"index_include\">\n";
|
2008-12-01 18:01:42 +00:00
|
|
|
insert_file($home_text);
|
2006-07-31 19:22:15 +00:00
|
|
|
print "</div>\n";
|
2006-07-31 09:22:13 +00:00
|
|
|
}
|
2008-10-03 07:29:45 +00:00
|
|
|
print $cgi->startform(-method => "get") .
|
|
|
|
"<p class=\"projsearch\">Search:\n" .
|
|
|
|
$cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
|
|
|
|
"</p>" .
|
|
|
|
$cgi->end_form() . "\n";
|
2006-10-24 03:33:17 +00:00
|
|
|
git_project_list_body(\@list, $order);
|
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_forks {
|
2008-10-10 18:42:26 +00:00
|
|
|
my $order = $input_params{'order'};
|
2007-04-06 21:58:24 +00:00
|
|
|
if (defined $order && $order !~ m/none|project|descr|owner|age/) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Unknown order parameter");
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
2006-10-24 03:33:17 +00:00
|
|
|
|
|
|
|
my @list = git_get_projects_list($project);
|
|
|
|
if (!@list) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(404, "No forks found");
|
2006-07-31 09:22:13 +00:00
|
|
|
}
|
2006-10-24 03:33:17 +00:00
|
|
|
|
|
|
|
git_header_html();
|
|
|
|
git_print_page_nav('','');
|
|
|
|
git_print_header_div('summary', "$project forks");
|
|
|
|
git_project_list_body(\@list, $order);
|
2006-07-31 19:22:15 +00:00
|
|
|
git_footer_html();
|
2006-07-31 09:22:13 +00:00
|
|
|
}
|
|
|
|
|
2006-09-15 02:56:03 +00:00
|
|
|
sub git_project_index {
|
2006-10-24 03:33:17 +00:00
|
|
|
my @projects = git_get_projects_list($project);
|
2006-09-15 02:56:03 +00:00
|
|
|
|
|
|
|
print $cgi->header(
|
|
|
|
-type => 'text/plain',
|
|
|
|
-charset => 'utf-8',
|
2006-09-25 23:59:43 +00:00
|
|
|
-content_disposition => 'inline; filename="index.aux"');
|
2006-09-15 02:56:03 +00:00
|
|
|
|
|
|
|
foreach my $pr (@projects) {
|
|
|
|
if (!exists $pr->{'owner'}) {
|
2007-07-03 22:11:23 +00:00
|
|
|
$pr->{'owner'} = git_get_project_owner("$pr->{'path'}");
|
2006-09-15 02:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
my ($path, $owner) = ($pr->{'path'}, $pr->{'owner'});
|
|
|
|
# quote as in CGI::Util::encode, but keep the slash, and use '+' for ' '
|
|
|
|
$path =~ s/([^a-zA-Z0-9_.\-\/ ])/sprintf("%%%02X", ord($1))/eg;
|
|
|
|
$owner =~ s/([^a-zA-Z0-9_.\-\/ ])/sprintf("%%%02X", ord($1))/eg;
|
|
|
|
$path =~ s/ /\+/g;
|
|
|
|
$owner =~ s/ /\+/g;
|
|
|
|
|
|
|
|
print "$path $owner\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-07 18:23:12 +00:00
|
|
|
sub git_summary {
|
2006-08-14 00:05:47 +00:00
|
|
|
my $descr = git_get_project_description($project) || "none";
|
2006-12-22 19:38:15 +00:00
|
|
|
my %co = parse_commit("HEAD");
|
2007-05-13 10:39:22 +00:00
|
|
|
my %cd = %co ? parse_date($co{'committer_epoch'}, $co{'committer_tz'}) : ();
|
2006-12-22 19:38:15 +00:00
|
|
|
my $head = $co{'id'};
|
2010-11-11 12:26:11 +00:00
|
|
|
my $remote_heads = gitweb_check_feature('remote_heads');
|
2005-08-07 18:23:12 +00:00
|
|
|
|
2006-08-14 00:10:06 +00:00
|
|
|
my $owner = git_get_project_owner($project);
|
2005-08-07 18:23:12 +00:00
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
my $refs = git_get_references();
|
2006-12-19 12:08:54 +00:00
|
|
|
# These get_*_list functions return one more to allow us to see if
|
|
|
|
# there are more ...
|
|
|
|
my @taglist = git_get_tags_list(16);
|
|
|
|
my @headlist = git_get_heads_list(16);
|
2010-11-11 12:26:17 +00:00
|
|
|
my %remotedata = $remote_heads ? git_get_remotes_list() : ();
|
2006-10-24 03:33:17 +00:00
|
|
|
my @forklist;
|
2008-11-29 21:07:29 +00:00
|
|
|
my $check_forks = gitweb_check_feature('forks');
|
2006-11-08 06:00:45 +00:00
|
|
|
|
|
|
|
if ($check_forks) {
|
2006-10-24 03:33:17 +00:00
|
|
|
@forklist = git_get_projects_list($project);
|
|
|
|
}
|
2006-09-19 12:33:22 +00:00
|
|
|
|
2005-08-07 18:23:12 +00:00
|
|
|
git_header_html();
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_page_nav('summary','', $head);
|
2006-07-31 09:22:13 +00:00
|
|
|
|
2005-08-07 18:26:27 +00:00
|
|
|
print "<div class=\"title\"> </div>\n";
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"projects_list\">\n" .
|
2008-10-02 14:25:05 +00:00
|
|
|
"<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";
|
2007-05-13 10:39:22 +00:00
|
|
|
if (defined $cd{'rfc2822'}) {
|
2008-10-02 14:25:05 +00:00
|
|
|
print "<tr id=\"metadata_lchange\"><td>last change</td><td>$cd{'rfc2822'}</td></tr>\n";
|
2007-05-13 10:39:22 +00:00
|
|
|
}
|
|
|
|
|
2006-08-16 12:50:34 +00:00
|
|
|
# use per project git URL list in $projectroot/$project/cloneurl
|
|
|
|
# or make project git URL from git base URL and project name
|
2006-08-15 21:03:17 +00:00
|
|
|
my $url_tag = "URL";
|
2006-08-16 12:50:34 +00:00
|
|
|
my @url_list = git_get_project_url_list($project);
|
|
|
|
@url_list = map { "$_/$project" } @git_base_url_list unless @url_list;
|
|
|
|
foreach my $git_url (@url_list) {
|
|
|
|
next unless $git_url;
|
2010-11-11 12:26:15 +00:00
|
|
|
print format_repo_url($url_tag, $git_url);
|
2006-08-15 21:03:17 +00:00
|
|
|
$url_tag = "";
|
|
|
|
}
|
2008-10-02 15:13:02 +00:00
|
|
|
|
|
|
|
# Tag cloud
|
2008-11-29 21:07:29 +00:00
|
|
|
my $show_ctags = gitweb_check_feature('ctags');
|
2008-10-02 15:13:02 +00:00
|
|
|
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>";
|
|
|
|
}
|
|
|
|
|
2006-08-15 21:03:17 +00:00
|
|
|
print "</table>\n";
|
2006-07-31 09:22:13 +00:00
|
|
|
|
2009-02-08 00:00:09 +00:00
|
|
|
# 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") {
|
2008-12-01 18:01:42 +00:00
|
|
|
print "<div class=\"title\">readme</div>\n" .
|
|
|
|
"<div class=\"readme\">\n";
|
|
|
|
insert_file("$projectroot/$project/README.html");
|
|
|
|
print "\n</div>\n"; # class="readme"
|
2006-10-24 03:23:46 +00:00
|
|
|
}
|
|
|
|
|
2006-12-19 12:08:54 +00:00
|
|
|
# we need to request one more than 16 (0..15) to check if
|
|
|
|
# those 16 are all
|
2007-05-13 10:39:22 +00:00
|
|
|
my @commitlist = $head ? parse_commits($head, 17) : ();
|
|
|
|
if (@commitlist) {
|
|
|
|
git_print_header_div('shortlog');
|
|
|
|
git_shortlog_body(\@commitlist, 0, 15, $refs,
|
|
|
|
$#commitlist <= 15 ? undef :
|
|
|
|
$cgi->a({-href => href(action=>"shortlog")}, "..."));
|
|
|
|
}
|
2005-08-07 18:23:12 +00:00
|
|
|
|
2006-09-19 12:33:22 +00:00
|
|
|
if (@taglist) {
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('tags');
|
2006-09-19 12:33:22 +00:00
|
|
|
git_tags_body(\@taglist, 0, 15,
|
2006-12-19 12:08:54 +00:00
|
|
|
$#taglist <= 15 ? undef :
|
2006-08-15 22:24:30 +00:00
|
|
|
$cgi->a({-href => href(action=>"tags")}, "..."));
|
2005-08-07 18:23:12 +00:00
|
|
|
}
|
2005-08-07 18:24:35 +00:00
|
|
|
|
2006-09-19 12:33:22 +00:00
|
|
|
if (@headlist) {
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('heads');
|
2006-09-19 12:33:22 +00:00
|
|
|
git_heads_body(\@headlist, $head, 0, 15,
|
2006-12-19 12:08:54 +00:00
|
|
|
$#headlist <= 15 ? undef :
|
2006-08-15 22:24:30 +00:00
|
|
|
$cgi->a({-href => href(action=>"heads")}, "..."));
|
2005-08-07 18:24:35 +00:00
|
|
|
}
|
2006-07-31 09:22:13 +00:00
|
|
|
|
2010-11-11 12:26:17 +00:00
|
|
|
if (%remotedata) {
|
2010-11-11 12:26:11 +00:00
|
|
|
git_print_header_div('remotes');
|
2010-11-11 12:26:17 +00:00
|
|
|
git_remotes_body(\%remotedata, 15, $head);
|
2010-11-11 12:26:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 03:33:17 +00:00
|
|
|
if (@forklist) {
|
|
|
|
git_print_header_div('forks');
|
2008-09-25 16:48:48 +00:00
|
|
|
git_project_list_body(\@forklist, 'age', 0, 15,
|
2006-12-22 19:38:12 +00:00
|
|
|
$#forklist <= 15 ? undef :
|
2006-10-24 03:33:17 +00:00
|
|
|
$cgi->a({-href => href(action=>"forks")}, "..."),
|
2008-09-25 16:48:48 +00:00
|
|
|
'no_header');
|
2006-10-24 03:33:17 +00:00
|
|
|
}
|
|
|
|
|
2005-08-07 18:23:12 +00:00
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
2005-08-07 18:28:53 +00:00
|
|
|
sub git_tag {
|
2006-08-14 00:05:47 +00:00
|
|
|
my %tag = parse_tag($hash);
|
2007-05-12 19:16:34 +00:00
|
|
|
|
|
|
|
if (! %tag) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(404, "Unknown tag object");
|
2007-05-12 19:16:34 +00:00
|
|
|
}
|
|
|
|
|
2010-08-27 17:38:16 +00:00
|
|
|
my $head = git_get_head_hash($project);
|
|
|
|
git_header_html();
|
|
|
|
git_print_page_nav('','', $head,undef,$head);
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('commit', esc_html($tag{'name'}), $hash);
|
2005-08-07 18:28:53 +00:00
|
|
|
print "<div class=\"title_text\">\n" .
|
2007-11-19 13:16:11 +00:00
|
|
|
"<table class=\"object_header\">\n" .
|
2005-08-07 22:02:39 +00:00
|
|
|
"<tr>\n" .
|
|
|
|
"<td>object</td>\n" .
|
2006-08-22 14:52:50 +00:00
|
|
|
"<td>" . $cgi->a({-class => "list", -href => href(action=>$tag{'type'}, hash=>$tag{'object'})},
|
|
|
|
$tag{'object'}) . "</td>\n" .
|
|
|
|
"<td class=\"link\">" . $cgi->a({-href => href(action=>$tag{'type'}, hash=>$tag{'object'})},
|
|
|
|
$tag{'type'}) . "</td>\n" .
|
2005-08-07 22:02:39 +00:00
|
|
|
"</tr>\n";
|
2005-08-07 18:28:53 +00:00
|
|
|
if (defined($tag{'author'})) {
|
2009-06-29 22:00:50 +00:00
|
|
|
git_print_authorship_rows(\%tag, 'author');
|
2005-08-07 18:28:53 +00:00
|
|
|
}
|
|
|
|
print "</table>\n\n" .
|
|
|
|
"</div>\n";
|
|
|
|
print "<div class=\"page_body\">";
|
|
|
|
my $comment = $tag{'comment'};
|
|
|
|
foreach my $line (@$comment) {
|
2006-11-24 22:04:01 +00:00
|
|
|
chomp $line;
|
2006-11-24 21:25:50 +00:00
|
|
|
print esc_html($line, -nbsp=>1) . "<br/>\n";
|
2005-08-07 18:28:53 +00:00
|
|
|
}
|
|
|
|
print "</div>\n";
|
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
sub git_blame_common {
|
|
|
|
my $format = shift || 'porcelain';
|
gitweb: Create links leading to 'blame_incremental' using JavaScript
The new 'blame_incremental' view requires JavaScript to run. Not all
web browsers implement JavaScript (e.g. text browsers such as Lynx),
and not all users have JavaScript enabled. Therefore instead of
unconditionally linking to 'blame_incremental' view, we use JavaScript
to convert those links to lead to view utilizing JavaScript, by adding
'js=1' to link.
Currently the only action that takes 'js=1' into account is 'blame',
which then acts as if it was called as 'blame_incremental' action.
Possible enhancement would be to do JavaScript redirect by setting
window.location instead of modifying $format and $action in
git_blame_common() subroutine.
The only JavaScript-aware/using view is currently 'blame_incremental'.
While at it move reading JavaScript to git_footer_html() subroutine.
Note that in this view we do not add 'js=1' currently (even though
perhaps we should; note that for consistency we should also add 'js=1'
in links added by JavaScript part of 'blame_incremental').
This idea was originally implemented by Petr Baudis in
http://article.gmane.org/gmane.comp.version-control.git/47614
but it added <script> element with fixBlameLinks() function in page
header, to be added as onload event using 'onload' attribute of HTML
'body' element: <body onload="fixBlameLinks();">. This version adds
script at then end of page (in the page footer), and uses JavaScript
'window.onload=fixLinks();'. Also in Petr version only links marked
with 'blamelink' class were modified, and they were modified by
replacing "a=blame" by "a=blame_incremental"... which doesn't work for
path_info links, and might replace wrong part if there is "a=blame" in
project name, ref name or file name.
Slightly different solution was implemented by Martin Koegler in
http://thread.gmane.org/gmane.comp.version-control.git/47902/focus=47905
Here GitAddLinks() function was in gitweb.js file, not as contents of
<script> element. It was also included in page header (in <head>
element) though, which means waiting for a script to load (and run).
It was smarter in that to "fix" (modify) link, it split URL, modified
value of 'a' parameter, and then recreated modified link. It avoids
trouble with "a=blame" as substring in project name or file name, but
it doesn't work with path_info URL/link in the way it was written.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:19 +00:00
|
|
|
if ($format eq 'porcelain' && $cgi->param('js')) {
|
|
|
|
$format = 'incremental';
|
|
|
|
$action = 'blame_incremental'; # for page title etc
|
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
# permissions
|
2008-11-29 21:07:29 +00:00
|
|
|
gitweb_check_feature('blame')
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
or die_error(403, "Blame view not allowed");
|
2008-06-19 20:03:21 +00:00
|
|
|
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
# error checking
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "No file name given") unless $file_name;
|
2006-08-14 00:05:47 +00:00
|
|
|
$hash_base ||= git_get_head_hash($project);
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
die_error(404, "Couldn't find base commit") unless $hash_base;
|
2006-08-14 00:05:47 +00:00
|
|
|
my %co = parse_commit($hash_base)
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Commit not found");
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
my $ftype = "blob";
|
2006-07-23 20:34:55 +00:00
|
|
|
if (!defined $hash) {
|
|
|
|
$hash = git_get_hash_by_path($hash_base, $file_name, "blob")
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Error looking up file");
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
} else {
|
|
|
|
$ftype = git_get_type($hash);
|
|
|
|
if ($ftype !~ "blob") {
|
|
|
|
die_error(400, "Object is not a blob");
|
|
|
|
}
|
2006-07-23 20:34:55 +00:00
|
|
|
}
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
my $fd;
|
|
|
|
if ($format eq 'incremental') {
|
|
|
|
# get file contents (as base)
|
|
|
|
open $fd, "-|", git_cmd(), 'cat-file', 'blob', $hash
|
|
|
|
or die_error(500, "Open git-cat-file failed");
|
|
|
|
} elsif ($format eq 'data') {
|
|
|
|
# run git-blame --incremental
|
|
|
|
open $fd, "-|", git_cmd(), "blame", "--incremental",
|
|
|
|
$hash_base, "--", $file_name
|
|
|
|
or die_error(500, "Open git-blame --incremental failed");
|
|
|
|
} else {
|
|
|
|
# run git-blame --porcelain
|
|
|
|
open $fd, "-|", git_cmd(), "blame", '-p',
|
|
|
|
$hash_base, '--', $file_name
|
|
|
|
or die_error(500, "Open git-blame --porcelain failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
# incremental blame data returns early
|
|
|
|
if ($format eq 'data') {
|
|
|
|
print $cgi->header(
|
|
|
|
-type=>"text/plain", -charset => "utf-8",
|
|
|
|
-status=> "200 OK");
|
|
|
|
local $| = 1; # output autoflush
|
|
|
|
print while <$fd>;
|
|
|
|
close $fd
|
|
|
|
or print "ERROR $!\n";
|
|
|
|
|
|
|
|
print 'END';
|
|
|
|
if (defined $t0 && gitweb_check_feature('timed')) {
|
|
|
|
print ' '.
|
2010-11-09 18:27:54 +00:00
|
|
|
tv_interval($t0, [ gettimeofday() ]).
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
' '.$number_of_git_cmds;
|
|
|
|
}
|
|
|
|
print "\n";
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
|
|
|
|
# page header
|
2006-07-23 20:34:55 +00:00
|
|
|
git_header_html();
|
2006-07-30 13:01:07 +00:00
|
|
|
my $formats_nav =
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"blob", -replay=>1)},
|
2006-08-22 14:52:50 +00:00
|
|
|
"blob") .
|
2009-12-01 16:54:26 +00:00
|
|
|
" | ";
|
|
|
|
if ($format eq 'incremental') {
|
|
|
|
$formats_nav .=
|
|
|
|
$cgi->a({-href => href(action=>"blame", javascript=>0, -replay=>1)},
|
|
|
|
"blame") . " (non-incremental)";
|
|
|
|
} else {
|
|
|
|
$formats_nav .=
|
|
|
|
$cgi->a({-href => href(action=>"blame_incremental", -replay=>1)},
|
|
|
|
"blame") . " (incremental)";
|
|
|
|
}
|
|
|
|
$formats_nav .=
|
2006-08-22 14:52:50 +00:00
|
|
|
" | " .
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"history", -replay=>1)},
|
|
|
|
"history") .
|
2006-09-22 01:19:41 +00:00
|
|
|
" | " .
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
$cgi->a({-href => href(action=>$action, file_name=>$file_name)},
|
2006-09-22 01:19:53 +00:00
|
|
|
"HEAD");
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
|
|
|
|
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
|
2006-08-17 17:39:29 +00:00
|
|
|
git_print_page_path($file_name, $ftype, $hash_base);
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
|
|
|
|
# page body
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
if ($format eq 'incremental') {
|
|
|
|
print "<noscript>\n<div class=\"error\"><center><b>\n".
|
|
|
|
"This page requires JavaScript to run.\n Use ".
|
gitweb: Create links leading to 'blame_incremental' using JavaScript
The new 'blame_incremental' view requires JavaScript to run. Not all
web browsers implement JavaScript (e.g. text browsers such as Lynx),
and not all users have JavaScript enabled. Therefore instead of
unconditionally linking to 'blame_incremental' view, we use JavaScript
to convert those links to lead to view utilizing JavaScript, by adding
'js=1' to link.
Currently the only action that takes 'js=1' into account is 'blame',
which then acts as if it was called as 'blame_incremental' action.
Possible enhancement would be to do JavaScript redirect by setting
window.location instead of modifying $format and $action in
git_blame_common() subroutine.
The only JavaScript-aware/using view is currently 'blame_incremental'.
While at it move reading JavaScript to git_footer_html() subroutine.
Note that in this view we do not add 'js=1' currently (even though
perhaps we should; note that for consistency we should also add 'js=1'
in links added by JavaScript part of 'blame_incremental').
This idea was originally implemented by Petr Baudis in
http://article.gmane.org/gmane.comp.version-control.git/47614
but it added <script> element with fixBlameLinks() function in page
header, to be added as onload event using 'onload' attribute of HTML
'body' element: <body onload="fixBlameLinks();">. This version adds
script at then end of page (in the page footer), and uses JavaScript
'window.onload=fixLinks();'. Also in Petr version only links marked
with 'blamelink' class were modified, and they were modified by
replacing "a=blame" by "a=blame_incremental"... which doesn't work for
path_info links, and might replace wrong part if there is "a=blame" in
project name, ref name or file name.
Slightly different solution was implemented by Martin Koegler in
http://thread.gmane.org/gmane.comp.version-control.git/47902/focus=47905
Here GitAddLinks() function was in gitweb.js file, not as contents of
<script> element. It was also included in page header (in <head>
element) though, which means waiting for a script to load (and run).
It was smarter in that to "fix" (modify) link, it split URL, modified
value of 'a' parameter, and then recreated modified link. It avoids
trouble with "a=blame" as substring in project name or file name, but
it doesn't work with path_info URL/link in the way it was written.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:19 +00:00
|
|
|
$cgi->a({-href => href(action=>'blame',javascript=>0,-replay=>1)},
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
'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 qq!<div class="page_body">\n!;
|
|
|
|
print qq!<div id="progress_info">... / ...</div>\n!
|
|
|
|
if ($format eq 'incremental');
|
|
|
|
print 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!.
|
|
|
|
qq!</thead>\n!.
|
|
|
|
qq!<tbody>\n!;
|
|
|
|
|
2009-07-24 22:44:06 +00:00
|
|
|
my @rev_color = qw(light dark);
|
2006-07-23 20:37:53 +00:00
|
|
|
my $num_colors = scalar(@rev_color);
|
|
|
|
my $current_color = 0;
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
if ($format eq 'incremental') {
|
|
|
|
my $color_class = $rev_color[$current_color];
|
|
|
|
|
|
|
|
#contents of a file
|
|
|
|
my $linenr = 0;
|
|
|
|
LINE:
|
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
$linenr++;
|
|
|
|
|
|
|
|
print 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!;
|
2006-10-05 20:55:58 +00:00
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
|
|
|
|
} else { # porcelain, i.e. ordinary blame
|
|
|
|
my %metainfo = (); # saves information about commits
|
|
|
|
|
|
|
|
# blame data
|
|
|
|
LINE:
|
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
# the header: <SHA-1> <src lineno> <dst lineno> [<lines in group>]
|
|
|
|
# no <lines in group> for subsequent lines in group of lines
|
|
|
|
my ($full_rev, $orig_lineno, $lineno, $group_size) =
|
|
|
|
($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/);
|
|
|
|
if (!exists $metainfo{$full_rev}) {
|
|
|
|
$metainfo{$full_rev} = { 'nprevious' => 0 };
|
2006-10-05 20:55:58 +00:00
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
my $meta = $metainfo{$full_rev};
|
|
|
|
my $data;
|
|
|
|
while ($data = <$fd>) {
|
|
|
|
chomp $data;
|
|
|
|
last if ($data =~ s/^\t//); # contents of line
|
|
|
|
if ($data =~ /^(\S+)(?: (.*))?$/) {
|
|
|
|
$meta->{$1} = $2 unless exists $meta->{$1};
|
|
|
|
}
|
|
|
|
if ($data =~ /^previous /) {
|
|
|
|
$meta->{'nprevious'}++;
|
|
|
|
}
|
2006-10-05 20:55:58 +00:00
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
my $short_rev = substr($full_rev, 0, 8);
|
|
|
|
my $author = $meta->{'author'};
|
|
|
|
my %date =
|
|
|
|
parse_date($meta->{'author-time'}, $meta->{'author-tz'});
|
|
|
|
my $date = $date{'iso-tz'};
|
|
|
|
if ($group_size) {
|
|
|
|
$current_color = ($current_color + 1) % $num_colors;
|
2009-07-24 22:44:04 +00:00
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
my $tr_class = $rev_color[$current_color];
|
|
|
|
$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";
|
|
|
|
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",
|
|
|
|
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 />" .
|
|
|
|
esc_html(join('', @author_initials));
|
|
|
|
# or join('.', ...)
|
|
|
|
}
|
2009-07-24 22:44:05 +00:00
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
print "</td>\n";
|
2009-07-24 22:44:05 +00:00
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
# 'previous' <sha1 of parent commit> <filename at commit>
|
|
|
|
if (exists $meta->{'previous'} &&
|
|
|
|
$meta->{'previous'} =~ /^([a-fA-F0-9]{40}) (.*)$/) {
|
|
|
|
$meta->{'parent'} = $1;
|
|
|
|
$meta->{'file_parent'} = unquote($2);
|
|
|
|
}
|
|
|
|
my $linenr_commit =
|
|
|
|
exists($meta->{'parent'}) ?
|
|
|
|
$meta->{'parent'} : $full_rev;
|
|
|
|
my $linenr_filename =
|
|
|
|
exists($meta->{'file_parent'}) ?
|
|
|
|
$meta->{'file_parent'} : unquote($meta->{'filename'});
|
|
|
|
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",
|
|
|
|
-class => "linenr" },
|
|
|
|
esc_html($lineno));
|
|
|
|
print "</td>";
|
|
|
|
print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
|
|
|
|
print "</tr>\n";
|
|
|
|
} # end while
|
|
|
|
|
2006-07-23 20:34:55 +00:00
|
|
|
}
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
|
|
|
|
# footer
|
|
|
|
print "</tbody>\n".
|
|
|
|
"</table>\n"; # class="blame"
|
|
|
|
print "</div>\n"; # class="blame_body"
|
2006-08-22 14:52:50 +00:00
|
|
|
close $fd
|
|
|
|
or print "Reading blob failed\n";
|
gitweb: A bit of code cleanup in git_blame()
Among others, here are the highlights:
* move variable declaration closer to the place it is set and used,
if possible,
* uniquify and simplify coding style a bit, which includes removing
unnecessary '()'.
* check type only if $hash was defined, as otherwise from the way
git_get_hash_by_path() is called (and works), we know that it is
a blob,
* use modern calling convention for git-blame,
* remove unused variable,
* don't use implicit variables ($_),
* add some comments
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Acked-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-12-09 22:48:51 +00:00
|
|
|
|
2006-07-23 20:34:55 +00:00
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
gitweb: Incremental blame (using JavaScript)
Add 'blame_incremental' view, which uses "git blame --incremental"
and JavaScript (Ajax), where 'blame' use "git blame --porcelain".
* gitweb generates initial info by putting file contents (from
"git cat-file") together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
function from gitweb.js
* startBlame() opens XMLHttpRequest connection to 'blame_data' view,
which in turn calls "git blame --incremental" for a file, and
streams output of git-blame to JavaScript (gitweb.js)
* XMLHttpRequest event handler updates line info in blame view as soon
as it gets data from 'blame_data' (from server), and it also updates
progress info
* when 'blame_data' ends, and gitweb.js finishes updating line info,
it fixes colors to match (as far as possible) ordinary 'blame' view,
and updates information about how long it took to generate page.
Gitweb deals with streamed 'blame_data' server errors by displaying
them in the progress info area (just in case).
The 'blame_incremental' view tries to be equivalent to 'blame' action;
there are however a few differences in output between 'blame' and
'blame_incremental' view:
* 'blame_incremental' always used query form for this part of link(s)
which is generated by JavaScript code. The difference is visible
if we use path_info link (pass some or all arguments in path_info).
Changing this would require implementing something akin to href()
subroutine from gitweb.perl in JavaScript (in gitweb.js).
* 'blame_incremental' always uses "rowspan" attribute, even if
rowspan="1". This simplifies code, and is not visible to user.
* The progress bar and progress info are still there even after
JavaScript part of 'blame_incremental' finishes work.
Note that currently no link generated by gitweb leads to this new view.
This code is based on patch by Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.
This patch adds GITWEB_JS compile configuration option, and modifies
git-instaweb.sh to take gitweb.js into account. The code for
git-instaweb.sh was taken from Pasky's patch.
Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-01 11:39:17 +00:00
|
|
|
sub git_blame {
|
|
|
|
git_blame_common();
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_blame_incremental {
|
|
|
|
git_blame_common('incremental');
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_blame_data {
|
|
|
|
git_blame_common('data');
|
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub git_tags {
|
2006-08-14 00:05:47 +00:00
|
|
|
my $head = git_get_head_hash($project);
|
2006-07-31 19:22:15 +00:00
|
|
|
git_header_html();
|
2010-11-11 12:26:12 +00:00
|
|
|
git_print_page_nav('','', $head,undef,$head,format_ref_views('tags'));
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('summary', $project);
|
2006-06-17 22:01:06 +00:00
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
my @tagslist = git_get_tags_list();
|
|
|
|
if (@tagslist) {
|
|
|
|
git_tags_body(\@tagslist);
|
2006-06-17 22:01:06 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
git_footer_html();
|
2006-06-17 22:01:06 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 19:22:15 +00:00
|
|
|
sub git_heads {
|
2006-08-14 00:05:47 +00:00
|
|
|
my $head = git_get_head_hash($project);
|
2006-07-31 19:22:15 +00:00
|
|
|
git_header_html();
|
2010-11-11 12:26:12 +00:00
|
|
|
git_print_page_nav('','', $head,undef,$head,format_ref_views('heads'));
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('summary', $project);
|
2006-07-10 03:18:57 +00:00
|
|
|
|
gitweb: Use git-for-each-ref to generate list of heads and/or tags
Add two subroutines: git_get_heads_list and git_get_refs_list, which
fill out needed parts of refs info (heads and tags respectively) info
using single call to git-for-each-ref, instead of using
git-peek-remote to get list of references and using parse_ref for each
ref to get ref info, which in turn uses at least one call of git
command.
Replace call to git_get_refs_list in git_summary by call to
git_get_references, git_get_heads_list and git_get_tags_list
(simplifying this subroutine a bit). Use git_get_heads_list in
git_heads and git_get_tags_list in git_tags. Modify git_tags_body
slightly to accept output from git_get_tags_list.
Remove no longer used, and a bit hackish, git_get_refs_list.
parse_ref is no longer used, but is left for now.
Generating "summary" and "tags" views should be much faster for
projects which have large number of tags.
CHANGES IN OUTPUT: Before, if ref in refs/tags was tag pointing to
commit we used committer epoch as epoch for ref, and used tagger epoch
as epoch only for tag pointing to object of other type. If ref in
refs/tags was commit, we used committer epoch as epoch for ref (see
parse_ref; we sorted in gitweb by 'epoch' field).
Currently we use committer epoch for refs pointing to commit objects,
and tagger epoch for refs pointing to tag object, even if tag points
to commit.
Simple ab benchmark before and after this patch for my git.git
repository (git/jnareb-git.git) with some heads and tags added
as compared to git.git repository, shows around 2.4-3.0 times speedup
for "summary" and "tags" views:
summary 3134 +/- 24.2 ms --> 1081 +/- 30.2 ms
tags 2886 +/- 18.9 ms --> 1196 +/- 15.6 ms
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-02 19:23:11 +00:00
|
|
|
my @headslist = git_get_heads_list();
|
|
|
|
if (@headslist) {
|
|
|
|
git_heads_body(\@headslist, $head);
|
2006-06-17 11:32:15 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
git_footer_html();
|
2006-06-17 11:32:15 +00:00
|
|
|
}
|
|
|
|
|
2010-11-11 12:26:17 +00:00
|
|
|
# used both for single remote view and for list of all the remotes
|
2010-11-11 12:26:11 +00:00
|
|
|
sub git_remotes {
|
|
|
|
gitweb_check_feature('remote_heads')
|
|
|
|
or die_error(403, "Remote heads view is disabled");
|
|
|
|
|
|
|
|
my $head = git_get_head_hash($project);
|
2010-11-11 12:26:14 +00:00
|
|
|
my $remote = $input_params{'hash'};
|
|
|
|
|
2010-11-11 12:26:17 +00:00
|
|
|
my $remotedata = git_get_remotes_list($remote);
|
|
|
|
die_error(500, "Unable to get remote information") unless defined $remotedata;
|
2010-11-11 12:26:14 +00:00
|
|
|
|
2010-11-11 12:26:17 +00:00
|
|
|
unless (%$remotedata) {
|
|
|
|
die_error(404, defined $remote ?
|
|
|
|
"Remote $remote not found" :
|
|
|
|
"No remotes found");
|
2010-11-11 12:26:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
git_header_html(undef, undef, -action_extra => $remote);
|
|
|
|
git_print_page_nav('', '', $head, undef, $head,
|
|
|
|
format_ref_views($remote ? '' : 'remotes'));
|
|
|
|
|
2010-11-11 12:26:17 +00:00
|
|
|
fill_remote_heads($remotedata);
|
2010-11-11 12:26:14 +00:00
|
|
|
if (defined $remote) {
|
|
|
|
git_print_header_div('remotes', "$remote remote for $project");
|
2010-11-11 12:26:17 +00:00
|
|
|
git_remote_block($remote, $remotedata->{$remote}, undef, $head);
|
2010-11-11 12:26:14 +00:00
|
|
|
} else {
|
|
|
|
git_print_header_div('summary', "$project remotes");
|
2010-11-11 12:26:17 +00:00
|
|
|
git_remotes_body($remotedata, undef, $head);
|
2010-11-11 12:26:11 +00:00
|
|
|
}
|
2010-11-11 12:26:14 +00:00
|
|
|
|
2010-11-11 12:26:11 +00:00
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
2005-08-07 18:26:27 +00:00
|
|
|
sub git_blob_plain {
|
2008-06-03 14:47:10 +00:00
|
|
|
my $type = shift;
|
2006-08-26 17:14:25 +00:00
|
|
|
my $expires;
|
|
|
|
|
2006-07-23 20:28:55 +00:00
|
|
|
if (!defined $hash) {
|
2006-07-29 20:43:40 +00:00
|
|
|
if (defined $file_name) {
|
2006-08-14 00:05:47 +00:00
|
|
|
my $base = $hash_base || git_get_head_hash($project);
|
2006-07-29 20:43:40 +00:00
|
|
|
$hash = git_get_hash_by_path($base, $file_name, "blob")
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Cannot find file");
|
2006-07-29 20:43:40 +00:00
|
|
|
} else {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "No file name defined");
|
2006-07-29 20:43:40 +00:00
|
|
|
}
|
2006-09-16 21:09:02 +00:00
|
|
|
} elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) {
|
|
|
|
# blobs defined by non-textual hash id's can be cached
|
|
|
|
$expires = "+1d";
|
2006-07-29 20:43:40 +00:00
|
|
|
}
|
2006-09-16 21:09:02 +00:00
|
|
|
|
2006-08-28 15:49:58 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-cat-file blob '$hash' failed");
|
2006-07-10 03:18:57 +00:00
|
|
|
|
2008-06-03 14:47:10 +00:00
|
|
|
# content-type (can include charset)
|
|
|
|
$type = blob_contenttype($fd, $file_name, $type);
|
2006-06-17 11:32:15 +00:00
|
|
|
|
2008-06-03 14:47:10 +00:00
|
|
|
# "save as" filename, even when no $file_name is given
|
2006-06-17 11:32:15 +00:00
|
|
|
my $save_as = "$hash";
|
2005-10-17 01:27:54 +00:00
|
|
|
if (defined $file_name) {
|
|
|
|
$save_as = $file_name;
|
2006-06-17 11:32:15 +00:00
|
|
|
} elsif ($type =~ m/^text\//) {
|
|
|
|
$save_as .= '.txt';
|
2005-10-17 01:27:54 +00:00
|
|
|
}
|
2006-06-17 11:32:15 +00:00
|
|
|
|
2009-02-08 00:00:09 +00:00
|
|
|
# With XSS prevention on, blobs of all types except a few known safe
|
|
|
|
# ones are served with "Content-Disposition: attachment" to make sure
|
|
|
|
# they don't run in our security domain. For certain image types,
|
|
|
|
# blob view writes an <img> tag referring to blob_plain view, and we
|
|
|
|
# want to be sure not to break that by serving the image as an
|
|
|
|
# attachment (though Firefox 3 doesn't seem to care).
|
|
|
|
my $sandbox = $prevent_xss &&
|
|
|
|
$type !~ m!^(?:text/plain|image/(?:gif|png|jpeg))$!;
|
|
|
|
|
2006-08-26 17:14:25 +00:00
|
|
|
print $cgi->header(
|
2008-06-03 14:47:10 +00:00
|
|
|
-type => $type,
|
|
|
|
-expires => $expires,
|
2009-02-08 00:00:09 +00:00
|
|
|
-content_disposition =>
|
|
|
|
($sandbox ? 'attachment' : 'inline')
|
|
|
|
. '; filename="' . $save_as . '"');
|
2009-05-11 01:29:40 +00:00
|
|
|
local $/ = undef;
|
2006-06-17 16:07:24 +00:00
|
|
|
binmode STDOUT, ':raw';
|
2005-08-07 18:26:27 +00:00
|
|
|
print <$fd>;
|
2006-06-17 16:07:24 +00:00
|
|
|
binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
|
2005-08-07 18:26:27 +00:00
|
|
|
close $fd;
|
|
|
|
}
|
|
|
|
|
2006-07-10 03:18:57 +00:00
|
|
|
sub git_blob {
|
2006-08-26 17:14:25 +00:00
|
|
|
my $expires;
|
|
|
|
|
2006-07-23 20:28:55 +00:00
|
|
|
if (!defined $hash) {
|
2006-07-29 20:43:40 +00:00
|
|
|
if (defined $file_name) {
|
2006-08-14 00:05:47 +00:00
|
|
|
my $base = $hash_base || git_get_head_hash($project);
|
2006-07-29 20:43:40 +00:00
|
|
|
$hash = git_get_hash_by_path($base, $file_name, "blob")
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Cannot find file");
|
2006-07-29 20:43:40 +00:00
|
|
|
} else {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "No file name defined");
|
2006-07-29 20:43:40 +00:00
|
|
|
}
|
2006-09-16 21:09:02 +00:00
|
|
|
} elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) {
|
|
|
|
# blobs defined by non-textual hash id's can be cached
|
|
|
|
$expires = "+1d";
|
2006-07-29 20:43:40 +00:00
|
|
|
}
|
2006-09-16 21:09:02 +00:00
|
|
|
|
2008-11-29 21:07:29 +00:00
|
|
|
my $have_blame = gitweb_check_feature('blame');
|
2006-08-28 15:49:58 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Couldn't cat $file_name, $hash");
|
2006-08-14 00:05:47 +00:00
|
|
|
my $mimetype = blob_mimetype($fd, $file_name);
|
2010-04-27 19:34:44 +00:00
|
|
|
# use 'blob_plain' (aka 'raw') view for files that cannot be displayed
|
2007-12-15 14:41:49 +00:00
|
|
|
if ($mimetype !~ m!^(?:text/|image/(?:gif|png|jpeg)$)! && -B $fd) {
|
2006-07-10 03:18:57 +00:00
|
|
|
close $fd;
|
|
|
|
return git_blob_plain($mimetype);
|
|
|
|
}
|
gitweb: Allow PNG, GIF, JPEG images to be displayed in "blob" view
Allow images in one of web formats (PNG, GIF, JPEG) - actually files
with mimetype of image/png, image/git, image/jpeg - to be displayed in
"blob" view using <img /> element, instead of using "blob_plain" view
for them, like for all other files except also text/* mimetype files.
This makes possible to easily go to file history, to HEAD version of
the file, to appropriate commit etc; all of those are not available
in "blob_plain" (raw) view.
Only text files can have "blame" view link in the formats part of
navbar.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-04 22:47:22 +00:00
|
|
|
# we can have blame only for text/* mimetype
|
|
|
|
$have_blame &&= ($mimetype =~ m!^text/!);
|
|
|
|
|
2010-04-27 19:34:45 +00:00
|
|
|
my $highlight = gitweb_check_feature('highlight');
|
|
|
|
my $syntax = guess_file_syntax($highlight, $mimetype, $file_name);
|
|
|
|
$fd = run_highlighter($fd, $highlight, $syntax)
|
|
|
|
if $syntax;
|
2010-04-27 19:34:44 +00:00
|
|
|
|
2006-08-26 17:14:25 +00:00
|
|
|
git_header_html(undef, $expires);
|
2006-07-30 13:01:07 +00:00
|
|
|
my $formats_nav = '';
|
2006-08-14 00:05:47 +00:00
|
|
|
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
|
2006-07-10 03:18:57 +00:00
|
|
|
if (defined $file_name) {
|
|
|
|
if ($have_blame) {
|
2006-08-22 14:52:50 +00:00
|
|
|
$formats_nav .=
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"blame", -replay=>1)},
|
2006-08-22 14:52:50 +00:00
|
|
|
"blame") .
|
|
|
|
" | ";
|
2006-07-10 03:18:57 +00:00
|
|
|
}
|
2006-07-30 13:01:07 +00:00
|
|
|
$formats_nav .=
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"history", -replay=>1)},
|
2006-09-22 01:19:41 +00:00
|
|
|
"history") .
|
|
|
|
" | " .
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"blob_plain", -replay=>1)},
|
2006-09-22 01:19:50 +00:00
|
|
|
"raw") .
|
2006-08-22 14:52:50 +00:00
|
|
|
" | " .
|
|
|
|
$cgi->a({-href => href(action=>"blob",
|
|
|
|
hash_base=>"HEAD", file_name=>$file_name)},
|
2006-09-22 01:19:53 +00:00
|
|
|
"HEAD");
|
2006-07-10 03:18:57 +00:00
|
|
|
} else {
|
2006-08-22 14:52:50 +00:00
|
|
|
$formats_nav .=
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"blob_plain", -replay=>1)},
|
|
|
|
"raw");
|
2006-07-10 03:18:57 +00:00
|
|
|
}
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
|
|
|
|
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
|
2006-07-10 03:18:57 +00:00
|
|
|
} else {
|
|
|
|
print "<div class=\"page_nav\">\n" .
|
|
|
|
"<br/><br/></div>\n" .
|
2010-12-14 23:34:01 +00:00
|
|
|
"<div class=\"title\">".esc_html($hash)."</div>\n";
|
2006-07-10 03:18:57 +00:00
|
|
|
}
|
2006-08-17 17:39:29 +00:00
|
|
|
git_print_page_path($file_name, "blob", $hash_base);
|
2006-07-10 03:18:57 +00:00
|
|
|
print "<div class=\"page_body\">\n";
|
2007-12-15 14:41:49 +00:00
|
|
|
if ($mimetype =~ m!^image/!) {
|
2010-12-14 23:34:01 +00:00
|
|
|
print qq!<img type="!.esc_attr($mimetype).qq!"!;
|
gitweb: Allow PNG, GIF, JPEG images to be displayed in "blob" view
Allow images in one of web formats (PNG, GIF, JPEG) - actually files
with mimetype of image/png, image/git, image/jpeg - to be displayed in
"blob" view using <img /> element, instead of using "blob_plain" view
for them, like for all other files except also text/* mimetype files.
This makes possible to easily go to file history, to HEAD version of
the file, to appropriate commit etc; all of those are not available
in "blob_plain" (raw) view.
Only text files can have "blame" view link in the formats part of
navbar.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-04 22:47:22 +00:00
|
|
|
if ($file_name) {
|
2010-12-14 23:34:01 +00:00
|
|
|
print qq! alt="!.esc_attr($file_name).qq!" title="!.esc_attr($file_name).qq!"!;
|
gitweb: Allow PNG, GIF, JPEG images to be displayed in "blob" view
Allow images in one of web formats (PNG, GIF, JPEG) - actually files
with mimetype of image/png, image/git, image/jpeg - to be displayed in
"blob" view using <img /> element, instead of using "blob_plain" view
for them, like for all other files except also text/* mimetype files.
This makes possible to easily go to file history, to HEAD version of
the file, to appropriate commit etc; all of those are not available
in "blob_plain" (raw) view.
Only text files can have "blame" view link in the formats part of
navbar.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-04 22:47:22 +00:00
|
|
|
}
|
|
|
|
print qq! src="! .
|
|
|
|
href(action=>"blob_plain", hash=>$hash,
|
|
|
|
hash_base=>$hash_base, file_name=>$file_name) .
|
|
|
|
qq!" />\n!;
|
2007-12-15 14:41:49 +00:00
|
|
|
} else {
|
|
|
|
my $nr;
|
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
$nr++;
|
|
|
|
$line = untabify($line);
|
2010-04-27 19:34:45 +00:00
|
|
|
printf qq!<div class="pre"><a id="l%i" href="%s#l%i" class="linenr">%4i</a> %s</div>\n!,
|
2010-12-15 19:45:36 +00:00
|
|
|
$nr, esc_attr(href(-replay => 1)), $nr, $nr, $syntax ? $line : esc_html($line, -nbsp=>1);
|
2007-12-15 14:41:49 +00:00
|
|
|
}
|
2006-07-10 03:18:57 +00:00
|
|
|
}
|
2006-08-22 14:52:50 +00:00
|
|
|
close $fd
|
|
|
|
or print "Reading blob failed.\n";
|
2006-07-10 03:18:57 +00:00
|
|
|
print "</div>";
|
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
2005-08-07 18:21:23 +00:00
|
|
|
sub git_tree {
|
2006-09-29 16:57:43 +00:00
|
|
|
if (!defined $hash_base) {
|
|
|
|
$hash_base = "HEAD";
|
|
|
|
}
|
2005-08-07 18:21:04 +00:00
|
|
|
if (!defined $hash) {
|
2005-08-07 18:21:23 +00:00
|
|
|
if (defined $file_name) {
|
2006-09-29 16:57:43 +00:00
|
|
|
$hash = git_get_hash_by_path($hash_base, $file_name, "tree");
|
|
|
|
} else {
|
|
|
|
$hash = $hash_base;
|
2005-08-07 18:25:27 +00:00
|
|
|
}
|
2005-08-07 18:23:35 +00:00
|
|
|
}
|
2008-10-02 14:50:04 +00:00
|
|
|
die_error(404, "No such tree") unless defined($hash);
|
2009-05-11 01:29:40 +00:00
|
|
|
|
2009-09-07 12:40:00 +00:00
|
|
|
my $show_sizes = gitweb_check_feature('show-sizes');
|
|
|
|
my $have_blame = gitweb_check_feature('blame');
|
|
|
|
|
2009-05-11 01:29:40 +00:00
|
|
|
my @entries = ();
|
|
|
|
{
|
|
|
|
local $/ = "\0";
|
2009-09-07 12:40:00 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "ls-tree", '-z',
|
|
|
|
($show_sizes ? '-l' : ()), @extra_options, $hash
|
2009-05-11 01:29:40 +00:00
|
|
|
or die_error(500, "Open git-ls-tree failed");
|
|
|
|
@entries = map { chomp; $_ } <$fd>;
|
|
|
|
close $fd
|
|
|
|
or die_error(404, "Reading tree failed");
|
|
|
|
}
|
2005-08-07 18:18:13 +00:00
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
my $refs = git_get_references();
|
|
|
|
my $ref = format_ref_marker($refs, $hash_base);
|
2005-08-07 18:02:47 +00:00
|
|
|
git_header_html();
|
2006-10-21 15:53:09 +00:00
|
|
|
my $basedir = '';
|
2006-08-14 00:05:47 +00:00
|
|
|
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
|
2006-09-22 01:19:41 +00:00
|
|
|
my @views_nav = ();
|
|
|
|
if (defined $file_name) {
|
|
|
|
push @views_nav,
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"history", -replay=>1)},
|
2006-09-22 01:19:41 +00:00
|
|
|
"history"),
|
|
|
|
$cgi->a({-href => href(action=>"tree",
|
|
|
|
hash_base=>"HEAD", file_name=>$file_name)},
|
2006-09-22 01:19:53 +00:00
|
|
|
"HEAD"),
|
2006-09-22 01:19:41 +00:00
|
|
|
}
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
my $snapshot_links = format_snapshot_links($hash);
|
|
|
|
if (defined $snapshot_links) {
|
2006-09-22 01:19:41 +00:00
|
|
|
# FIXME: Should be available when we have no hash base as well.
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
push @views_nav, $snapshot_links;
|
2006-09-22 01:19:41 +00:00
|
|
|
}
|
2009-09-07 12:40:00 +00:00
|
|
|
git_print_page_nav('tree','', $hash_base, undef, undef,
|
|
|
|
join(' | ', @views_nav));
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
|
2005-08-07 18:18:13 +00:00
|
|
|
} else {
|
2006-08-30 22:35:07 +00:00
|
|
|
undef $hash_base;
|
2005-08-07 18:18:13 +00:00
|
|
|
print "<div class=\"page_nav\">\n";
|
|
|
|
print "<br/><br/></div>\n";
|
2010-12-14 23:34:01 +00:00
|
|
|
print "<div class=\"title\">".esc_html($hash)."</div>\n";
|
2005-08-07 18:18:13 +00:00
|
|
|
}
|
2005-08-07 18:21:23 +00:00
|
|
|
if (defined $file_name) {
|
2006-10-21 15:53:09 +00:00
|
|
|
$basedir = $file_name;
|
|
|
|
if ($basedir ne '' && substr($basedir, -1) ne '/') {
|
|
|
|
$basedir .= '/';
|
|
|
|
}
|
2008-10-02 14:50:04 +00:00
|
|
|
git_print_page_path($file_name, 'tree', $hash_base);
|
2005-08-07 18:21:23 +00:00
|
|
|
}
|
2005-08-07 18:12:11 +00:00
|
|
|
print "<div class=\"page_body\">\n";
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"tree\">\n";
|
gitweb: "alternate" starts with shade (i.e. 1)
When displaying a list of rows (difftree, shortlog, etc),
the first entry is now printed shaded, i.e. alternate is
initialized to 1, as opposed to non-shaded (alternate
initialized to 0).
This solves the problem when there is only one row to
display -- it is displayed shaded to visually indicate that
it is "active", part of a "list", etc.
(Compare this to the trivial case of more than one entry,
where the rows have alternating shade, thus suggesting
being part of a "list" of "active" entries, etc.)
Signed-off-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-28 23:47:50 +00:00
|
|
|
my $alternate = 1;
|
2006-10-21 15:54:44 +00:00
|
|
|
# '..' (top directory) link if possible
|
|
|
|
if (defined $hash_base &&
|
|
|
|
defined $file_name && $file_name =~ m![^/]+$!) {
|
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
|
|
|
|
|
|
|
my $up = $file_name;
|
|
|
|
$up =~ s!/?[^/]+$!!;
|
|
|
|
undef $up unless $up;
|
|
|
|
# based on git_print_tree_entry
|
|
|
|
print '<td class="mode">' . mode_str('040000') . "</td>\n";
|
2009-09-07 12:40:00 +00:00
|
|
|
print '<td class="size"> </td>'."\n" if $show_sizes;
|
2006-10-21 15:54:44 +00:00
|
|
|
print '<td class="list">';
|
2009-09-07 12:40:00 +00:00
|
|
|
print $cgi->a({-href => href(action=>"tree",
|
|
|
|
hash_base=>$hash_base,
|
2006-10-21 15:54:44 +00:00
|
|
|
file_name=>$up)},
|
|
|
|
"..");
|
|
|
|
print "</td>\n";
|
|
|
|
print "<td class=\"link\"></td>\n";
|
|
|
|
|
|
|
|
print "</tr>\n";
|
|
|
|
}
|
2005-08-07 17:49:46 +00:00
|
|
|
foreach my $line (@entries) {
|
2009-09-07 12:40:00 +00:00
|
|
|
my %t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
|
2006-08-30 22:32:15 +00:00
|
|
|
|
2005-08-07 18:25:42 +00:00
|
|
|
if ($alternate) {
|
2005-08-07 18:27:18 +00:00
|
|
|
print "<tr class=\"dark\">\n";
|
2005-08-07 18:25:42 +00:00
|
|
|
} else {
|
2005-08-07 18:27:18 +00:00
|
|
|
print "<tr class=\"light\">\n";
|
2005-08-07 18:25:42 +00:00
|
|
|
}
|
|
|
|
$alternate ^= 1;
|
2006-08-30 22:32:15 +00:00
|
|
|
|
2006-10-21 15:53:09 +00:00
|
|
|
git_print_tree_entry(\%t, $basedir, $hash_base, $have_blame);
|
2006-08-30 22:35:07 +00:00
|
|
|
|
2005-08-07 18:21:46 +00:00
|
|
|
print "</tr>\n";
|
2005-08-07 17:49:46 +00:00
|
|
|
}
|
2005-08-07 18:21:46 +00:00
|
|
|
print "</table>\n" .
|
|
|
|
"</div>";
|
2005-08-07 18:02:47 +00:00
|
|
|
git_footer_html();
|
2005-08-07 18:21:23 +00:00
|
|
|
}
|
|
|
|
|
2009-11-07 15:13:29 +00:00
|
|
|
sub snapshot_name {
|
|
|
|
my ($project, $hash) = @_;
|
|
|
|
|
|
|
|
# path/to/project.git -> project
|
|
|
|
# path/to/project/.git -> project
|
|
|
|
my $name = to_utf8($project);
|
|
|
|
$name =~ s,([^/])/*\.git$,$1,;
|
|
|
|
$name = basename($name);
|
|
|
|
# sanitize name
|
|
|
|
$name =~ s/[[:cntrl:]]/?/g;
|
|
|
|
|
|
|
|
my $ver = $hash;
|
|
|
|
if ($hash =~ /^[0-9a-fA-F]+$/) {
|
|
|
|
# shorten SHA-1 hash
|
|
|
|
my $full_hash = git_get_full_hash($project, $hash);
|
|
|
|
if ($full_hash =~ /^$hash/ && length($hash) > 7) {
|
|
|
|
$ver = git_get_short_hash($project, $hash);
|
|
|
|
}
|
|
|
|
} elsif ($hash =~ m!^refs/tags/(.*)$!) {
|
|
|
|
# tags don't need shortened SHA-1 hash
|
|
|
|
$ver = $1;
|
|
|
|
} else {
|
|
|
|
# branches and other need shortened SHA-1 hash
|
|
|
|
if ($hash =~ m!^refs/(?:heads|remotes)/(.*)$!) {
|
|
|
|
$ver = $1;
|
|
|
|
}
|
|
|
|
$ver .= '-' . git_get_short_hash($project, $hash);
|
|
|
|
}
|
|
|
|
# in case of hierarchical branch names
|
|
|
|
$ver =~ s!/!.!g;
|
|
|
|
|
|
|
|
# name = project-version_string
|
|
|
|
$name = "$name-$ver";
|
|
|
|
|
|
|
|
return wantarray ? ($name, $name) : $name;
|
|
|
|
}
|
|
|
|
|
2006-08-17 15:29:46 +00:00
|
|
|
sub git_snapshot {
|
2008-10-10 18:42:26 +00:00
|
|
|
my $format = $input_params{'snapshot_format'};
|
2008-11-02 09:21:37 +00:00
|
|
|
if (!@snapshot_fmts) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(403, "Snapshots not allowed");
|
2007-07-24 23:19:58 +00:00
|
|
|
}
|
|
|
|
# default to first supported snapshot format
|
2008-11-02 09:21:37 +00:00
|
|
|
$format ||= $snapshot_fmts[0];
|
2007-07-24 23:19:58 +00:00
|
|
|
if ($format !~ m/^[a-z0-9]+$/) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Invalid snapshot format parameter");
|
2007-07-24 23:19:58 +00:00
|
|
|
} elsif (!exists($known_snapshot_formats{$format})) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Unknown snapshot format");
|
2009-08-06 14:25:39 +00:00
|
|
|
} elsif ($known_snapshot_formats{$format}{'disabled'}) {
|
|
|
|
die_error(403, "Snapshot format not allowed");
|
2009-08-25 04:59:48 +00:00
|
|
|
} elsif (!grep($_ eq $format, @snapshot_fmts)) {
|
|
|
|
die_error(403, "Unsupported snapshot format");
|
2006-08-20 06:23:04 +00:00
|
|
|
}
|
|
|
|
|
2009-09-26 17:46:08 +00:00
|
|
|
my $type = git_get_type("$hash^{}");
|
|
|
|
if (!$type) {
|
|
|
|
die_error(404, 'Object does not exist');
|
|
|
|
} elsif ($type eq 'blob') {
|
|
|
|
die_error(400, 'Object is not a tree-ish');
|
2006-08-17 15:29:46 +00:00
|
|
|
}
|
|
|
|
|
2009-11-07 15:13:29 +00:00
|
|
|
my ($name, $prefix) = snapshot_name($project, $hash);
|
|
|
|
my $filename = "$name$known_snapshot_formats{$format}{'suffix'}";
|
|
|
|
my $cmd = quote_command(
|
2008-06-17 21:46:35 +00:00
|
|
|
git_cmd(), 'archive',
|
|
|
|
"--format=$known_snapshot_formats{$format}{'format'}",
|
2009-11-07 15:13:29 +00:00
|
|
|
"--prefix=$prefix/", $hash);
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
if (exists $known_snapshot_formats{$format}{'compressor'}) {
|
2008-06-17 21:46:35 +00:00
|
|
|
$cmd .= ' | ' . quote_command(@{$known_snapshot_formats{$format}{'compressor'}});
|
2007-05-20 15:46:46 +00:00
|
|
|
}
|
2006-08-17 15:29:46 +00:00
|
|
|
|
2009-11-07 15:13:29 +00:00
|
|
|
$filename =~ s/(["\\])/\\$1/g;
|
2006-09-25 23:59:43 +00:00
|
|
|
print $cgi->header(
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
-type => $known_snapshot_formats{$format}{'type'},
|
2009-11-07 15:13:29 +00:00
|
|
|
-content_disposition => 'inline; filename="' . $filename . '"',
|
2006-09-25 23:59:43 +00:00
|
|
|
-status => '200 OK');
|
2006-08-17 15:29:46 +00:00
|
|
|
|
2007-05-20 15:46:46 +00:00
|
|
|
open my $fd, "-|", $cmd
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Execute git-archive failed");
|
2006-08-17 15:29:46 +00:00
|
|
|
binmode STDOUT, ':raw';
|
|
|
|
print <$fd>;
|
|
|
|
binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
|
|
|
|
close $fd;
|
|
|
|
}
|
|
|
|
|
2009-11-13 01:02:13 +00:00
|
|
|
sub git_log_generic {
|
2009-11-13 01:02:14 +00:00
|
|
|
my ($fmt_name, $body_subr, $base, $parent, $file_name, $file_hash) = @_;
|
2009-11-13 01:02:13 +00:00
|
|
|
|
2006-08-14 00:05:47 +00:00
|
|
|
my $head = git_get_head_hash($project);
|
2009-11-13 01:02:14 +00:00
|
|
|
if (!defined $base) {
|
|
|
|
$base = $head;
|
2005-08-07 18:24:35 +00:00
|
|
|
}
|
2005-08-07 18:26:49 +00:00
|
|
|
if (!defined $page) {
|
|
|
|
$page = 0;
|
2005-08-07 18:21:04 +00:00
|
|
|
}
|
2006-08-14 00:05:47 +00:00
|
|
|
my $refs = git_get_references();
|
2005-08-07 18:26:49 +00:00
|
|
|
|
2009-11-13 01:02:14 +00:00
|
|
|
my $commit_hash = $base;
|
|
|
|
if (defined $parent) {
|
|
|
|
$commit_hash = "$parent..$base";
|
|
|
|
}
|
|
|
|
my @commitlist =
|
|
|
|
parse_commits($commit_hash, 101, (100 * $page),
|
|
|
|
defined $file_name ? ($file_name, "--full-history") : ());
|
|
|
|
|
|
|
|
my $ftype;
|
|
|
|
if (!defined $file_hash && defined $file_name) {
|
|
|
|
# some commits could have deleted file in question,
|
|
|
|
# and not have it in tree, but one of them has to have it
|
|
|
|
for (my $i = 0; $i < @commitlist; $i++) {
|
|
|
|
$file_hash = git_get_hash_by_path($commitlist[$i]{'id'}, $file_name);
|
|
|
|
last if defined $file_hash;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (defined $file_hash) {
|
|
|
|
$ftype = git_get_type($file_hash);
|
|
|
|
}
|
|
|
|
if (defined $file_name && !defined $ftype) {
|
|
|
|
die_error(500, "Unknown type of object");
|
|
|
|
}
|
|
|
|
my %co;
|
|
|
|
if (defined $file_name) {
|
|
|
|
%co = parse_commit($base)
|
|
|
|
or die_error(404, "Unknown commit object");
|
2009-11-13 01:02:13 +00:00
|
|
|
}
|
2005-08-07 18:26:49 +00:00
|
|
|
|
2009-11-13 01:02:14 +00:00
|
|
|
|
|
|
|
my $paging_nav = format_paging_nav($fmt_name, $page, $#commitlist >= 100);
|
2009-11-13 01:02:13 +00:00
|
|
|
my $next_link = '';
|
2009-11-13 01:02:12 +00:00
|
|
|
if ($#commitlist >= 100) {
|
|
|
|
$next_link =
|
|
|
|
$cgi->a({-href => href(-replay=>1, page=>$page+1),
|
|
|
|
-accesskey => "n", -title => "Alt-n"}, "next");
|
|
|
|
}
|
2009-11-13 01:02:13 +00:00
|
|
|
my $patch_max = gitweb_get_feature('patches');
|
2009-11-13 01:02:14 +00:00
|
|
|
if ($patch_max && !defined $file_name) {
|
2008-12-18 07:13:19 +00:00
|
|
|
if ($patch_max < 0 || @commitlist <= $patch_max) {
|
|
|
|
$paging_nav .= " ⋅ " .
|
|
|
|
$cgi->a({-href => href(action=>"patches", -replay=>1)},
|
|
|
|
"patches");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-30 13:01:07 +00:00
|
|
|
git_header_html();
|
2009-11-13 01:02:13 +00:00
|
|
|
git_print_page_nav($fmt_name,'', $hash,$hash,$hash, $paging_nav);
|
2009-11-13 01:02:14 +00:00
|
|
|
if (defined $file_name) {
|
|
|
|
git_print_header_div('commit', esc_html($co{'title'}), $base);
|
|
|
|
} else {
|
|
|
|
git_print_header_div('summary', $project)
|
|
|
|
}
|
|
|
|
git_print_page_path($file_name, $ftype, $hash_base)
|
|
|
|
if (defined $file_name);
|
2006-08-17 09:21:23 +00:00
|
|
|
|
2009-11-13 01:02:14 +00:00
|
|
|
$body_subr->(\@commitlist, 0, 99, $refs, $next_link,
|
|
|
|
$file_name, $file_hash, $ftype);
|
2009-11-13 01:02:12 +00:00
|
|
|
|
2005-08-07 18:20:07 +00:00
|
|
|
git_footer_html();
|
2005-08-07 18:21:23 +00:00
|
|
|
}
|
|
|
|
|
2009-11-13 01:02:13 +00:00
|
|
|
sub git_log {
|
2009-11-13 01:02:14 +00:00
|
|
|
git_log_generic('log', \&git_log_body,
|
|
|
|
$hash, $hash_parent);
|
2009-11-13 01:02:13 +00:00
|
|
|
}
|
|
|
|
|
2005-08-07 18:21:23 +00:00
|
|
|
sub git_commit {
|
2006-11-18 22:35:41 +00:00
|
|
|
$hash ||= $hash_base || "HEAD";
|
2008-06-19 20:03:21 +00:00
|
|
|
my %co = parse_commit($hash)
|
|
|
|
or die_error(404, "Unknown commit object");
|
2005-08-07 17:49:46 +00:00
|
|
|
|
2006-12-15 20:57:16 +00:00
|
|
|
my $parent = $co{'parent'};
|
|
|
|
my $parents = $co{'parents'}; # listref
|
|
|
|
|
|
|
|
# we need to prepare $formats_nav before any parameter munging
|
|
|
|
my $formats_nav;
|
|
|
|
if (!defined $parent) {
|
|
|
|
# --root commitdiff
|
|
|
|
$formats_nav .= '(initial)';
|
|
|
|
} elsif (@$parents == 1) {
|
|
|
|
# single parent commit
|
|
|
|
$formats_nav .=
|
|
|
|
'(parent: ' .
|
|
|
|
$cgi->a({-href => href(action=>"commit",
|
|
|
|
hash=>$parent)},
|
|
|
|
esc_html(substr($parent, 0, 7))) .
|
|
|
|
')';
|
|
|
|
} else {
|
|
|
|
# merge commit
|
|
|
|
$formats_nav .=
|
|
|
|
'(merge: ' .
|
|
|
|
join(' ', map {
|
2007-03-23 20:04:31 +00:00
|
|
|
$cgi->a({-href => href(action=>"commit",
|
2006-12-15 20:57:16 +00:00
|
|
|
hash=>$_)},
|
|
|
|
esc_html(substr($_, 0, 7)));
|
|
|
|
} @$parents ) .
|
|
|
|
')';
|
|
|
|
}
|
2009-10-09 12:26:44 +00:00
|
|
|
if (gitweb_check_feature('patches') && @$parents <= 1) {
|
2008-12-18 07:13:19 +00:00
|
|
|
$formats_nav .= " | " .
|
|
|
|
$cgi->a({-href => href(action=>"patch", -replay=>1)},
|
|
|
|
"patch");
|
|
|
|
}
|
2006-12-15 20:57:16 +00:00
|
|
|
|
2005-08-07 18:28:53 +00:00
|
|
|
if (!defined $parent) {
|
gitweb: Use list for of open for running git commands, thorougly.
Use list form of open for running git commands and reading their
output through pipe, for example
open my $fd, "-|", $GIT, "rev-list", "--header", "--parents", $hash
instead of
open my $fd, "-|", "$GIT rev-list --header --parents $hash"
Single letter options use ' instead of " as quotes, according to style
used in list form of magic "-|" open.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-31 01:28:34 +00:00
|
|
|
$parent = "--root";
|
2005-08-07 18:19:56 +00:00
|
|
|
}
|
2006-12-15 16:53:45 +00:00
|
|
|
my @difftree;
|
2007-05-06 23:10:08 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id",
|
|
|
|
@diff_opts,
|
|
|
|
(@$parents <= 1 ? $parent : '-c'),
|
|
|
|
$hash, "--"
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-diff-tree failed");
|
2007-05-06 23:10:08 +00:00
|
|
|
@difftree = map { chomp; $_ } <$fd>;
|
2008-06-19 20:03:21 +00:00
|
|
|
close $fd or die_error(404, "Reading git-diff-tree failed");
|
2005-10-19 01:18:45 +00:00
|
|
|
|
|
|
|
# non-textual hash id's can be cached
|
|
|
|
my $expires;
|
|
|
|
if ($hash =~ m/^[0-9a-fA-F]{40}$/) {
|
|
|
|
$expires = "+1d";
|
|
|
|
}
|
2006-08-14 00:05:47 +00:00
|
|
|
my $refs = git_get_references();
|
|
|
|
my $ref = format_ref_marker($refs, $co{'id'});
|
2006-08-20 06:23:04 +00:00
|
|
|
|
2006-07-31 00:21:52 +00:00
|
|
|
git_header_html(undef, $expires);
|
2006-10-06 16:59:33 +00:00
|
|
|
git_print_page_nav('commit', '',
|
2006-08-22 14:52:50 +00:00
|
|
|
$hash, $co{'tree'}, $hash,
|
2006-12-15 20:57:16 +00:00
|
|
|
$formats_nav);
|
2006-07-23 20:36:32 +00:00
|
|
|
|
2005-08-07 18:21:04 +00:00
|
|
|
if (defined $co{'parent'}) {
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('commitdiff', esc_html($co{'title'}) . $ref, $hash);
|
2005-08-07 18:21:04 +00:00
|
|
|
} else {
|
2006-08-14 00:05:47 +00:00
|
|
|
git_print_header_div('tree', esc_html($co{'title'}) . $ref, $co{'tree'}, $hash);
|
2005-08-07 18:21:04 +00:00
|
|
|
}
|
2005-08-07 18:19:56 +00:00
|
|
|
print "<div class=\"title_text\">\n" .
|
2007-11-19 13:16:11 +00:00
|
|
|
"<table class=\"object_header\">\n";
|
2009-06-29 22:00:48 +00:00
|
|
|
git_print_authorship_rows(\%co);
|
2006-06-20 14:58:12 +00:00
|
|
|
print "<tr><td>commit</td><td class=\"sha1\">$co{'id'}</td></tr>\n";
|
2005-08-07 18:25:42 +00:00
|
|
|
print "<tr>" .
|
|
|
|
"<td>tree</td>" .
|
2006-06-20 14:58:12 +00:00
|
|
|
"<td class=\"sha1\">" .
|
2006-08-22 14:52:50 +00:00
|
|
|
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash),
|
|
|
|
class => "list"}, $co{'tree'}) .
|
2005-08-07 18:26:27 +00:00
|
|
|
"</td>" .
|
2006-08-22 14:52:50 +00:00
|
|
|
"<td class=\"link\">" .
|
|
|
|
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash)},
|
|
|
|
"tree");
|
gitweb: snapshot cleanups & support for offering multiple formats
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. There was taken care
for old-style gitweb configuration to work as it used to, but this
backward compatibility works only for the values which correspond to
gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e.
['x-gzip', 'gz', 'gzip']
['x-bzip2', 'bz2', 'bzip2']
['x-zip', 'zip', '']
The preferred names for gitweb.snapshot in repository configuration
have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but
the old names are still recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-21 23:30:27 +00:00
|
|
|
my $snapshot_links = format_snapshot_links($hash);
|
|
|
|
if (defined $snapshot_links) {
|
|
|
|
print " | " . $snapshot_links;
|
2006-08-17 15:29:46 +00:00
|
|
|
}
|
|
|
|
print "</td>" .
|
2005-08-07 18:25:42 +00:00
|
|
|
"</tr>\n";
|
2006-12-15 16:53:45 +00:00
|
|
|
|
2005-08-07 18:05:15 +00:00
|
|
|
foreach my $par (@$parents) {
|
2005-08-07 18:25:42 +00:00
|
|
|
print "<tr>" .
|
|
|
|
"<td>parent</td>" .
|
2006-08-22 14:52:50 +00:00
|
|
|
"<td class=\"sha1\">" .
|
|
|
|
$cgi->a({-href => href(action=>"commit", hash=>$par),
|
|
|
|
class => "list"}, $par) .
|
|
|
|
"</td>" .
|
2005-08-07 18:25:42 +00:00
|
|
|
"<td class=\"link\">" .
|
2006-08-15 22:24:30 +00:00
|
|
|
$cgi->a({-href => href(action=>"commit", hash=>$par)}, "commit") .
|
2006-08-22 14:52:50 +00:00
|
|
|
" | " .
|
2006-09-03 21:43:03 +00:00
|
|
|
$cgi->a({-href => href(action=>"commitdiff", hash=>$hash, hash_parent=>$par)}, "diff") .
|
2005-08-07 18:25:42 +00:00
|
|
|
"</td>" .
|
|
|
|
"</tr>\n";
|
2005-08-07 18:05:15 +00:00
|
|
|
}
|
2006-06-21 07:48:02 +00:00
|
|
|
print "</table>".
|
2005-08-07 18:21:04 +00:00
|
|
|
"</div>\n";
|
2006-08-17 09:21:23 +00:00
|
|
|
|
2005-08-07 18:12:11 +00:00
|
|
|
print "<div class=\"page_body\">\n";
|
2006-08-17 09:21:23 +00:00
|
|
|
git_print_log($co{'comment'});
|
2005-08-07 18:18:44 +00:00
|
|
|
print "</div>\n";
|
2006-08-14 00:18:33 +00:00
|
|
|
|
2007-05-06 23:10:08 +00:00
|
|
|
git_difftree_body(\@difftree, $hash, @$parents);
|
2006-08-14 00:18:33 +00:00
|
|
|
|
2005-08-07 18:02:47 +00:00
|
|
|
git_footer_html();
|
2005-08-07 18:21:23 +00:00
|
|
|
}
|
|
|
|
|
2006-12-10 12:25:47 +00:00
|
|
|
sub git_object {
|
|
|
|
# object is defined by:
|
|
|
|
# - hash or hash_base alone
|
|
|
|
# - hash_base and file_name
|
|
|
|
my $type;
|
|
|
|
|
|
|
|
# - hash or hash_base alone
|
|
|
|
if ($hash || ($hash_base && !defined $file_name)) {
|
|
|
|
my $object_id = $hash || $hash_base;
|
|
|
|
|
2008-06-17 21:46:35 +00:00
|
|
|
open my $fd, "-|", quote_command(
|
|
|
|
git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null'
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Object does not exist");
|
2006-12-10 12:25:47 +00:00
|
|
|
$type = <$fd>;
|
|
|
|
chomp $type;
|
|
|
|
close $fd
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Object does not exist");
|
2006-12-10 12:25:47 +00:00
|
|
|
|
|
|
|
# - hash_base and file_name
|
|
|
|
} elsif ($hash_base && defined $file_name) {
|
|
|
|
$file_name =~ s,/+$,,;
|
|
|
|
|
|
|
|
system(git_cmd(), "cat-file", '-e', $hash_base) == 0
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Base object does not exist");
|
2006-12-10 12:25:47 +00:00
|
|
|
|
|
|
|
# here errors should not hapen
|
|
|
|
open my $fd, "-|", git_cmd(), "ls-tree", $hash_base, "--", $file_name
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-ls-tree failed");
|
2006-12-10 12:25:47 +00:00
|
|
|
my $line = <$fd>;
|
|
|
|
close $fd;
|
|
|
|
|
|
|
|
#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
|
|
|
|
unless ($line && $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(404, "File or directory for given base does not exist");
|
2006-12-10 12:25:47 +00:00
|
|
|
}
|
|
|
|
$type = $2;
|
|
|
|
$hash = $3;
|
|
|
|
} else {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Not enough information to find object");
|
2006-12-10 12:25:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
print $cgi->redirect(-uri => href(action=>$type, -full=>1,
|
|
|
|
hash=>$hash, hash_base=>$hash_base,
|
|
|
|
file_name=>$file_name),
|
|
|
|
-status => '302 Found');
|
|
|
|
}
|
|
|
|
|
2005-08-07 18:21:23 +00:00
|
|
|
sub git_blobdiff {
|
2006-08-25 19:14:49 +00:00
|
|
|
my $format = shift || 'html';
|
|
|
|
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
my $fd;
|
|
|
|
my @difftree;
|
|
|
|
my %diffinfo;
|
2006-08-25 19:14:49 +00:00
|
|
|
my $expires;
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
|
|
|
|
# preparing $fd and %diffinfo for git_patchset_body
|
|
|
|
# new style URI
|
|
|
|
if (defined $hash_base && defined $hash_parent_base) {
|
|
|
|
if (defined $file_name) {
|
|
|
|
# read raw output
|
2006-10-30 21:29:06 +00:00
|
|
|
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
|
|
|
|
$hash_parent_base, $hash_base,
|
2007-03-30 21:41:26 +00:00
|
|
|
"--", (defined $file_parent ? $file_parent : ()), $file_name
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-diff-tree failed");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
@difftree = map { chomp; $_ } <$fd>;
|
|
|
|
close $fd
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Reading git-diff-tree failed");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
@difftree
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Blob diff not found");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
|
2006-08-27 21:45:26 +00:00
|
|
|
} elsif (defined $hash &&
|
|
|
|
$hash =~ /[0-9a-fA-F]{40}/) {
|
|
|
|
# try to find filename from $hash
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
|
|
|
|
# read filtered raw output
|
2006-10-30 21:29:06 +00:00
|
|
|
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
|
|
|
|
$hash_parent_base, $hash_base, "--"
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-diff-tree failed");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
@difftree =
|
|
|
|
# ':100644 100644 03b21826... 3b93d5e7... M ls-files.c'
|
|
|
|
# $hash == to_id
|
|
|
|
grep { /^:[0-7]{6} [0-7]{6} [0-9a-fA-F]{40} $hash/ }
|
|
|
|
map { chomp; $_ } <$fd>;
|
|
|
|
close $fd
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Reading git-diff-tree failed");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
@difftree
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(404, "Blob diff not found");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
|
|
|
|
} else {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Missing one of the blob diff parameters");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (@difftree > 1) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Ambiguous blob diff specification");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
%diffinfo = parse_difftree_raw_line($difftree[0]);
|
2007-11-01 11:38:08 +00:00
|
|
|
$file_parent ||= $diffinfo{'from_file'} || $file_name;
|
|
|
|
$file_name ||= $diffinfo{'to_file'};
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
|
|
|
|
$hash_parent ||= $diffinfo{'from_id'};
|
|
|
|
$hash ||= $diffinfo{'to_id'};
|
|
|
|
|
2006-08-25 19:14:49 +00:00
|
|
|
# non-textual hash id's can be cached
|
|
|
|
if ($hash_base =~ m/^[0-9a-fA-F]{40}$/ &&
|
|
|
|
$hash_parent_base =~ m/^[0-9a-fA-F]{40}$/) {
|
|
|
|
$expires = '+1d';
|
|
|
|
}
|
|
|
|
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
# open patch output
|
2006-08-28 15:49:58 +00:00
|
|
|
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
|
2007-04-05 11:45:41 +00:00
|
|
|
'-p', ($format eq 'html' ? "--full-index" : ()),
|
|
|
|
$hash_parent_base, $hash_base,
|
2007-03-30 21:41:26 +00:00
|
|
|
"--", (defined $file_parent ? $file_parent : ()), $file_name
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-diff-tree failed");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
}
|
|
|
|
|
2008-12-17 03:42:02 +00:00
|
|
|
# old/legacy style URI -- not generated anymore since 1.4.3.
|
|
|
|
if (!%diffinfo) {
|
|
|
|
die_error('404 Not Found', "Missing one of the blob diff parameters")
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# header
|
2006-08-25 19:14:49 +00:00
|
|
|
if ($format eq 'html') {
|
|
|
|
my $formats_nav =
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"blobdiff_plain", -replay=>1)},
|
2006-09-22 01:19:50 +00:00
|
|
|
"raw");
|
2006-08-25 19:14:49 +00:00
|
|
|
git_header_html(undef, $expires);
|
|
|
|
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
|
|
|
|
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";
|
2010-12-14 23:34:01 +00:00
|
|
|
print "<div class=\"title\">".esc_html("$hash vs $hash_parent")."</div>\n";
|
2006-08-25 19:14:49 +00:00
|
|
|
}
|
|
|
|
if (defined $file_name) {
|
|
|
|
git_print_page_path($file_name, "blob", $hash_base);
|
|
|
|
} else {
|
|
|
|
print "<div class=\"page_path\"></div>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
} elsif ($format eq 'plain') {
|
|
|
|
print $cgi->header(
|
|
|
|
-type => 'text/plain',
|
|
|
|
-charset => 'utf-8',
|
|
|
|
-expires => $expires,
|
2006-09-28 23:51:43 +00:00
|
|
|
-content_disposition => 'inline; filename="' . "$file_name" . '.patch"');
|
2006-08-25 19:14:49 +00:00
|
|
|
|
|
|
|
print "X-Git-Url: " . $cgi->self_url() . "\n\n";
|
|
|
|
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
} else {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Unknown blobdiff format");
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# patch
|
2006-08-25 19:14:49 +00:00
|
|
|
if ($format eq 'html') {
|
|
|
|
print "<div class=\"page_body\">\n";
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
|
2006-08-25 19:14:49 +00:00
|
|
|
git_patchset_body($fd, [ \%diffinfo ], $hash_base, $hash_parent_base);
|
|
|
|
close $fd;
|
gitweb: Use git-diff-tree or git-diff patch output for blobdiff
This is second part of removing gitweb dependency on external
diff (used in git_diff_print).
Get rid of git_diff_print invocation in git_blobdiff, and use either
git-diff-tree (when both hash_base and hash_parent_base are provided)
patch format or git-diff patch format (when only hash and hash_parent
are provided) for output.
Supported URI schemes, and output formats:
* New URI scheme: both hash_base and hash_parent_base (trees-ish
containing blobs versions we want to compare) are provided.
Also either filename is provided, or hash (of blob) is provided
(we try to find filename then).
For this scheme we have copying and renames detection, mode changes,
file types etc., and information extended diff header is correct.
* Old URI scheme: hash_parent_base is not provided, we use hash and
hash_parent to directly compare blobs using git-diff. If no filename
is given, blobs hashes are used in place of filenames.
This scheme has always "blob" as file type, it cannot detect mode
changes, and we rely on CGI parameters to provide name of the file.
Added git_to_hash subroutine, which transforms symbolic name or list
of symbolic name to hash or list of hashes using git-rev-parse.
To have "blob" instead of "unknown" (or "file" regardless of the type)
in "gitweb diff header" for legacy scheme, file_type function now
returns its argument if it is not octal string.
Added support for fake "2" status code in git_patchset_body. Such code
is generated by git_blobdiff in legacy scheme case.
ATTENTION: The order of arguments (operands) to git-diff is reversed
(sic!) to have correct diff in the legacy (no hash_parent_base) case.
$hash_parent, $hash ordering is commented out, as it gives reversed
patch (at least for git version 1.4.1.1) as compared to output in new
scheme and output of older gitweb version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-25 19:13:34 +00:00
|
|
|
|
2006-08-25 19:14:49 +00:00
|
|
|
print "</div>\n"; # class="page_body"
|
|
|
|
git_footer_html();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
while (my $line = <$fd>) {
|
2006-11-08 10:48:56 +00:00
|
|
|
$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;
|
2006-08-25 19:14:49 +00:00
|
|
|
|
|
|
|
print $line;
|
|
|
|
|
|
|
|
last if $line =~ m!^\+\+\+!;
|
|
|
|
}
|
|
|
|
local $/ = undef;
|
|
|
|
print <$fd>;
|
|
|
|
close $fd;
|
|
|
|
}
|
2005-08-07 18:21:23 +00:00
|
|
|
}
|
|
|
|
|
2005-08-07 18:26:27 +00:00
|
|
|
sub git_blobdiff_plain {
|
2006-08-25 19:14:49 +00:00
|
|
|
git_blobdiff('plain');
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
|
|
|
|
2005-08-07 18:21:23 +00:00
|
|
|
sub git_commitdiff {
|
2008-12-18 07:13:17 +00:00
|
|
|
my %params = @_;
|
|
|
|
my $format = $params{-format} || 'html';
|
2008-12-18 07:13:16 +00:00
|
|
|
|
2008-12-18 07:13:19 +00:00
|
|
|
my ($patch_max) = gitweb_get_feature('patches');
|
2008-12-18 07:13:16 +00:00
|
|
|
if ($format eq 'patch') {
|
|
|
|
die_error(403, "Patch view not allowed") unless $patch_max;
|
|
|
|
}
|
|
|
|
|
2006-11-18 22:35:41 +00:00
|
|
|
$hash ||= $hash_base || "HEAD";
|
2008-06-19 20:03:21 +00:00
|
|
|
my %co = parse_commit($hash)
|
|
|
|
or die_error(404, "Unknown commit object");
|
2006-10-22 22:37:56 +00:00
|
|
|
|
2007-06-08 11:33:28 +00:00
|
|
|
# choose format for commitdiff for merge
|
|
|
|
if (! defined $hash_parent && @{$co{'parents'}} > 1) {
|
|
|
|
$hash_parent = '--cc';
|
|
|
|
}
|
|
|
|
# we need to prepare $formats_nav before almost any parameter munging
|
2006-10-22 22:37:56 +00:00
|
|
|
my $formats_nav;
|
|
|
|
if ($format eq 'html') {
|
|
|
|
$formats_nav =
|
2007-11-01 12:06:29 +00:00
|
|
|
$cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},
|
2006-10-22 22:37:56 +00:00
|
|
|
"raw");
|
2009-10-09 12:26:44 +00:00
|
|
|
if ($patch_max && @{$co{'parents'}} <= 1) {
|
2008-12-18 07:13:19 +00:00
|
|
|
$formats_nav .= " | " .
|
|
|
|
$cgi->a({-href => href(action=>"patch", -replay=>1)},
|
|
|
|
"patch");
|
|
|
|
}
|
2006-10-22 22:37:56 +00:00
|
|
|
|
2007-06-08 11:33:28 +00:00
|
|
|
if (defined $hash_parent &&
|
|
|
|
$hash_parent ne '-c' && $hash_parent ne '--cc') {
|
2006-10-22 22:37:56 +00:00
|
|
|
# commitdiff with two commits given
|
|
|
|
my $hash_parent_short = $hash_parent;
|
|
|
|
if ($hash_parent =~ m/^[0-9a-fA-F]{40}$/) {
|
|
|
|
$hash_parent_short = substr($hash_parent, 0, 7);
|
|
|
|
}
|
|
|
|
$formats_nav .=
|
2007-06-08 11:26:31 +00:00
|
|
|
' (from';
|
|
|
|
for (my $i = 0; $i < @{$co{'parents'}}; $i++) {
|
|
|
|
if ($co{'parents'}[$i] eq $hash_parent) {
|
|
|
|
$formats_nav .= ' parent ' . ($i+1);
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$formats_nav .= ': ' .
|
2006-10-22 22:37:56 +00:00
|
|
|
$cgi->a({-href => href(action=>"commitdiff",
|
|
|
|
hash=>$hash_parent)},
|
|
|
|
esc_html($hash_parent_short)) .
|
|
|
|
')';
|
|
|
|
} elsif (!$co{'parent'}) {
|
|
|
|
# --root commitdiff
|
|
|
|
$formats_nav .= ' (initial)';
|
|
|
|
} elsif (scalar @{$co{'parents'}} == 1) {
|
|
|
|
# single parent commit
|
|
|
|
$formats_nav .=
|
|
|
|
' (parent: ' .
|
|
|
|
$cgi->a({-href => href(action=>"commitdiff",
|
|
|
|
hash=>$co{'parent'})},
|
|
|
|
esc_html(substr($co{'parent'}, 0, 7))) .
|
|
|
|
')';
|
|
|
|
} else {
|
|
|
|
# merge commit
|
2007-06-08 11:33:28 +00:00
|
|
|
if ($hash_parent eq '--cc') {
|
|
|
|
$formats_nav .= ' | ' .
|
|
|
|
$cgi->a({-href => href(action=>"commitdiff",
|
|
|
|
hash=>$hash, hash_parent=>'-c')},
|
|
|
|
'combined');
|
|
|
|
} else { # $hash_parent eq '-c'
|
|
|
|
$formats_nav .= ' | ' .
|
|
|
|
$cgi->a({-href => href(action=>"commitdiff",
|
|
|
|
hash=>$hash, hash_parent=>'--cc')},
|
|
|
|
'compact');
|
|
|
|
}
|
2006-10-22 22:37:56 +00:00
|
|
|
$formats_nav .=
|
|
|
|
' (merge: ' .
|
|
|
|
join(' ', map {
|
|
|
|
$cgi->a({-href => href(action=>"commitdiff",
|
|
|
|
hash=>$_)},
|
|
|
|
esc_html(substr($_, 0, 7)));
|
|
|
|
} @{$co{'parents'}} ) .
|
|
|
|
')';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-06 23:10:07 +00:00
|
|
|
my $hash_parent_param = $hash_parent;
|
2007-06-08 11:33:28 +00:00
|
|
|
if (!defined $hash_parent_param) {
|
|
|
|
# --cc for multiple parents, --root for parentless
|
2007-05-06 23:10:07 +00:00
|
|
|
$hash_parent_param =
|
2007-06-08 11:33:28 +00:00
|
|
|
@{$co{'parents'}} > 1 ? '--cc' : $co{'parent'} || '--root';
|
2005-08-07 18:25:42 +00:00
|
|
|
}
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
|
|
|
# read commitdiff
|
|
|
|
my $fd;
|
|
|
|
my @difftree;
|
|
|
|
if ($format eq 'html') {
|
2006-08-28 15:49:58 +00:00
|
|
|
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
|
2006-10-30 21:29:06 +00:00
|
|
|
"--no-commit-id", "--patch-with-raw", "--full-index",
|
2007-05-06 23:10:07 +00:00
|
|
|
$hash_parent_param, $hash, "--"
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-diff-tree failed");
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
2006-11-18 22:35:38 +00:00
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
# empty line ends raw part of diff-tree output
|
|
|
|
last unless $line;
|
2007-05-06 23:10:06 +00:00
|
|
|
push @difftree, scalar parse_difftree_raw_line($line);
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} elsif ($format eq 'plain') {
|
2006-08-28 15:49:58 +00:00
|
|
|
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
|
2007-05-06 23:10:07 +00:00
|
|
|
'-p', $hash_parent_param, $hash, "--"
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(500, "Open git-diff-tree failed");
|
2008-12-18 07:13:16 +00:00
|
|
|
} elsif ($format eq 'patch') {
|
|
|
|
# For commit ranges, we limit the output to the number of
|
|
|
|
# patches specified in the 'patches' feature.
|
|
|
|
# For single commits, we limit the output to a single patch,
|
|
|
|
# diverging from the git-format-patch default.
|
|
|
|
my @commit_spec = ();
|
|
|
|
if ($hash_parent) {
|
|
|
|
if ($patch_max > 0) {
|
|
|
|
push @commit_spec, "-$patch_max";
|
|
|
|
}
|
|
|
|
push @commit_spec, '-n', "$hash_parent..$hash";
|
|
|
|
} else {
|
2008-12-18 07:13:18 +00:00
|
|
|
if ($params{-single}) {
|
|
|
|
push @commit_spec, '-1';
|
|
|
|
} else {
|
|
|
|
if ($patch_max > 0) {
|
|
|
|
push @commit_spec, "-$patch_max";
|
|
|
|
}
|
|
|
|
push @commit_spec, "-n";
|
|
|
|
}
|
|
|
|
push @commit_spec, '--root', $hash;
|
2008-12-18 07:13:16 +00:00
|
|
|
}
|
2010-05-10 16:41:35 +00:00
|
|
|
open $fd, "-|", git_cmd(), "format-patch", @diff_opts,
|
|
|
|
'--encoding=utf8', '--stdout', @commit_spec
|
2008-12-18 07:13:16 +00:00
|
|
|
or die_error(500, "Open git-format-patch failed");
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
} else {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Unknown commitdiff format");
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
2005-08-07 17:49:46 +00:00
|
|
|
|
2005-10-19 01:18:45 +00:00
|
|
|
# non-textual hash id's can be cached
|
|
|
|
my $expires;
|
|
|
|
if ($hash =~ m/^[0-9a-fA-F]{40}$/) {
|
|
|
|
$expires = "+1d";
|
|
|
|
}
|
2005-08-07 18:21:23 +00:00
|
|
|
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
# write commit message
|
|
|
|
if ($format eq 'html') {
|
|
|
|
my $refs = git_get_references();
|
|
|
|
my $ref = format_ref_marker($refs, $co{'id'});
|
2005-08-07 18:28:01 +00:00
|
|
|
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
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);
|
2009-06-29 22:00:49 +00:00
|
|
|
print "<div class=\"title_text\">\n" .
|
|
|
|
"<table class=\"object_header\">\n";
|
|
|
|
git_print_authorship_rows(\%co);
|
|
|
|
print "</table>".
|
|
|
|
"</div>\n";
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
print "<div class=\"page_body\">\n";
|
2006-10-24 11:55:33 +00:00
|
|
|
if (@{$co{'comment'}} > 1) {
|
|
|
|
print "<div class=\"log\">\n";
|
|
|
|
git_print_log($co{'comment'}, -final_empty_line=> 1, -remove_title => 1);
|
|
|
|
print "</div>\n"; # class="log"
|
|
|
|
}
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
|
|
|
|
} elsif ($format eq 'plain') {
|
|
|
|
my $refs = git_get_references("tags");
|
2006-08-24 17:45:30 +00:00
|
|
|
my $tagname = git_get_rev_name_tags($hash);
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
my $filename = basename($project) . "-$hash.patch";
|
|
|
|
|
|
|
|
print $cgi->header(
|
|
|
|
-type => 'text/plain',
|
|
|
|
-charset => 'utf-8',
|
|
|
|
-expires => $expires,
|
2006-09-28 23:51:43 +00:00
|
|
|
-content_disposition => 'inline; filename="' . "$filename" . '"');
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
|
2008-01-29 12:16:02 +00:00
|
|
|
print "From: " . to_utf8($co{'author'}) . "\n";
|
|
|
|
print "Date: $ad{'rfc2822'} ($ad{'tz_local'})\n";
|
|
|
|
print "Subject: " . to_utf8($co{'title'}) . "\n";
|
|
|
|
|
2006-08-24 17:45:30 +00:00
|
|
|
print "X-Git-Tag: $tagname\n" if $tagname;
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
print "X-Git-Url: " . $cgi->self_url() . "\n\n";
|
2006-08-24 17:45:30 +00:00
|
|
|
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
foreach my $line (@{$co{'comment'}}) {
|
2008-01-29 12:16:02 +00:00
|
|
|
print to_utf8($line) . "\n";
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
|
|
|
print "---\n\n";
|
2008-12-18 07:13:16 +00:00
|
|
|
} elsif ($format eq 'patch') {
|
|
|
|
my $filename = basename($project) . "-$hash.patch";
|
|
|
|
|
|
|
|
print $cgi->header(
|
|
|
|
-type => 'text/plain',
|
|
|
|
-charset => 'utf-8',
|
|
|
|
-expires => $expires,
|
|
|
|
-content_disposition => 'inline; filename="' . "$filename" . '"');
|
2005-08-07 18:28:01 +00:00
|
|
|
}
|
|
|
|
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
# write patch
|
|
|
|
if ($format eq 'html') {
|
2007-06-08 11:33:28 +00:00
|
|
|
my $use_parents = !defined $hash_parent ||
|
|
|
|
$hash_parent eq '-c' || $hash_parent eq '--cc';
|
|
|
|
git_difftree_body(\@difftree, $hash,
|
|
|
|
$use_parents ? @{$co{'parents'}} : $hash_parent);
|
2006-08-28 12:48:14 +00:00
|
|
|
print "<br/>\n";
|
2005-08-07 18:28:01 +00:00
|
|
|
|
2007-06-08 11:33:28 +00:00
|
|
|
git_patchset_body($fd, \@difftree, $hash,
|
|
|
|
$use_parents ? @{$co{'parents'}} : $hash_parent);
|
2006-08-24 17:34:36 +00:00
|
|
|
close $fd;
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
print "</div>\n"; # class="page_body"
|
|
|
|
git_footer_html();
|
|
|
|
|
|
|
|
} elsif ($format eq 'plain') {
|
|
|
|
local $/ = undef;
|
|
|
|
print <$fd>;
|
|
|
|
close $fd
|
|
|
|
or print "Reading git-diff-tree failed\n";
|
2008-12-18 07:13:16 +00:00
|
|
|
} elsif ($format eq 'patch') {
|
|
|
|
local $/ = undef;
|
|
|
|
print <$fd>;
|
|
|
|
close $fd
|
|
|
|
or print "Reading git-format-patch failed\n";
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
sub git_commitdiff_plain {
|
2008-12-18 07:13:17 +00:00
|
|
|
git_commitdiff(-format => 'plain');
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
|
|
|
|
2008-12-18 07:13:16 +00:00
|
|
|
# format-patch-style patches
|
|
|
|
sub git_patch {
|
2009-10-09 12:26:44 +00:00
|
|
|
git_commitdiff(-format => 'patch', -single => 1);
|
2008-12-18 07:13:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sub git_patches {
|
2008-12-18 07:13:17 +00:00
|
|
|
git_commitdiff(-format => 'patch');
|
gitweb: Use git-diff-tree patch output for commitdiff
Get rid of git_diff_print invocation in git_commitdiff and therefore
external diff (/usr/bin/diff) invocation, and use only git-diff-tree
to generate patch.
git_commitdiff and git_commitdiff_plain are collapsed into one
subroutine git_commitdiff, with format (currently 'html' which is
default format corresponding to git_commitdiff, and 'plain'
corresponding to git_commitdiff_plain) specified in argument.
Separate patch (diff) pretty-printing into git_patchset_body.
It is used in git_commitdiff.
Separate patch (diff) line formatting from git_diff_print into
format_diff_line function. It is used in git_patchset_body.
While at it, add $hash parameter to git_difftree_body, according to
rule that inner functions should use parameter passing, and not global
variables.
CHANGES TO OUTPUT:
* "commitdiff" now products patches with renaming and copying
detection (git-diff-tree is invoked with -M and -C options).
Empty patches (mode changes and pure renames and copying)
are not written currently. Former version broke renaming and
copying, and didn't notice mode changes, like this version.
* "commitdiff" output is now divided into several div elements
of class "log", "patchset" and "patch".
* "commitdiff_plain" now only generates X-Git-Tag: line only if there
is tag pointing to the current commit. Former version which wrote
first tag following current commit was broken[*1*]; besides we are
interested rather in tags _preceding_ the commit, and _heads_
following the commit. X-Git-Url: now is current URL; former version
tried[*2*] to output URL to HTML version of commitdiff.
* "commitdiff_plain" is generated by git-diff-tree, and has therefore
has git specific extensions to diff format: "git diff" header and
optional extended header lines.
FOOTNOTES
[*1*] First it generated rev-list starting from HEAD even if hash_base
parameter was set, second it wasn't corrected according to changes
made in git_get_references (formerly read_info_ref) output, third even
for older version of read_info_ref output it didn't work for multiple
tags pointing to the current commit (rare).
[*2*] It wrote URL for commitdiff without hash_parent, which produces
diff to first parent and is not the same as current diff if it is diff
of merge commit to non-first parent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 22:15:14 +00:00
|
|
|
}
|
|
|
|
|
2005-08-07 18:21:23 +00:00
|
|
|
sub git_history {
|
2009-11-13 01:02:14 +00:00
|
|
|
git_log_generic('history', \&git_history_body,
|
|
|
|
$hash_base, $hash_parent_base,
|
|
|
|
$file_name, $hash);
|
2005-08-07 17:49:46 +00:00
|
|
|
}
|
2005-08-07 18:26:27 +00:00
|
|
|
|
|
|
|
sub git_search {
|
2008-11-29 21:07:29 +00:00
|
|
|
gitweb_check_feature('search') or die_error(403, "Search is disabled");
|
2005-08-07 18:26:27 +00:00
|
|
|
if (!defined $searchtext) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Text field is empty");
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
|
|
|
if (!defined $hash) {
|
2006-08-14 00:05:47 +00:00
|
|
|
$hash = git_get_head_hash($project);
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
2006-08-14 00:05:47 +00:00
|
|
|
my %co = parse_commit($hash);
|
2005-08-07 18:26:27 +00:00
|
|
|
if (!%co) {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(404, "Unknown commit object");
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
2006-12-23 14:57:12 +00:00
|
|
|
if (!defined $page) {
|
|
|
|
$page = 0;
|
|
|
|
}
|
2006-09-10 22:29:27 +00:00
|
|
|
|
2006-10-24 03:15:46 +00:00
|
|
|
$searchtype ||= 'commit';
|
|
|
|
if ($searchtype eq 'pickaxe') {
|
2006-09-10 22:29:27 +00:00
|
|
|
# pickaxe may take all resources of your box and run for several minutes
|
|
|
|
# with every query - so decide by yourself how public you make this feature
|
2008-11-29 21:07:29 +00:00
|
|
|
gitweb_check_feature('pickaxe')
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(403, "Pickaxe is disabled");
|
2005-08-07 18:27:18 +00:00
|
|
|
}
|
2007-05-17 02:31:12 +00:00
|
|
|
if ($searchtype eq 'grep') {
|
2008-11-29 21:07:29 +00:00
|
|
|
gitweb_check_feature('grep')
|
2008-06-19 20:03:21 +00:00
|
|
|
or die_error(403, "Grep is disabled");
|
2007-05-17 02:31:12 +00:00
|
|
|
}
|
2006-10-24 03:15:46 +00:00
|
|
|
|
2005-08-07 18:26:27 +00:00
|
|
|
git_header_html();
|
|
|
|
|
2006-10-24 03:15:46 +00:00
|
|
|
if ($searchtype eq 'commit' or $searchtype eq 'author' or $searchtype eq 'committer') {
|
2006-12-23 03:35:14 +00:00
|
|
|
my $greptype;
|
|
|
|
if ($searchtype eq 'commit') {
|
|
|
|
$greptype = "--grep=";
|
|
|
|
} elsif ($searchtype eq 'author') {
|
|
|
|
$greptype = "--author=";
|
|
|
|
} elsif ($searchtype eq 'committer') {
|
|
|
|
$greptype = "--committer=";
|
|
|
|
}
|
2008-02-26 12:22:07 +00:00
|
|
|
$greptype .= $searchtext;
|
|
|
|
my @commitlist = parse_commits($hash, 101, (100 * $page), undef,
|
2008-02-26 12:22:08 +00:00
|
|
|
$greptype, '--regexp-ignore-case',
|
|
|
|
$search_use_regexp ? '--extended-regexp' : '--fixed-strings');
|
2006-12-23 14:57:12 +00:00
|
|
|
|
|
|
|
my $paging_nav = '';
|
|
|
|
if ($page > 0) {
|
|
|
|
$paging_nav .=
|
|
|
|
$cgi->a({-href => href(action=>"search", hash=>$hash,
|
2008-02-26 12:22:07 +00:00
|
|
|
searchtext=>$searchtext,
|
|
|
|
searchtype=>$searchtype)},
|
2007-04-01 20:21:38 +00:00
|
|
|
"first");
|
2006-12-23 14:57:12 +00:00
|
|
|
$paging_nav .= " ⋅ " .
|
2007-11-01 12:06:28 +00:00
|
|
|
$cgi->a({-href => href(-replay=>1, page=>$page-1),
|
2007-04-01 20:21:38 +00:00
|
|
|
-accesskey => "p", -title => "Alt-p"}, "prev");
|
2006-12-23 14:57:12 +00:00
|
|
|
} else {
|
|
|
|
$paging_nav .= "first";
|
|
|
|
$paging_nav .= " ⋅ prev";
|
|
|
|
}
|
2007-11-01 12:06:28 +00:00
|
|
|
my $next_link = '';
|
2006-12-24 14:31:46 +00:00
|
|
|
if ($#commitlist >= 100) {
|
2007-11-01 12:06:28 +00:00
|
|
|
$next_link =
|
|
|
|
$cgi->a({-href => href(-replay=>1, page=>$page+1),
|
2007-04-01 20:21:38 +00:00
|
|
|
-accesskey => "n", -title => "Alt-n"}, "next");
|
2007-11-01 12:06:28 +00:00
|
|
|
$paging_nav .= " ⋅ $next_link";
|
2006-12-23 14:57:12 +00:00
|
|
|
} else {
|
|
|
|
$paging_nav .= " ⋅ next";
|
|
|
|
}
|
2007-11-01 12:06:28 +00:00
|
|
|
|
2006-12-23 14:57:12 +00:00
|
|
|
git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);
|
|
|
|
git_print_header_div('commit', esc_html($co{'title'}), $hash);
|
2010-08-07 21:56:47 +00:00
|
|
|
if ($page == 0 && !@commitlist) {
|
|
|
|
print "<p>No match.</p>\n";
|
|
|
|
} else {
|
|
|
|
git_search_grep_body(\@commitlist, 0, 99, $next_link);
|
|
|
|
}
|
2005-08-07 18:27:18 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 03:15:46 +00:00
|
|
|
if ($searchtype eq 'pickaxe') {
|
2006-12-23 14:57:12 +00:00
|
|
|
git_print_page_nav('','', $hash,$co{'tree'},$hash);
|
|
|
|
git_print_header_div('commit', esc_html($co{'title'}), $hash);
|
|
|
|
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"pickaxe search\">\n";
|
2006-12-23 14:57:12 +00:00
|
|
|
my $alternate = 1;
|
2009-05-11 01:29:40 +00:00
|
|
|
local $/ = "\n";
|
2008-03-05 08:31:55 +00:00
|
|
|
open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts,
|
|
|
|
'--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext",
|
|
|
|
($search_use_regexp ? '--pickaxe-regex' : ());
|
2005-08-07 18:27:18 +00:00
|
|
|
undef %co;
|
|
|
|
my @files;
|
|
|
|
while (my $line = <$fd>) {
|
2008-03-05 08:31:55 +00:00
|
|
|
chomp $line;
|
|
|
|
next unless $line;
|
|
|
|
|
|
|
|
my %set = parse_difftree_raw_line($line);
|
|
|
|
if (defined $set{'commit'}) {
|
|
|
|
# finish previous commit
|
2005-08-07 18:27:18 +00:00
|
|
|
if (%co) {
|
|
|
|
print "</td>\n" .
|
|
|
|
"<td class=\"link\">" .
|
2006-08-16 22:28:36 +00:00
|
|
|
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
|
2006-08-22 14:52:50 +00:00
|
|
|
" | " .
|
|
|
|
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
|
2005-08-07 18:27:18 +00:00
|
|
|
print "</td>\n" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
2008-03-05 08:31:55 +00:00
|
|
|
|
|
|
|
if ($alternate) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<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" .
|
|
|
|
"<td><i>$author</i></td>\n" .
|
|
|
|
"<td>" .
|
|
|
|
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
|
|
|
|
-class => "list subject"},
|
|
|
|
chop_and_escape_str($co{'title'}, 50) . "<br/>");
|
|
|
|
} elsif (defined $set{'to_id'}) {
|
|
|
|
next if ($set{'to_id'} =~ m/^0{40}$/);
|
|
|
|
|
|
|
|
print $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>") .
|
|
|
|
"<br/>\n";
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
|
|
|
}
|
2005-08-07 18:27:18 +00:00
|
|
|
close $fd;
|
2006-12-23 14:57:12 +00:00
|
|
|
|
2008-03-05 08:31:55 +00:00
|
|
|
# finish last commit (warning: repetition!)
|
|
|
|
if (%co) {
|
|
|
|
print "</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" .
|
|
|
|
"</tr>\n";
|
|
|
|
}
|
|
|
|
|
2006-12-23 14:57:12 +00:00
|
|
|
print "</table>\n";
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
2007-05-17 02:31:12 +00:00
|
|
|
|
|
|
|
if ($searchtype eq 'grep') {
|
|
|
|
git_print_page_nav('','', $hash,$co{'tree'},$hash);
|
|
|
|
git_print_header_div('commit', esc_html($co{'title'}), $hash);
|
|
|
|
|
2007-11-19 13:16:11 +00:00
|
|
|
print "<table class=\"grep_search\">\n";
|
2007-05-17 02:31:12 +00:00
|
|
|
my $alternate = 1;
|
|
|
|
my $matches = 0;
|
2009-05-11 01:29:40 +00:00
|
|
|
local $/ = "\n";
|
2008-02-26 12:22:08 +00:00
|
|
|
open my $fd, "-|", git_cmd(), 'grep', '-n',
|
|
|
|
$search_use_regexp ? ('-E', '-i') : '-F',
|
|
|
|
$searchtext, $co{'tree'};
|
2007-05-17 02:31:12 +00:00
|
|
|
my $lastfile = '';
|
|
|
|
while (my $line = <$fd>) {
|
|
|
|
chomp $line;
|
|
|
|
my ($file, $lno, $ltext, $binary);
|
|
|
|
last if ($matches++ > 1000);
|
|
|
|
if ($line =~ /^Binary file (.+) matches$/) {
|
|
|
|
$file = $1;
|
|
|
|
$binary = 1;
|
|
|
|
} else {
|
|
|
|
(undef, $file, $lno, $ltext) = split(/:/, $line, 4);
|
|
|
|
}
|
|
|
|
if ($file ne $lastfile) {
|
|
|
|
$lastfile and print "</td></tr>\n";
|
|
|
|
if ($alternate++) {
|
|
|
|
print "<tr class=\"dark\">\n";
|
|
|
|
} else {
|
|
|
|
print "<tr class=\"light\">\n";
|
|
|
|
}
|
|
|
|
print "<td class=\"list\">".
|
|
|
|
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
|
|
|
|
file_name=>"$file"),
|
|
|
|
-class => "list"}, esc_path($file));
|
|
|
|
print "</td><td>\n";
|
|
|
|
$lastfile = $file;
|
|
|
|
}
|
|
|
|
if ($binary) {
|
|
|
|
print "<div class=\"binary\">Binary file</div>\n";
|
|
|
|
} else {
|
|
|
|
$ltext = untabify($ltext);
|
2008-02-26 12:22:08 +00:00
|
|
|
if ($ltext =~ m/^(.*)($search_regexp)(.*)$/i) {
|
2007-05-17 02:31:12 +00:00
|
|
|
$ltext = esc_html($1, -nbsp=>1);
|
|
|
|
$ltext .= '<span class="match">';
|
|
|
|
$ltext .= esc_html($2, -nbsp=>1);
|
|
|
|
$ltext .= '</span>';
|
|
|
|
$ltext .= esc_html($3, -nbsp=>1);
|
|
|
|
} else {
|
|
|
|
$ltext = esc_html($ltext, -nbsp=>1);
|
|
|
|
}
|
|
|
|
print "<div class=\"pre\">" .
|
|
|
|
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
|
|
|
|
file_name=>"$file").'#l'.$lno,
|
|
|
|
-class => "linenr"}, sprintf('%4i', $lno))
|
|
|
|
. ' ' . $ltext . "</div>\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($lastfile) {
|
|
|
|
print "</td></tr>\n";
|
|
|
|
if ($matches > 1000) {
|
|
|
|
print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
print "<div class=\"diff nodifferences\">No matches found</div>\n";
|
|
|
|
}
|
|
|
|
close $fd;
|
|
|
|
|
|
|
|
print "</table>\n";
|
|
|
|
}
|
2005-08-07 18:26:27 +00:00
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
2006-10-24 03:15:46 +00:00
|
|
|
sub git_search_help {
|
|
|
|
git_header_html();
|
|
|
|
git_print_page_nav('','', $hash,$hash,$hash);
|
|
|
|
print <<EOT;
|
2008-02-26 12:22:08 +00:00
|
|
|
<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
|
|
|
|
<a href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a> (also case
|
|
|
|
insensitive).</p>
|
2006-10-24 03:15:46 +00:00
|
|
|
<dl>
|
|
|
|
<dt><b>commit</b></dt>
|
2008-02-26 12:22:08 +00:00
|
|
|
<dd>The commit messages and authorship information will be scanned for the given pattern.</dd>
|
2007-05-17 02:31:12 +00:00
|
|
|
EOT
|
2008-11-29 21:07:29 +00:00
|
|
|
my $have_grep = gitweb_check_feature('grep');
|
2007-05-17 02:31:12 +00:00
|
|
|
if ($have_grep) {
|
|
|
|
print <<EOT;
|
|
|
|
<dt><b>grep</b></dt>
|
|
|
|
<dd>All files in the currently selected tree (HEAD unless you are explicitly browsing
|
2008-02-26 12:22:08 +00:00
|
|
|
a different one) are searched for the given pattern. On large trees, this search can take
|
|
|
|
a while and put some strain on the server, so please use it with some consideration. Note that
|
|
|
|
due to git-grep peculiarity, currently if regexp mode is turned off, the matches are
|
|
|
|
case-sensitive.</dd>
|
2007-05-17 02:31:12 +00:00
|
|
|
EOT
|
|
|
|
}
|
|
|
|
print <<EOT;
|
2006-10-24 03:15:46 +00:00
|
|
|
<dt><b>author</b></dt>
|
2008-02-26 12:22:08 +00:00
|
|
|
<dd>Name and e-mail of the change author and date of birth of the patch will be scanned for the given pattern.</dd>
|
2006-10-24 03:15:46 +00:00
|
|
|
<dt><b>committer</b></dt>
|
2008-02-26 12:22:08 +00:00
|
|
|
<dd>Name and e-mail of the committer and date of commit will be scanned for the given pattern.</dd>
|
2006-10-24 03:15:46 +00:00
|
|
|
EOT
|
2008-11-29 21:07:29 +00:00
|
|
|
my $have_pickaxe = gitweb_check_feature('pickaxe');
|
2006-10-24 03:15:46 +00:00
|
|
|
if ($have_pickaxe) {
|
|
|
|
print <<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
|
2008-02-26 12:22:08 +00:00
|
|
|
takes a lot of strain on the server, so please use it wisely. Note that since you may be
|
|
|
|
interested even in changes just changing the case as well, this search is case sensitive.</dd>
|
2006-10-24 03:15:46 +00:00
|
|
|
EOT
|
|
|
|
}
|
|
|
|
print "</dl>\n";
|
|
|
|
git_footer_html();
|
|
|
|
}
|
|
|
|
|
2005-08-07 18:26:27 +00:00
|
|
|
sub git_shortlog {
|
2009-11-13 01:02:14 +00:00
|
|
|
git_log_generic('shortlog', \&git_shortlog_body,
|
|
|
|
$hash, $hash_parent);
|
2005-08-07 18:26:27 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
|
|
|
|
## ......................................................................
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
## feeds (RSS, Atom; OPML)
|
2006-07-31 19:22:15 +00:00
|
|
|
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
sub git_feed {
|
|
|
|
my $format = shift || 'atom';
|
2008-11-29 21:07:29 +00:00
|
|
|
my $have_blame = gitweb_check_feature('blame');
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
|
|
|
|
# Atom: http://www.atomenabled.org/developers/syndication/
|
|
|
|
# RSS: http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ
|
|
|
|
if ($format ne 'rss' && $format ne 'atom') {
|
2008-06-19 20:03:21 +00:00
|
|
|
die_error(400, "Unknown web feed format");
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# log/feed of current (HEAD) branch, log of given branch, history of file/directory
|
|
|
|
my $head = $hash || 'HEAD';
|
2008-02-26 12:22:06 +00:00
|
|
|
my @commitlist = parse_commits($head, 150, 0, $file_name);
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
|
|
|
|
my %latest_commit;
|
|
|
|
my %latest_date;
|
|
|
|
my $content_type = "application/$format+xml";
|
|
|
|
if (defined $cgi->http('HTTP_ACCEPT') &&
|
|
|
|
$cgi->Accept('text/xml') > $cgi->Accept($content_type)) {
|
|
|
|
# browser (feed reader) prefers text/xml
|
|
|
|
$content_type = 'text/xml';
|
|
|
|
}
|
2006-12-24 14:31:47 +00:00
|
|
|
if (defined($commitlist[0])) {
|
|
|
|
%latest_commit = %{$commitlist[0]};
|
2009-01-26 11:50:16 +00:00
|
|
|
my $latest_epoch = $latest_commit{'committer_epoch'};
|
2011-03-19 22:53:55 +00:00
|
|
|
%latest_date = parse_date($latest_epoch, $latest_commit{'comitter_tz'});
|
2009-01-26 11:50:16 +00:00
|
|
|
my $if_modified = $cgi->http('IF_MODIFIED_SINCE');
|
|
|
|
if (defined $if_modified) {
|
|
|
|
my $since;
|
|
|
|
if (eval { require HTTP::Date; 1; }) {
|
|
|
|
$since = HTTP::Date::str2time($if_modified);
|
|
|
|
} elsif (eval { require Time::ParseDate; 1; }) {
|
|
|
|
$since = Time::ParseDate::parsedate($if_modified, GMT => 1);
|
|
|
|
}
|
|
|
|
if (defined $since && $latest_epoch <= $since) {
|
|
|
|
print $cgi->header(
|
|
|
|
-type => $content_type,
|
|
|
|
-charset => 'utf-8',
|
|
|
|
-last_modified => $latest_date{'rfc2822'},
|
|
|
|
-status => '304 Not Modified');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
print $cgi->header(
|
|
|
|
-type => $content_type,
|
|
|
|
-charset => 'utf-8',
|
|
|
|
-last_modified => $latest_date{'rfc2822'});
|
|
|
|
} else {
|
|
|
|
print $cgi->header(
|
|
|
|
-type => $content_type,
|
|
|
|
-charset => 'utf-8');
|
|
|
|
}
|
|
|
|
|
|
|
|
# Optimization: skip generating the body if client asks only
|
|
|
|
# for Last-Modified date.
|
|
|
|
return if ($cgi->request_method() eq 'HEAD');
|
|
|
|
|
|
|
|
# header variables
|
|
|
|
my $title = "$site_name - $project/$action";
|
|
|
|
my $feed_type = 'log';
|
|
|
|
if (defined $hash) {
|
|
|
|
$title .= " - '$hash'";
|
|
|
|
$feed_type = 'branch log';
|
|
|
|
if (defined $file_name) {
|
|
|
|
$title .= " :: $file_name";
|
|
|
|
$feed_type = 'history';
|
|
|
|
}
|
|
|
|
} elsif (defined $file_name) {
|
|
|
|
$title .= " - $file_name";
|
|
|
|
$feed_type = 'history';
|
|
|
|
}
|
|
|
|
$title .= " $feed_type";
|
|
|
|
my $descr = git_get_project_description($project);
|
|
|
|
if (defined $descr) {
|
|
|
|
$descr = esc_html($descr);
|
|
|
|
} else {
|
|
|
|
$descr = "$project " .
|
|
|
|
($format eq 'rss' ? 'RSS' : 'Atom') .
|
|
|
|
" feed";
|
|
|
|
}
|
|
|
|
my $owner = git_get_project_owner($project);
|
|
|
|
$owner = esc_html($owner);
|
|
|
|
|
|
|
|
#header
|
|
|
|
my $alt_url;
|
|
|
|
if (defined $file_name) {
|
|
|
|
$alt_url = href(-full=>1, action=>"history", hash=>$hash, file_name=>$file_name);
|
|
|
|
} elsif (defined $hash) {
|
|
|
|
$alt_url = href(-full=>1, action=>"log", hash=>$hash);
|
|
|
|
} else {
|
|
|
|
$alt_url = href(-full=>1, action=>"summary");
|
|
|
|
}
|
|
|
|
print qq!<?xml version="1.0" encoding="utf-8"?>\n!;
|
|
|
|
if ($format eq 'rss') {
|
|
|
|
print <<XML;
|
2006-08-22 21:42:53 +00:00
|
|
|
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
|
|
|
|
<channel>
|
|
|
|
XML
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
print "<title>$title</title>\n" .
|
|
|
|
"<link>$alt_url</link>\n" .
|
|
|
|
"<description>$descr</description>\n" .
|
2009-01-26 11:50:13 +00:00
|
|
|
"<language>en</language>\n" .
|
|
|
|
# project owner is responsible for 'editorial' content
|
|
|
|
"<managingEditor>$owner</managingEditor>\n";
|
2009-01-26 11:50:11 +00:00
|
|
|
if (defined $logo || defined $favicon) {
|
|
|
|
# prefer the logo to the favicon, since RSS
|
|
|
|
# doesn't allow both
|
|
|
|
my $img = esc_url($logo || $favicon);
|
|
|
|
print "<image>\n" .
|
|
|
|
"<url>$img</url>\n" .
|
|
|
|
"<title>$title</title>\n" .
|
|
|
|
"<link>$alt_url</link>\n" .
|
|
|
|
"</image>\n";
|
|
|
|
}
|
2009-01-26 11:50:14 +00:00
|
|
|
if (%latest_date) {
|
|
|
|
print "<pubDate>$latest_date{'rfc2822'}</pubDate>\n";
|
|
|
|
print "<lastBuildDate>$latest_date{'rfc2822'}</lastBuildDate>\n";
|
|
|
|
}
|
2009-01-26 11:50:12 +00:00
|
|
|
print "<generator>gitweb v.$version/$git_version</generator>\n";
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
} elsif ($format eq 'atom') {
|
|
|
|
print <<XML;
|
|
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
|
|
XML
|
|
|
|
print "<title>$title</title>\n" .
|
|
|
|
"<subtitle>$descr</subtitle>\n" .
|
|
|
|
'<link rel="alternate" type="text/html" href="' .
|
|
|
|
$alt_url . '" />' . "\n" .
|
|
|
|
'<link rel="self" type="' . $content_type . '" href="' .
|
|
|
|
$cgi->self_url() . '" />' . "\n" .
|
|
|
|
"<id>" . href(-full=>1) . "</id>\n" .
|
|
|
|
# use project owner for feed author
|
|
|
|
"<author><name>$owner</name></author>\n";
|
|
|
|
if (defined $favicon) {
|
|
|
|
print "<icon>" . esc_url($favicon) . "</icon>\n";
|
|
|
|
}
|
2010-09-04 00:44:39 +00:00
|
|
|
if (defined $logo) {
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
# not twice as wide as tall: 72 x 27 pixels
|
2006-12-04 13:09:43 +00:00
|
|
|
print "<logo>" . esc_url($logo) . "</logo>\n";
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
}
|
|
|
|
if (! %latest_date) {
|
|
|
|
# dummy date to keep the feed valid until commits trickle in:
|
|
|
|
print "<updated>1970-01-01T00:00:00Z</updated>\n";
|
|
|
|
} else {
|
|
|
|
print "<updated>$latest_date{'iso-8601'}</updated>\n";
|
|
|
|
}
|
2009-01-26 11:50:12 +00:00
|
|
|
print "<generator version='$version/$git_version'>gitweb</generator>\n";
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
# contents
|
2006-12-24 14:31:47 +00:00
|
|
|
for (my $i = 0; $i <= $#commitlist; $i++) {
|
|
|
|
my %co = %{$commitlist[$i]};
|
|
|
|
my $commit = $co{'id'};
|
2006-07-31 19:22:15 +00:00
|
|
|
# we read 150, we always show 30 and the ones more recent than 48 hours
|
2006-11-25 14:54:34 +00:00
|
|
|
if (($i >= 20) && ((time - $co{'author_epoch'}) > 48*60*60)) {
|
2006-07-31 19:22:15 +00:00
|
|
|
last;
|
|
|
|
}
|
2011-03-19 22:53:55 +00:00
|
|
|
my %cd = parse_date($co{'author_epoch'}, $co{'author_tz'});
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
|
|
|
|
# get list of changed files
|
2006-12-24 14:31:47 +00:00
|
|
|
open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
|
2007-05-19 00:47:51 +00:00
|
|
|
$co{'parent'} || "--root",
|
|
|
|
$co{'id'}, "--", (defined $file_name ? $file_name : ())
|
2006-08-27 21:49:36 +00:00
|
|
|
or next;
|
2006-07-31 19:22:15 +00:00
|
|
|
my @difftree = map { chomp; $_ } <$fd>;
|
2006-08-27 21:49:36 +00:00
|
|
|
close $fd
|
|
|
|
or next;
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
|
|
|
|
# print element (entry, item)
|
2008-02-03 11:38:46 +00:00
|
|
|
my $co_url = href(-full=>1, action=>"commitdiff", hash=>$commit);
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
if ($format eq 'rss') {
|
|
|
|
print "<item>\n" .
|
|
|
|
"<title>" . esc_html($co{'title'}) . "</title>\n" .
|
|
|
|
"<author>" . esc_html($co{'author'}) . "</author>\n" .
|
|
|
|
"<pubDate>$cd{'rfc2822'}</pubDate>\n" .
|
|
|
|
"<guid isPermaLink=\"true\">$co_url</guid>\n" .
|
|
|
|
"<link>$co_url</link>\n" .
|
|
|
|
"<description>" . esc_html($co{'title'}) . "</description>\n" .
|
|
|
|
"<content:encoded>" .
|
|
|
|
"<![CDATA[\n";
|
|
|
|
} elsif ($format eq 'atom') {
|
|
|
|
print "<entry>\n" .
|
|
|
|
"<title type=\"html\">" . esc_html($co{'title'}) . "</title>\n" .
|
|
|
|
"<updated>$cd{'iso-8601'}</updated>\n" .
|
2006-11-25 14:54:33 +00:00
|
|
|
"<author>\n" .
|
|
|
|
" <name>" . esc_html($co{'author_name'}) . "</name>\n";
|
|
|
|
if ($co{'author_email'}) {
|
|
|
|
print " <email>" . esc_html($co{'author_email'}) . "</email>\n";
|
|
|
|
}
|
|
|
|
print "</author>\n" .
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
# use committer for contributor
|
2006-11-25 14:54:33 +00:00
|
|
|
"<contributor>\n" .
|
|
|
|
" <name>" . esc_html($co{'committer_name'}) . "</name>\n";
|
|
|
|
if ($co{'committer_email'}) {
|
|
|
|
print " <email>" . esc_html($co{'committer_email'}) . "</email>\n";
|
|
|
|
}
|
|
|
|
print "</contributor>\n" .
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
"<published>$cd{'iso-8601'}</published>\n" .
|
|
|
|
"<link rel=\"alternate\" type=\"text/html\" href=\"$co_url\" />\n" .
|
|
|
|
"<id>$co_url</id>\n" .
|
|
|
|
"<content type=\"xhtml\" xml:base=\"" . esc_url($my_url) . "\">\n" .
|
|
|
|
"<div xmlns=\"http://www.w3.org/1999/xhtml\">\n";
|
|
|
|
}
|
2006-07-31 19:22:15 +00:00
|
|
|
my $comment = $co{'comment'};
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
print "<pre>\n";
|
2006-07-31 19:22:15 +00:00
|
|
|
foreach my $line (@$comment) {
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
$line = esc_html($line);
|
|
|
|
print "$line\n";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
print "</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>" .
|
|
|
|
"[" .
|
|
|
|
$cgi->a({-href => href(-full=>1, action=>"blobdiff",
|
|
|
|
hash=>$difftree{'to_id'}, hash_parent=>$difftree{'from_id'},
|
|
|
|
hash_base=>$co{'id'}, hash_parent_base=>$co{'parent'},
|
|
|
|
file_name=>$file, file_parent=>$difftree{'from_file'}),
|
|
|
|
-title => "diff"}, 'D');
|
|
|
|
if ($have_blame) {
|
|
|
|
print $cgi->a({-href => href(-full=>1, action=>"blame",
|
|
|
|
file_name=>$file, hash_base=>$commit),
|
|
|
|
-title => "blame"}, 'B');
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
# 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",
|
|
|
|
file_name=>$file, hash=>$commit),
|
|
|
|
-title => "history"}, 'H');
|
|
|
|
}
|
|
|
|
$file = esc_path($file);
|
|
|
|
print "] ".
|
|
|
|
"$file</li>\n";
|
|
|
|
}
|
|
|
|
if ($format eq 'rss') {
|
|
|
|
print "</ul>]]>\n" .
|
|
|
|
"</content:encoded>\n" .
|
|
|
|
"</item>\n";
|
|
|
|
} elsif ($format eq 'atom') {
|
|
|
|
print "</ul>\n</div>\n" .
|
|
|
|
"</content>\n" .
|
|
|
|
"</entry>\n";
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
}
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
|
|
|
|
# end of feed
|
|
|
|
if ($format eq 'rss') {
|
|
|
|
print "</channel>\n</rss>\n";
|
2009-05-11 17:37:28 +00:00
|
|
|
} elsif ($format eq 'atom') {
|
gitweb: Refactor feed generation, make output prettier, add Atom feed
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-19 14:05:22 +00:00
|
|
|
print "</feed>\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_rss {
|
|
|
|
git_feed('rss');
|
|
|
|
}
|
|
|
|
|
|
|
|
sub git_atom {
|
|
|
|
git_feed('atom');
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sub git_opml {
|
2006-08-14 00:05:47 +00:00
|
|
|
my @list = git_get_projects_list();
|
2006-07-31 19:22:15 +00:00
|
|
|
|
2009-01-02 12:49:30 +00:00
|
|
|
print $cgi->header(
|
|
|
|
-type => 'text/xml',
|
|
|
|
-charset => 'utf-8',
|
|
|
|
-content_disposition => 'inline; filename="opml.xml"');
|
|
|
|
|
2006-08-22 21:42:53 +00:00
|
|
|
print <<XML;
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
<opml version="1.0">
|
|
|
|
<head>
|
2006-10-24 03:18:39 +00:00
|
|
|
<title>$site_name OPML Export</title>
|
2006-08-22 21:42:53 +00:00
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<outline text="git RSS feeds">
|
|
|
|
XML
|
2006-07-31 19:22:15 +00:00
|
|
|
|
|
|
|
foreach my $pr (@list) {
|
|
|
|
my %proj = %$pr;
|
2006-08-14 00:05:47 +00:00
|
|
|
my $head = git_get_head_hash($proj{'path'});
|
2006-07-31 19:22:15 +00:00
|
|
|
if (!defined $head) {
|
|
|
|
next;
|
|
|
|
}
|
2006-08-28 15:49:58 +00:00
|
|
|
$git_dir = "$projectroot/$proj{'path'}";
|
2006-08-14 00:05:47 +00:00
|
|
|
my %co = parse_commit($head);
|
2006-07-31 19:22:15 +00:00
|
|
|
if (!%co) {
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $path = esc_html(chop_str($proj{'path'}, 25, 5));
|
2009-01-02 12:15:28 +00:00
|
|
|
my $rss = href('project' => $proj{'path'}, 'action' => 'rss', -full => 1);
|
|
|
|
my $html = href('project' => $proj{'path'}, 'action' => 'summary', -full => 1);
|
2006-07-31 19:22:15 +00:00
|
|
|
print "<outline type=\"rss\" text=\"$path\" title=\"$path\" xmlUrl=\"$rss\" htmlUrl=\"$html\"/>\n";
|
|
|
|
}
|
2006-08-22 21:42:53 +00:00
|
|
|
print <<XML;
|
|
|
|
</outline>
|
|
|
|
</body>
|
|
|
|
</opml>
|
|
|
|
XML
|
2006-07-31 19:22:15 +00:00
|
|
|
}
|