# filename of html text to include at bottom of each page
our $site_footer = "++GITWEB_SITE_FOOTER++";
+# Whether to show table header row on index page
+our $index_header = 1;
+
# URI of stylesheets
our @stylesheets = ("++GITWEB_CSS++");
# URI of a single stylesheet, which can be overridden in GITWEB_CONFIG.
# valid values are none, project, descr, owner, and age
our $default_projects_order = "project";
+# show table header row for projects list on index page
+our $projects_table_headers = 1;
+
# show repository only if this file exists
# (only effective if this variable evaluates to true)
our $export_ok = "++GITWEB_EXPORT_OK++";
# don't generate information about owners of repositories
our $omit_owner=0;
+# Hide links to each repo's pages in the index
+our $omit_shortcuts = 0;
+
+# Hide .git extension in index table
+our $omit_git_extension = 0;
+
# 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"; }
# could be even 'utf-8' for the old behavior)
our $fallback_encoding = 'latin1';
+# number of characters to truncate commit hashes to
+# Added by Andrew Lorimer, October 2019
+our $hash_char = 7;
+
+# whether to show OPML feed link on homepage
+# Added by Andrew Lorimer, October 2019
+our $opml = 1;
+
+# whether to show TXT link on homepage
+# Added by Andrew Lorimer, October 2019
+our $txt = 1;
+
# 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).
(map { $_ => 'pl' } qw(pl perl pm)), # perhaps also 'cgi'
(map { $_ => 'make'} qw(make mak mk)),
(map { $_ => 'xml' } qw(xml xhtml html htm)),
+ (map { $_ => 'markdown' } qw(md markdown))
);
# You define site-wide feature defaults here; override them with
'override' => 0,
'default' => [0]},
+ # Regex filter for paths (files and directories) to display in the
+ # tree view. Currently this only affects the files listed in the tree,
+ # and files that do not match this regex can still be accessed through
+ # the full URL. This value can be overriden for individual projects.
+ # Note that double-escaping is necessary for backslashes (i.e. to match
+ # a literal full stop, use `\\.`).
+ 'tree_filter' => {
+ 'sub' => \&feature_tree_filter,
+ 'override' => 0,
+ 'default' => [".*"]},
+
# Enable the 'snapshot' link, providing a compressed archive of any
# tree. This can potentially generate high traffic if you have large
# project.
}
}
+sub feature_tree_filter {
+ my @pattern_global = shift;
+ my @pattern_project = git_get_project_config('tree_filter');
+ return (scalar(@pattern_project) > 0 ? $pattern_project[0] : $pattern_global[0]);
+}
+
sub feature_snapshot {
my (@fmts) = @_;
"blobdiff_plain" => \&git_blobdiff_plain,
"blob" => \&git_blob,
"blob_plain" => \&git_blob_plain,
- "commitdiff" => \&git_commitdiff,
- "commitdiff_plain" => \&git_commitdiff_plain,
+ "diff" => \&git_diff,
+ "diff_plain" => \&git_diff_plain,
"commit" => \&git_commit,
"forks" => \&git_forks,
"heads" => \&git_heads,
# 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);
+#set_message(\&handle_errors_html);
# dispatch
sub dispatch {
$class .= " indirect" if $indirect;
my $dest_action = "shortlog";
+ my $dest = "";
+ $dest .= "refs/" unless $ref =~ m!^refs/!;
+ $dest .= $ref;
if ($indirect) {
$dest_action = "tag" unless $action eq "tag";
+ $markers .= $cgi->a({
+ -href => href(
+ action=>$dest_action,
+ hash=>$dest
+ )}, '<span class="' . esc_attr($class)
+ . '" title="' . esc_attr($ref) . '"><svg width="14" height="14" '
+ . 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
+ . '<use xlink:href="#tagicon" /></svg>' . esc_html($name) . '</span>');
} elsif ($action =~ /^(history|(short)?log)$/) {
$dest_action = $action;
+ $markers .= $cgi->a({
+ -href => href(
+ action=>$dest_action,
+ hash=>$dest
+ )}, '<span class="' . esc_attr($class)
+ . '" title="' . esc_attr($ref) . '"><svg width="14" height="14" '
+ . 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
+ . '<use xlink:href="#reficon" /></svg>' . esc_html($name) . '</span>');
}
- my $dest = "";
- $dest .= "refs/" unless $ref =~ m!^refs/!;
- $dest .= $ref;
- my $link = $cgi->a({
- -href => href(
- action=>$dest_action,
- hash=>$dest
- )}, esc_html($name));
- $markers .= " <span class=\"".esc_attr($class)."\" title=\"".esc_attr($ref)."\">" .
- $link . "</span>";
}
}
foreach my $title (@commit_lines) {
$title =~ s/^ //;
if ($title ne "") {
- $co{'title'} = chop_str($title, 80, 5);
+ #$co{'title'} = chop_str($title, 80, 5);
+ $co{'title'} = $title;
# remove leading stuff of merges to make the interesting part visible
if (length($title) > 50) {
$title =~ s/^Automatic //;
$title =~ s/\/pub\/scm//;
}
}
- $co{'title_short'} = chop_str($title, 50, 5);
+ #$co{'title_short'} = chop_str($title, 50, 5);
+ $co{'title_short'} = $title;
last;
}
}
sub print_nav_breadcrumbs {
my %opts = @_;
+ # Modified by Andrew Lorimer, October 2019
+ # Do not show trailing slash in breadcrumb for last item
+ #my @crumbs = (@extra_breadcrumbs, [ $home_link_str => $home_link ]);
+ #for my $i (0 .. (length @crumbs - 1)) {
+ # print $cgi->a({-href => esc_url($crumbs[$i]->[1])}, $crumbs[$i]->[0]);
+ # if ($i != $#crumbs) {
+ # print " / ";
+ # }
+ #}
+ my @base_links = ();
for my $crumb (@extra_breadcrumbs, [ $home_link_str => $home_link ]) {
- print $cgi->a({-href => esc_url($crumb->[1])}, $crumb->[0]) . " / ";
+ if (defined $crumb && length $crumb && $crumb ne "") {
+ push(@base_links, $cgi->a({-href => esc_url($crumb->[1])}, $crumb->[0]));
+ }
}
+ print join(" / ", @base_links);
if (defined $project) {
+ print " / ";
my @dirname = split '/', $project;
my $projectbasename = pop @dirname;
print_nav_breadcrumbs_path(@dirname);
if ($use_pathinfo) {
$action .= "/".esc_url($project);
}
+ print "<div class=\"search\">";
print $cgi->start_form(-method => "get", -action => $action) .
- "<div class=\"search\">\n" .
(!$use_pathinfo &&
$cgi->input({-name=>"p", -value=>$project, -type=>"hidden"}) . "\n") .
$cgi->input({-name=>"a", -value=>"search", -type=>"hidden"}) . "\n" .
$cgi->popup_menu(-name => 'st', -default => 'commit',
-values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) .
" " . $cgi->a({-href => href(action=>"search_help"),
- -title => "search help" }, "?") . " search:\n",
- $cgi->textfield(-name => "s", -value => $searchtext, -override => 1) . "\n" .
+ -title => "search help" }, "?"),
+ $cgi->textfield(-name => "s", -value => $searchtext, -override => 1, -placeholder => "search " . $project) . "\n" .
"<span title=\"Extended regular expression\">" .
$cgi->checkbox(-name => 'sr', -value => 1, -label => 're',
-checked => $search_use_regexp) .
"</span>" .
- "</div>" .
$cgi->end_form() . "\n";
+ print "</div>";
}
sub git_header_html {
<?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">
-<!-- git web interface version $version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
+<!-- gitweb $version, originally (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
+<!-- modified by Andrew Lorimer, 2019 (see <https://git.lorimer.id.au>) -->
<!-- git core binaries version $git_version -->
<head>
<meta http-equiv="content-type" content="$content_type; charset=utf-8"/>
<meta name="generator" content="gitweb/$version git/$git_version$mod_perl_version"/>
<meta name="robots" content="index, nofollow"/>
+<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>$title</title>
EOF
# the stylesheet, favicon etc urls won't work correctly with path_info
}
print "</head>\n" .
- "<body>\n";
+ '<body>
+ <svg>
+ <symbol width="14" height="14" viewBox="0 0 384 512" id="reficon" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="code-branch" class="svg-inline--fa fa-code-branch fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg">
+ <path fill="currentColor" d="M384 144c0-44.2-35.8-80-80-80s-80 35.8-80 80c0 36.4 24.3 67.1 57.5 76.8-.6 16.1-4.2 28.5-11 36.9-15.4 19.2-49.3 22.4-85.2 25.7-28.2 2.6-57.4 5.4-81.3 16.9v-144c32.5-10.2 56-40.5 56-76.3 0-44.2-35.8-80-80-80S0 35.8 0 80c0 35.8 23.5 66.1 56 76.3v199.3C23.5 365.9 0 396.2 0 432c0 44.2 35.8 80 80 80s80-35.8 80-80c0-34-21.2-63.1-51.2-74.6 3.1-5.2 7.8-9.8 14.9-13.4 16.2-8.2 40.4-10.4 66.1-12.8 42.2-3.9 90-8.4 118.2-43.4 14-17.4 21.1-39.8 21.6-67.9 31.6-10.8 54.4-40.7 54.4-75.9zM80 64c8.8 0 16 7.2 16 16s-7.2 16-16 16-16-7.2-16-16 7.2-16 16-16zm0 384c-8.8 0-16-7.2-16-16s7.2-16 16-16 16 7.2 16 16-7.2 16-16 16zm224-320c8.8 0 16 7.2 16 16s-7.2 16-16 16-16-7.2-16-16 7.2-16 16-16z"></path>
+ </symbol>
+ <symbol width="14" height="14" viewBox="0 0 448 512" id="copyicon" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="copy" class="svg-inline--fa fa-copy fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg">
+ <path d="M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"></path>
+ </symbol>
+ <symbol width="14" height="14" viewBox="0 0 512 512" id="foldericon" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="folder" class="svg-inline--fa fa-folder fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg">
+ <path d="M464 128H272l-64-64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V176c0-26.51-21.49-48-48-48z"></path>
+ </symbol>
+ <symbol width="14" height="14" viewBox="0 0 512 512" id="tagicon" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="tag" class="svg-inline--fa fa-tag fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg">
+ <path d="M0 252.118V48C0 21.49 21.49 0 48 0h204.118a48 48 0 0 1 33.941 14.059l211.882 211.882c18.745 18.745 18.745 49.137 0 67.882L293.823 497.941c-18.745 18.745-49.137 18.745-67.882 0L14.059 286.059A48 48 0 0 1 0 252.118zM112 64c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"></path>
+ </symbol>
+ <symbol width="14" height="14" viewBox="0 0 320 512" id="parenticon" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="level-up-alt" class="svg-inline--fa fa-level-up-alt fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg">
+ <path d="M313.553 119.669L209.587 7.666c-9.485-10.214-25.676-10.229-35.174 0L70.438 119.669C56.232 134.969 67.062 160 88.025 160H152v272H68.024a11.996 11.996 0 0 0-8.485 3.515l-56 56C-4.021 499.074 1.333 512 12.024 512H208c13.255 0 24-10.745 24-24V160h63.966c20.878 0 31.851-24.969 17.587-40.331z"></path>
+ </symbol>
+ </svg>
+ ';
if (defined $site_header && -f $site_header) {
insert_file($site_header);
}
- print "<div class=\"page_header\">\n";
- if (defined $logo) {
+ print "<div class=\"breadcrumb\">\n";
+
+ # Modified by Andrew Lorimer, October 2019
+ # Do not print logo if the image source is empty
+ if (defined $logo && $logo ne "") {
print $cgi->a({-href => esc_url($logo_url),
-title => $logo_label},
$cgi->img({-src => esc_url($logo),
}
print_nav_breadcrumbs(%opts);
print "</div>\n";
-
- my $have_search = gitweb_check_feature('search');
- if (defined $project && $have_search) {
- print_search_form();
- }
}
sub git_footer_html {
my $feed_class = 'rss_logo';
- print "<div class=\"page_footer\">\n";
+ print "<footer>\n";
if (defined $project) {
- my $descr = git_get_project_description($project);
- if (defined $descr) {
- print "<div class=\"page_footer_text\">" . esc_html($descr) . "</div>\n";
- }
-
my %href_params = get_feed_info();
if (!%href_params) {
$feed_class .= ' generic';
}
} else {
+ if ($opml) {
print $cgi->a({-href => href(project=>undef, action=>"opml",
project_filter => $project_filter),
-class => $feed_class}, "OPML") . " ";
+ }
+ if ($txt) {
print $cgi->a({-href => href(project=>undef, action=>"project_index",
project_filter => $project_filter),
-class => $feed_class}, "TXT") . "\n";
+ }
}
- print "</div>\n"; # class="page_footer"
-
if (defined $t0 && gitweb_check_feature('timed')) {
print "<div id=\"generating_info\">\n";
print 'This page took '.
'<span id="generating_time" class="time_span">'.
tv_interval($t0, [ gettimeofday() ]).
- ' seconds </span>'.
+ ' s</span>'.
' and '.
'<span id="generating_cmd">'.
$number_of_git_cmds.
- '</span> git commands '.
+ ' git commands </span>'.
" to generate.\n";
print "</div>\n"; # class="page_footer"
}
if (defined $site_footer && -f $site_footer) {
insert_file($site_footer);
}
+ print "</footer>\n";
+
print qq!<script type="text/javascript" src="!.esc_url($javascript).qq!"></script>\n!;
if (defined $action &&
);
git_header_html($http_responses{$status}, undef, %opts);
print <<EOF;
-<div class="page_body">
<br /><br />
$status - $error
<br />
print "<hr />\n" .
"$extra\n";
}
- print "</div>\n";
git_footer_html();
goto DONE_GITWEB
my ($current, $suppress, $head, $treehead, $treebase, $extra) = @_;
$extra = '' if !defined $extra; # pager or formats
- my @navs = qw(summary shortlog log commit commitdiff tree);
+ my @navs = qw(summary shortlog log commit diff tree);
if ($suppress) {
@navs = grep { $_ ne $suppress } @navs;
}
my %arg = map { $_ => {action=>$_} } @navs;
if (defined $head) {
- for (qw(commit commitdiff)) {
+ for (qw(commit diff)) {
$arg{$_}{'hash'} = $head;
}
- if ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {
+ if ($current =~ m/^(tree | log | shortlog | commit | diff | search)$/x) {
for (qw(shortlog log)) {
$arg{$_}{'hash'} = $head;
}
$arg{$label}{'_href'} = $link;
}
- print "<div class=\"page_nav\">\n" .
+ print "<header>";
+ print "<nav>\n" .
(join " | ",
map { $_ eq $current ?
$_ : $cgi->a({-href => ($arg{$_}{_href} ? $arg{$_}{_href} : href(%{$arg{$_}}))}, "$_")
} @navs);
- print "<br/>\n$extra<br/>\n" .
- "</div>\n";
+ print "<br/>\n$extra<br/>\n" if ($extra);
+ print "</nav>\n";
+
+ my $have_search = gitweb_check_feature('search');
+ if (defined $project && $have_search) {
+ print_search_form();
+ }
+ print "</header>";
}
# returns a submenu for the navigation of the refs views (tags, heads,
## functions printing or outputting HTML: div
sub git_print_header_div {
- my ($action, $title, $hash, $hash_base) = @_;
+ my ($action, $title, $refstr, $hash, $hash_base) = @_;
my %args = ();
$args{'action'} = $action;
$args{'hash'} = $hash if $hash;
$args{'hash_base'} = $hash_base if $hash_base;
- print "<div class=\"header\">\n" .
- $cgi->a({-href => href(%args), -class => "title"},
- $title ? $title : $action) .
- "\n</div>\n";
+ if (defined $title && length $title) {
+ print "<div class=\"header\">\n" .
+ $cgi->a({-href => href(%args), -class => "title"},
+ $title ? $title : $action) .
+ "\n</div>\n";
+ }
}
sub format_repo_url {
@people = ('author', 'committer') unless @people;
foreach my $who (@people) {
my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"});
- print "<tr><td>$who</td><td>" .
+ print "<tr><th rowspan=\"2\" class=\"$who\">$who</th><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\">" .
- git_get_avatar($co->{"${who}_email"}, -size => 'double') .
- "</td></tr>\n" .
- "<tr>" .
- "<td></td><td>" .
+ "</td></tr><tr>";
+ if ($git_avatar) {
+ print "<td rowspan=\"2\">"
+ . git_get_avatar($co->{"${who}_email"}, -size => 'double')
+ . "</td>";
+ }
+ print "\n<td>" .
format_timestamp_html(\%wd) .
"</td>" .
"</tr>\n";
my $name = shift;
my $type = shift;
my $hb = shift;
+ my $noprint = shift;
- print "<div class=\"page_path\">";
- print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
+ my $output = $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
-title => 'tree root'}, to_utf8("[$project]"));
- print " / ";
+ $output .= " / ";
if (defined $name) {
my @dirname = split '/', $name;
my $basename = pop @dirname;
foreach my $dir (@dirname) {
$fullname .= ($fullname ? '/' : '') . $dir;
- print $cgi->a({-href => href(action=>"tree", file_name=>$fullname,
+ $output .= $cgi->a({-href => href(action=>"tree", file_name=>$fullname,
hash_base=>$hb),
-title => $fullname}, esc_path($dir));
- print " / ";
+ $output .= " / ";
}
if (defined $type && $type eq 'blob') {
- print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name,
+ $output .= $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name,
hash_base=>$hb),
-title => $name}, esc_path($basename));
} elsif (defined $type && $type eq 'tree') {
- print $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
+ $output .= $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
hash_base=>$hb),
-title => $name}, esc_path($basename));
- print " / ";
+ $output .= " / ";
} else {
- print esc_path($basename);
+ $output .= esc_path($basename);
}
}
- print "<br/></div>\n";
+ $output .= "<br/>\n";
+ unless ($noprint) {
+ print $output;
+ }
+ return $output;
+}
+
+
+sub git_path_header {
+ my $name = shift;
+ my $type = shift;
+ my $hb = shift;
+ my $noprint = shift;
+ my $title = shift;
+ my $ref = shift;
+ my $hash = shift;
+
+ my $output = "";
+ if (defined $name) {
+ my @dirname = split '/', $name;
+ my $basename = pop @dirname;
+ my $fullname = '';
+
+ foreach my $dir (@dirname) {
+ $fullname .= ($fullname ? '/' : '') . $dir;
+ $output .= $cgi->a({-href => href(action=>"tree", file_name=>$fullname,
+ hash_base=>$hb),
+ -title => $fullname, -class => "title"}, esc_path($dir));
+ $output .= " / ";
+ }
+ if (defined $type && $type eq 'blob') {
+ $output .= $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name,
+ hash_base=>$hb),
+ -title => $name, -class => "title"}, esc_path($basename));
+ } elsif (defined $type && $type eq 'tree') {
+ $output .= $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
+ hash_base=>$hb),
+ -title => $name, -class => "title"}, esc_path($basename));
+ $output .= " / ";
+ } else {
+ $output .= esc_path($basename);
+ }
+ }
+
+ $output .= "<span class=\"tree_commit_info\">on commit "
+ . $cgi->a({-href => href(action => 'commit', hash => $ref)}, "$title (" . substr($hash, 0, $hash_char) . ")")
+ . "</span>";
+ unless ($noprint) {
+ print $output;
+ }
+ return $output;
}
sub git_print_log {
# the mode of the entry, list is the name of the entry, an href,
# and link is the action links of the entry.
- print "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n";
+ print "<td class=\"mode\">";
+ if (S_ISDIR(oct $t->{'mode'} & S_IFMT)) {
+ print '<svg width="14" height="14" '
+ . 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
+ . '<use xlink:href="#foldericon" /></svg>';
+ }
+ print mode_str($t->{'mode'}) . "</td>\n";
if (exists $t->{'size'}) {
print "<td class=\"size\">$t->{'size'}</td>\n";
}
my ($difftree, $hash, @parents) = @_;
my ($parent) = $parents[0];
my $have_blame = gitweb_check_feature('blame');
- print "<div class=\"list_head\">\n";
if ($#{$difftree} > 10) {
+ print "<div class=\"list_head\">\n";
print(($#{$difftree} + 1) . " files changed:\n");
+ print "</div>\n";
}
- print "</div>\n";
print "<table class=\"" .
(@parents > 1 ? "combined " : "") .
"diff_tree\">\n";
- # header only for combined diff in 'commitdiff' view
- my $has_header = @$difftree && @parents > 1 && $action eq 'commitdiff';
+ # header only for combined diff in 'diff' view
+ my $has_header = @$difftree && @parents > 1 && $action eq 'diff';
if ($has_header) {
# table header
print "<thead><tr>\n" .
for (my $i = 0; $i < @parents; $i++) {
my $par = $parents[$i];
print "<th>" .
- $cgi->a({-href => href(action=>"commitdiff",
+ $cgi->a({-href => href(action=>"diff",
hash=>$hash, hash_parent=>$par),
- -title => 'commitdiff to parent number ' .
+ -title => 'diff to parent number ' .
($i+1) . ': ' . substr($par,0,7)},
$i+1) .
" </th>\n";
"</td>\n";
}
- if ($action eq 'commitdiff') {
+ if ($action eq 'diff') {
# link to patch
$patchno++;
print "<td class=\"link\">" .
print "</td>\n";
print "<td>$mode_chng</td>\n";
print "<td class=\"link\">";
- if ($action eq 'commitdiff') {
+ if ($action eq 'diff') {
# link to patch
$patchno++;
print $cgi->a({-href => href(-anchor=>"patch$patchno")},
print "</td>\n";
print "<td>$mode_chng</td>\n";
print "<td class=\"link\">";
- if ($action eq 'commitdiff') {
+ if ($action eq 'diff') {
# link to patch
$patchno++;
print $cgi->a({-href => href(-anchor=>"patch$patchno")},
print "</td>\n";
print "<td>$mode_chnge</td>\n";
print "<td class=\"link\">";
- if ($action eq 'commitdiff') {
+ if ($action eq 'diff') {
# link to patch
$patchno++;
print $cgi->a({-href => href(-anchor=>"patch$patchno")},
-class => "list"}, esc_path($diff->{'from_file'})) .
" with " . (int $diff->{'similarity'}) . "% similarity$mode_chng]</span></td>\n" .
"<td class=\"link\">";
- if ($action eq 'commitdiff') {
+ if ($action eq 'diff') {
# link to patch
$patchno++;
print $cgi->a({-href => href(-anchor=>"patch$patchno")},
if (defined $project_filter);
print $cgi->textfield(-name => 's', -value => $searchtext,
-title => "Search project by name and description$limit",
- -size => 60) . "\n" .
+ -size => 60,
+ -placeholder => "search repos") . "\n" .
+ $cgi->submit(-name => 'btnS', -value => 'search') .
"<span title=\"Extended regular expression\">" .
$cgi->checkbox(-name => 'sr', -value => 1, -label => 're',
-checked => $search_use_regexp) .
"</span>\n" .
- $cgi->submit(-name => 'btnS', -value => 'Search') .
$cgi->end_form() . "\n" .
$cgi->a({-href => href(project => undef, searchtext => undef,
project_filter => $project_filter)},
}
print "</td>\n";
}
+
+ # Added by Andrew Lorimer, October 2019
+ # Optionally remove ".git" extension in table
+ my $prname = esc_html_match_hl($pr->{'path'}, $search_regexp);
+ if ($omit_git_extension) {
+ $prname =~ s/\.git//;
+ }
+
print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
- -class => "list"},
- esc_html_match_hl($pr->{'path'}, $search_regexp)) .
+ -class => "list"}, $prname) .
"</td>\n" .
"<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
-class => "list",
$pr->{'descr'}, $search_regexp)
: esc_html($pr->{'descr'})) .
"</td>\n";
+
unless ($omit_owner) {
- print "<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
+ print "<td>" . chop_and_escape_str($pr->{'owner'}, 15) . "</td>\n";
}
+
+ # Modified by Andrew Lorimer, October 2019
+ # Link date field to latest commit
unless ($omit_age_column) {
print "<td class=\"". age_class($pr->{'age'}) . "\">" .
- (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n";
+ (defined $pr->{'age_string'} ? $cgi->a({-href => href(project=>$pr->{'path'},
+ action=>"commit"), -class => "list"}, $pr->{'age_string'}) : "No commits") . "</td>\n";
}
- print"<td class=\"link\">" .
+
+ # Added by Andrew Lorimer, October 2019
+ # Optionally hide repo-specific page shortcuts in project list
+ unless ($omit_shortcuts) {
+ print"<td class=\"link\">" .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " .
$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";
+ "</td>\n";
+ }
+ print "</tr>\n";
}
}
}
print "<table class=\"project_list\">\n";
- unless ($no_header) {
+ unless ($no_header || not $index_header) {
print "<tr>\n";
if ($check_forks) {
print "<th></th>\n";
my $ref = format_ref_marker($refs, $commit);
git_print_header_div('commit',
"<span class=\"age\">$co{'age_string'}</span>" .
- esc_html($co{'title'}) . $ref,
+ 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=>"diff", hash=>$commit)}, "diff") .
" | " .
$cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree") .
"<br/>\n" .
print "</div>\n";
}
if ($extra) {
- print "<div class=\"page_nav\">\n";
+ print "<nav>\n";
print "$extra\n";
- print "</div>\n";
+ print "</nav>\n";
}
}
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" .
+ print "<td class=\"age\" title=\"$co{'age_string_age'}\">$co{'age_string_date'}</td>\n" .
+ "<td class=\"separator\">•</td>" .
format_author_html('td', \%co, 10) . "<td>";
print format_subject_html($co{'title'}, $co{'title_short'},
href(action=>"commit", hash=>$commit), $ref);
print "</td>\n" .
"<td class=\"link\">" .
- $cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") . " | " .
- $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") . " | " .
+ $cgi->a({-href => href(action=>"diff", hash=>$commit)}, "diff") . " | " .
$cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree");
my $snapshot_links = format_snapshot_links($commit);
if (defined $snapshot_links) {
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+ print "<td title=\"$co{'age_string_age'}\">$co{'age_string_date'}</td>\n" .
# shortlog: format_author_html('td', \%co, 10)
format_author_html('td', \%co, 15, 3) . "<td>";
# originally git_history used chop_str($co{'title'}, 50)
print "</td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => href(action=>$ftype, hash_base=>$commit, file_name=>$file_name)}, $ftype) . " | " .
- $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff");
+ $cgi->a({-href => href(action=>"diff", hash=>$commit)}, "diff");
if ($ftype eq 'blob') {
print " | " .
}
$alternate ^= 1;
if (defined $tag{'age'}) {
- print "<td><i>$tag{'age'}</i></td>\n";
+ print "<td>$tag{'age'}</td>\n";
} else {
print "<td></td>\n";
}
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td><i>$ref{'age'}</i></td>\n" .
+ print "<td>$ref{'age'}</td>\n" .
($curr ? "<td class=\"current_head\">" : "<td>") .
$cgi->a({-href => href(action=>"shortlog", hash=>$ref{'fullname'}),
-class => "list name"},esc_html($ref{'name'})) .
"</td>\n" .
"</tr>";
}
- if (defined $extra) {
+ if (defined $extra && $extra != "") {
print "<tr>\n" .
"<td colspan=\"3\">$extra</td>\n" .
"</tr>\n";
my $dots;
if (defined $limit && $limit < @$heads) {
- $dots = $cgi->a({-href => href(action=>"remotes", hash=>$remote)}, "...");
+ $dots = $cgi->a({-href => href(action=>"remotes", hash=>$remote)}, "show all remotes");
}
print $urls_table;
if ($limited) {
print "<tr>\n" .
"<td colspan=\"3\">" .
- $cgi->a({-href => href(action=>"remotes")}, "...") .
+ $cgi->a({-href => href(action=>"remotes")}, "show all remotes") .
"</td>\n" . "</tr>\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" .
+ print "<td title=\"$co{'age_string_age'}\">$co{'age_string_date'}</td>\n" .
+ "<td>$author</td>\n" .
"<td>" .
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
-class => "list subject"},
my $matches = 0;
my $lastfile = '';
my $file_href;
+ my $in_table = 0;
while (my $line = <$fd>) {
chomp $line;
my ($file, $lno, $ltext, $binary);
- last if ($matches++ > 1000);
if ($line =~ /^Binary file (.+) matches$/) {
$file = $1;
$binary = 1;
$file =~ s/^$co{'tree'}://;
}
if ($file ne $lastfile) {
- $lastfile and print "</td></tr>\n";
- if ($alternate++) {
- print "<tr class=\"dark\">\n";
- } else {
- print "<tr class=\"light\">\n";
- }
+ if ($in_table) {
+ print "\t\t</table>\n\t</td>\n</tr>\n";
+ $in_table = 0;
+ }
+ if ($alternate++) {
+ print "<tr class=\"dark\">\n";
+ } else {
+ print "<tr class=\"light\">\n";
+ }
$file_href = href(action=>"blob", hash_base=>$co{'id'},
file_name=>$file);
- print "<td class=\"list\">".
+ print "\t<td class=\"list\">".
$cgi->a({-href => $file_href, -class => "list"}, esc_path($file));
- print "</td><td>\n";
+ print "\t</td>\n";
+ print "\t<td>\n\t\t<table class=\"grep_lines\">\n";
+ $in_table = 1;
$lastfile = $file;
}
+ last if ($matches++ > 1000);
if ($binary) {
- print "<div class=\"binary\">Binary file</div>\n";
+ print "\t\t\t<tr>\n\t\t\t\t<td colspan=\"2\" class=\"binary\">Binary file</td>\n\t\t\t</tr>\n";
} else {
$ltext = untabify($ltext);
if ($ltext =~ m/^(.*)($search_regexp)(.*)$/i) {
} else {
$ltext = esc_html($ltext, -nbsp=>1);
}
- print "<div class=\"pre\">" .
- $cgi->a({-href => $file_href.'#l'.$lno,
- -class => "linenr"}, sprintf('%4i', $lno)) .
- ' ' . $ltext . "</div>\n";
+ print "\t\t\t<tr>\n\t\t\t\t<td>\n\t\t\t\t\t"
+ . $cgi->a({-href => $file_href.'#l'.$lno,
+ -class => "linenr"}, sprintf('%4i', $lno)) . "\n\t\t\t\t</td>\n";
+ print "\t\t\t\t<td>\n\t\t\t\t\t<pre>$ltext</pre>\n\t\t\t\t</td>\n\t\t\t</tr>\n";
}
}
if ($lastfile) {
- print "</td></tr>\n";
if ($matches > 1000) {
- print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
+ print "<td colspan=\"3\"><div class=\"diff nodifferences\">Too many matches, listing trimmed</div></td>\n";
}
+ print "</tr>\n</table>\n";
} else {
- print "<div class=\"diff nodifferences\">No matches found</div>\n";
+ print "<tr><td colspan=\"3\"><div class=\"diff nodifferences\">No matches found</div></td>\n";
+ $in_table = 0;
}
close $fd;
- print "</table>\n";
+ if ($in_table) {
+ print "\t\t</table>\n\t</td>\n";
+ $in_table = 0;
+ }
git_footer_html();
}
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+ print "<td title=\"$co{'age_string_age'}\">$co{'age_string_date'}</td>\n" .
format_author_html('td', \%co, 15, 5) .
"<td>" .
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
}
print "</td>\n" .
"<td class=\"link\">" .
- $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
- " | " .
- $cgi->a({-href => href(action=>"commitdiff", hash=>$co{'id'})}, "commitdiff") .
+ $cgi->a({-href => href(action=>"diff", hash=>$co{'id'})}, "diff") .
" | " .
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
print "</td>\n" .
"</tr>\n";
}
- if (defined $extra) {
+ if (defined $extra && $extra != "") {
print "<tr>\n" .
"<td colspan=\"3\">$extra</td>\n" .
"</tr>\n";
git_header_html();
git_print_page_nav('summary','', $head);
- print "<div class=\"title\"> </div>\n";
print "<table class=\"projects_list\">\n" .
"<tr id=\"metadata_desc\"><td>description</td><td>" . esc_html($descr) . "</td></tr>\n";
if ($owner and not $omit_owner) {
git_print_header_div('shortlog');
git_shortlog_body(\@commitlist, 0, 15, $refs,
$#commitlist <= 15 ? undef :
- $cgi->a({-href => href(action=>"shortlog")}, "..."));
+ $cgi->a({-href => href(action=>"shortlog")}, "show all commits"));
}
if (@taglist) {
git_print_header_div('tags');
git_tags_body(\@taglist, 0, 15,
$#taglist <= 15 ? undef :
- $cgi->a({-href => href(action=>"tags")}, "..."));
+ $cgi->a({-href => href(action=>"tags")}, "show all tags"));
}
if (@headlist) {
git_print_header_div('heads');
git_heads_body(\@headlist, $head, 0, 15,
$#headlist <= 15 ? undef :
- $cgi->a({-href => href(action=>"heads")}, "..."));
+ $cgi->a({-href => href(action=>"heads")}, "show all branches"));
}
if (%remotedata) {
git_print_header_div('forks');
git_project_list_body(\@forklist, 'age', 0, 15,
$#forklist <= 15 ? undef :
- $cgi->a({-href => href(action=>"forks")}, "..."),
+ $cgi->a({-href => href(action=>"forks")}, "show all forks"),
'no_header');
}
}
print "</table>\n\n" .
"</div>\n";
- print "<div class=\"page_body\">";
+ print "<main>";
my $comment = $tag{'comment'};
foreach my $line (@$comment) {
chomp $line;
- print esc_html($line, -nbsp=>1) . "<br/>\n";
+ print esc_html($line, -nbsp=>1) . "\n";
}
- print "</div>\n";
+ print "</main>\n";
git_footer_html();
}
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!.
$cgi->a({-href => href(action=>"blob_plain", -replay=>1)},
"raw");
}
- git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
- git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
+ git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base);
+ print "<div class=\"header\">\n";
+ print git_path_header($file_name, "blob", $hash_base, 1, esc_html($co{'title'}), $co{'id'}, $co{'id'});
+ print "</div>"
} else {
- print "<div class=\"page_nav\">\n" .
- "<br/><br/></div>\n" .
+ print "<nav>\n" .
+ "</nav>\n" .
"<div class=\"title\">".esc_html($hash)."</div>\n";
}
- git_print_page_path($file_name, "blob", $hash_base);
- print "<div class=\"page_body\">\n";
+ print "<nav class=\"formats_nav\">" . $formats_nav . "</nav>";
+
if ($mimetype =~ m!^image/!) {
- print qq!<img class="blob" type="!.esc_attr($mimetype).qq!"!;
+ my $img_src = href(action=>"blob_plain", hash=>$hash,
+ hash_base=>$hash_base, file_name=>$file_name);
+ print qq!<a href="$img_src"><img class="blob" type="!.esc_attr($mimetype).qq!"!;
if ($file_name) {
print qq! alt="!.esc_attr($file_name).qq!" title="!.esc_attr($file_name).qq!"!;
}
- print qq! src="! .
- href(action=>"blob_plain", hash=>$hash,
- hash_base=>$hash_base, file_name=>$file_name) .
- qq!" />\n!;
+ print qq! src="! .$img_src . qq!" /></a>\n!;
} else {
my $nr;
+ print "<pre class=\"tree_lines\">";
while (my $line = <$fd>) {
chomp $line;
$nr++;
- $line = untabify($line);
- printf qq!<div class="pre"><a id="l%i" href="%s#l%i" class="linenr">%4i</a> %s</div>\n!,
+ # $line = untabify($line);
+ printf qq!<span class="tree_line"><a id="l%i" href="%s#l%i" class="linenr">%4i</a><code>%s</code></span>\n!,
$nr, esc_attr(href(-replay => 1)), $nr, $nr,
$highlight ? sanitize($line) : esc_html($line, -nbsp=>1);
}
+ print "</pre>";
}
close $fd
or print "Reading blob failed.\n";
- print "</div>";
git_footer_html();
}
# FIXME: Should be available when we have no hash base as well.
push @views_nav, $snapshot_links;
}
- git_print_page_nav('tree','', $hash_base, undef, undef,
- join(' | ', @views_nav));
- git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
+ git_print_page_nav('tree','', $hash_base, undef, undef);
+ if (scalar(@views_nav) > 0) {
+ print "<nav class=\"formats_nav\">" . join(' | ', @views_nav) . "</nav>";
+ }
+ unless ($hash_base eq "HEAD") {
+ git_print_header_div('commit', esc_html($co{'title'}), $ref, $hash_base);
+ }
} else {
undef $hash_base;
- print "<div class=\"page_nav\">\n";
- print "<br/><br/></div>\n";
- print "<div class=\"title\">".esc_html($hash)."</div>\n";
+ print "<nav>\n";
+ print "</nav>".esc_html($hash)."</div>\n";
}
if (defined $file_name) {
$basedir = $file_name;
}
git_print_page_path($file_name, 'tree', $hash_base);
}
- print "<div class=\"page_body\">\n";
print "<table class=\"tree\">\n";
- my $alternate = 1;
# '..' (top directory) link if possible
if (defined $hash_base &&
defined $file_name && $file_name =~ m![^/]+$!) {
- if ($alternate) {
- print "<tr class=\"dark\">\n";
- } else {
- print "<tr class=\"light\">\n";
- }
- $alternate ^= 1;
-
+ print "<tr>\n";
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";
+ print '<td class="mode">';
+ print '<svg width="14" height="14" '
+ . 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
+ . '<use xlink:href="#parenticon" /></svg>';
+ print mode_str('040000') . "</td>\n";
print '<td class="size"> </td>'."\n" if $show_sizes;
print '<td class="list">';
print $cgi->a({-href => href(action=>"tree",
hash_base=>$hash_base,
file_name=>$up)},
- "..");
+ "parent");
print "</td>\n";
print "<td class=\"link\"></td>\n";
print "</tr>\n";
}
+ my @treefilter_pattern = gitweb_get_feature('tree_filter');
foreach my $line (@entries) {
- my %t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
-
- if ($alternate) {
- print "<tr class=\"dark\">\n";
- } else {
- print "<tr class=\"light\">\n";
- }
- $alternate ^= 1;
-
- git_print_tree_entry(\%t, $basedir, $hash_base, $have_blame);
-
- print "</tr>\n";
+ my $t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
+ if ($t->{'name'} =~ /@treefilter_pattern/) {
+ print "<tr>\n";
+ git_print_tree_entry($t, $basedir, $hash_base, $have_blame);
+ print "</tr>\n";
+ }
}
- print "</table>\n" .
- "</div>";
+ print "</table>\n";
git_footer_html();
}
# we need to prepare $formats_nav before any parameter munging
my $formats_nav;
if (!defined $parent) {
- # --root commitdiff
+ # --root diff
$formats_nav .= '(initial)';
} elsif (@$parents == 1) {
# single parent commit
'(parent: ' .
$cgi->a({-href => href(action=>"commit",
hash=>$parent)},
- esc_html(substr($parent, 0, 7))) .
+ esc_html(substr($parent, 0, $hash_char))) .
')';
} else {
# merge commit
join(' ', map {
$cgi->a({-href => href(action=>"commit",
hash=>$_)},
- esc_html(substr($_, 0, 7)));
+ esc_html(substr($_, 0, $hash_char)));
} @$parents ) .
')';
}
git_header_html(undef, $expires);
git_print_page_nav('commit', '',
- $hash, $co{'tree'}, $hash,
- $formats_nav);
+ $hash, $co{'tree'}, $hash);
if (defined $co{'parent'}) {
- git_print_header_div('commitdiff', esc_html($co{'title'}) . $ref, $hash);
+ git_print_header_div('diff', esc_html($co{'title'}), $ref, $hash);
} else {
- git_print_header_div('tree', esc_html($co{'title'}) . $ref, $co{'tree'}, $hash);
+ git_print_header_div('tree', esc_html($co{'title'}), $ref, $co{'tree'}, $hash);
}
print "<div class=\"title_text\">\n" .
"<table class=\"object_header\">\n";
git_print_authorship_rows(\%co);
- print "<tr><td>commit</td><td class=\"sha1\">$co{'id'}</td></tr>\n";
+ print "<tr><th>commit</th><td class=\"sha1\">" . truncate_hash($co{'id'})
+ . "</td></tr>\n";
print "<tr>" .
- "<td>tree</td>" .
+ "<th>tree</th>" .
"<td class=\"sha1\">" .
- $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash),
- class => "list"}, $co{'tree'}) .
- "</td>" .
- "<td class=\"link\">" .
- $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash)},
+ truncate_hash($co{'tree'}, "tree_hash", href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash)) .
+ " (" . $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash)},
"tree");
my $snapshot_links = format_snapshot_links($hash);
if (defined $snapshot_links) {
print " | " . $snapshot_links;
}
- print "</td>" .
+ print ")</td>" .
"</tr>\n";
foreach my $par (@$parents) {
print "<tr>" .
- "<td>parent</td>" .
+ "<th>parent</th>" .
"<td class=\"sha1\">" .
- $cgi->a({-href => href(action=>"commit", hash=>$par),
- class => "list"}, $par) .
- "</td>" .
- "<td class=\"link\">" .
- $cgi->a({-href => href(action=>"commit", hash=>$par)}, "commit") .
- " | " .
- $cgi->a({-href => href(action=>"commitdiff", hash=>$hash, hash_parent=>$par)}, "diff") .
- "</td>" .
+ truncate_hash($par, "parent_hash", href(action=>"commit", hash=>$par)) .
+ " (" .
+ $cgi->a({-href => href(action=>"diff", hash=>$hash, hash_parent=>$par)}, "diff") .
+ ")</td>" .
"</tr>\n";
}
print "</table>".
"</div>\n";
-
- print "<div class=\"page_body\">\n";
- git_print_log($co{'comment'});
- print "</div>\n";
+ print "<nav class=\"formats_nav\">$formats_nav</nav>";
git_difftree_body(\@difftree, $hash, @$parents);
git_footer_html();
}
+sub truncate_hash {
+ # Truncate an SHA1 hash into HTML code tags & add link
+ my ($value, $elem_id, $href) = @_;
+ my $truncated = (defined $elem_id ? "<span id=\"$elem_id\">" : "<span>");
+ my $span_content = "<code>" . esc_html(substr($value, 0, $hash_char))
+ . "</code><code class=\"ellipsis\">...</code><code class=\"spoiler\">"
+ . esc_html(substr($value, $hash_char + 1))
+ . "</code>";
+ if (defined $href) {
+ $truncated .= $cgi->a({-href => $href, -class => "list"}, $span_content);
+ } else {
+ $truncated .= $span_content;
+ }
+ $truncated .= (defined $elem_id ? copy_svg($elem_id) : "") . "</span>";
+ return $truncated;
+}
+
+sub copy_svg {
+ # Return an HTML string containing an SVG button to copy the content of
+ # an element to the clipboard.
+ my ($elem_id) = @_;
+ return "<svg width=\"14\" height=\"14\" xmlns=\"http://www.w3.org/2000/svg\" "
+ . "xmlns:xlink=\"http://www.w3.org/1999/xlink\" class=\"copyicon\" "
+ . "onclick=\"clipboardCopy('$elem_id');\">"
+ . "<title>copy hash to clipboard</title>"
+ . "<use xlink:href=\"#copyicon\" /></svg>";
+}
+
sub git_object {
# object is defined by:
# - hash or hash_base alone
$formats_nav .= diff_style_nav($diff_style);
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_page_nav('','', $hash_base,$co{'tree'},$hash_base);
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
} else {
- print "<div class=\"page_nav\"><br/>$formats_nav<br/></div>\n";
print "<div class=\"title\">".esc_html("$hash vs $hash_parent")."</div>\n";
}
if (defined $file_name) {
# patch
if ($format eq 'html') {
- print "<div class=\"page_body\">\n";
-
git_patchset_body($fd, $diff_style,
[ \%diffinfo ], $hash_base, $hash_parent_base);
close $fd;
- print "</div>\n"; # class="page_body"
git_footer_html();
} else {
} @styles;
}
-sub git_commitdiff {
+sub git_diff {
my %params = @_;
my $format = $params{-format} || 'html';
my $diff_style = $input_params{'diff_style'} || 'inline';
my %co = parse_commit($hash)
or die_error(404, "Unknown commit object");
- # choose format for commitdiff for merge
+ # choose format for diff for merge
if (! defined $hash_parent && @{$co{'parents'}} > 1) {
$hash_parent = '--cc';
}
my $formats_nav;
if ($format eq 'html') {
$formats_nav =
- $cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},
+ $cgi->a({-href => href(action=>"diff_plain", -replay=>1)},
"raw");
if ($patch_max && @{$co{'parents'}} <= 1) {
$formats_nav .= " | " .
if (defined $hash_parent &&
$hash_parent ne '-c' && $hash_parent ne '--cc') {
- # commitdiff with two commits given
+ # diff with two commits given
my $hash_parent_short = $hash_parent;
if ($hash_parent =~ m/^$oid_regex$/) {
$hash_parent_short = substr($hash_parent, 0, 7);
esc_html($hash_parent_short)) .
')';
} elsif (!$co{'parent'}) {
- # --root commitdiff
+ # --root diff
$formats_nav .= ' (initial)';
} elsif (scalar @{$co{'parents'}} == 1) {
# single parent commit
@{$co{'parents'}} > 1 ? '--cc' : $co{'parent'} || '--root';
}
- # read commitdiff
+ # read diff
my $fd;
my @difftree;
if ($format eq 'html') {
'--encoding=utf8', '--stdout', @commit_spec
or die_error(500, "Open git-format-patch failed");
} else {
- die_error(400, "Unknown commitdiff format");
+ die_error(400, "Unknown diff format");
}
# non-textual hash id's can be cached
my $ref = format_ref_marker($refs, $co{'id'});
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);
+ git_print_page_nav('diff','', $hash,$co{'tree'},$hash);
+ git_print_header_div('commit', esc_html($co{'title'}), $ref, $hash);
print "<div class=\"title_text\">\n" .
"<table class=\"object_header\">\n";
git_print_authorship_rows(\%co);
print "</table>".
"</div>\n";
- print "<div class=\"page_body\">\n";
if (@{$co{'comment'}} > 1) {
print "<div class=\"log\">\n";
git_print_log($co{'comment'}, -final_empty_line=> 1, -remove_title => 1);
$hash_parent eq '-c' || $hash_parent eq '--cc';
git_difftree_body(\@difftree, $hash,
$use_parents ? @{$co{'parents'}} : $hash_parent);
- print "<br/>\n";
+ print "<nav class=\"formats_nav\">$formats_nav</nav>";
git_patchset_body($fd, $diff_style,
\@difftree, $hash,
$use_parents ? @{$co{'parents'}} : $hash_parent);
close $fd;
- print "</div>\n"; # class="page_body"
git_footer_html();
} elsif ($format eq 'plain') {
}
}
-sub git_commitdiff_plain {
- git_commitdiff(-format => 'plain');
+sub git_diff_plain {
+ git_diff(-format => 'plain');
}
# format-patch-style patches
sub git_patch {
- git_commitdiff(-format => 'patch', -single => 1);
+ git_diff(-format => 'patch', -single => 1);
}
sub git_patches {
- git_commitdiff(-format => 'patch');
+ git_diff(-format => 'patch');
}
sub git_history {
if (defined $descr) {
$descr = esc_html($descr);
} else {
- $descr = "$project " .
- ($format eq 'rss' ? 'RSS' : 'Atom') .
- " feed";
+ $descr = ($format eq 'rss' ? 'RSS' : 'Atom') .
+ " feed of $project";
}
my $owner = git_get_project_owner($project);
$owner = esc_html($owner);
or next;
# print element (entry, item)
- my $co_url = href(-full=>1, action=>"commitdiff", hash=>$commit);
+ my $co_url = href(-full=>1, action=>"diff", hash=>$commit);
if ($format eq 'rss') {
print "<item>\n" .
"<title>" . esc_html($co{'title'}) . "</title>\n" .