X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/ed433e486ee9aa30b6685a586a09ac0a32dcf98d879ccc9ced5ed2eb6a52422f..a040232a8f88efb9caaba991ebb3a386eba3d8d9f0f9c10fbb82ed774d8f1253:/gitweb.perl
diff --git a/gitweb.perl b/gitweb.perl
index 7e1e27a..2f78bfb 100755
--- a/gitweb.perl
+++ b/gitweb.perl
@@ -1117,8 +1117,7 @@ sub to_utf8 {
# correct, but quoted slashes look too horrible in bookmarks
sub esc_param {
my $str = shift;
- $str =~ s/([^A-Za-z0-9\-_.~()\/:@])/sprintf("%%%02X", ord($1))/eg;
- $str =~ s/\+/%2B/g;
+ $str =~ s/([^A-Za-z0-9\-_.~()\/:@ ]+)/CGI::escape($1)/eg;
$str =~ s/ /\+/g;
return $str;
}
@@ -1629,6 +1628,29 @@ sub git_get_avatar {
}
}
+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;
+ }
+}
+
# 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).
@@ -1637,8 +1659,10 @@ sub format_author_html {
my $co = shift;
my $author = chop_and_escape_str($co->{'author_name'}, @_);
return "<$tag class=\"author\">" .
- git_get_avatar($co->{'author_email'}, -pad_after => 1) .
- $author . "$tag>";
+ format_search_author($co->{'author_name'}, "author",
+ git_get_avatar($co->{'author_email'}, -pad_after => 1) .
+ $author) .
+ "$tag>";
}
# format git diff header line, i.e. "diff --(git|combined|cc) ..."
@@ -2018,16 +2042,27 @@ sub quote_command {
# get HEAD ref of given project as hash
sub git_get_head_hash {
- my $project = shift;
+ 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) = @_;
my $o_git_dir = $git_dir;
my $retval = undef;
$git_dir = "$projectroot/$project";
- if (open my $fd, "-|", git_cmd(), "rev-parse", "--verify", "HEAD") {
- my $head = <$fd>;
+ if (open my $fd, '-|', git_cmd(), 'rev-parse',
+ '--verify', '-q', @options, $hash) {
+ $retval = <$fd>;
+ chomp $retval if defined $retval;
close $fd;
- if (defined $head && $head =~ /^([0-9a-fA-F]{40})$/) {
- $retval = $1;
- }
}
if (defined $o_git_dir) {
$git_dir = $o_git_dir;
@@ -3449,10 +3484,11 @@ sub git_print_authorship {
my $co = shift;
my %opts = @_;
my $tag = $opts{-tag} || 'div';
+ my $author = $co->{'author_name'};
my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'});
print "<$tag class=\"author_date\">" .
- esc_html($co->{'author_name'}) .
+ format_search_author($author, "author", esc_html($author)) .
" [$ad{'rfc2822'}";
print_local_time(%ad) if ($opts{-localtime});
print "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1)
@@ -3471,8 +3507,12 @@ sub git_print_authorship_rows {
@people = ('author', 'committer') unless @people;
foreach my $who (@people) {
my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"});
- print "
| $who | " . esc_html($co->{$who}) . " | " .
- "" .
+ print " |
| $who | " .
+ format_search_author($co->{"${who}_name"}, $who,
+ esc_html($co->{"${who}_name"})) . " " .
+ format_search_author($co->{"${who}_email"}, $who,
+ esc_html("<" . $co->{"${who}_email"} . ">")) .
+ " | " .
git_get_avatar($co->{"${who}_email"}, -size => 'double') .
" |
\n" .
"" .
@@ -4380,6 +4420,46 @@ sub git_project_list_body {
print "\n";
}
+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);
+ my %ad = parse_date($co{'author_epoch'});
+ git_print_header_div('commit',
+ "$co{'age_string'}" .
+ esc_html($co{'title'}) . $ref,
+ $commit);
+ print "\n" .
+ "
\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") .
+ "
\n" .
+ "
\n";
+ git_print_authorship(\%co, -tag => 'span');
+ print "
\n
\n";
+
+ print "\n";
+ git_print_log($co{'comment'}, -final_empty_line=> 1);
+ print "
\n";
+ }
+ if ($extra) {
+ print "\n";
+ print "$extra\n";
+ print "
\n";
+ }
+}
+
sub git_shortlog_body {
# uses global variable $project
my ($commitlist, $from, $to, $refs, $extra) = @_;
@@ -5238,7 +5318,8 @@ sub git_blob {
chomp $line;
$nr++;
$line = untabify($line);
- printf "\n",
+ printf "\n",
$nr, $nr, $nr, esc_html($line, -nbsp=>1);
}
}
@@ -5358,6 +5439,43 @@ sub git_tree {
git_footer_html();
}
+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;
+}
+
sub git_snapshot {
my $format = $input_params{'snapshot_format'};
if (!@snapshot_fmts) {
@@ -5382,24 +5500,20 @@ sub git_snapshot {
die_error(400, 'Object is not a tree-ish');
}
- my $name = $project;
- $name =~ s,([^/])/*\.git$,$1,;
- $name = basename($name);
- my $filename = to_utf8($name);
- $name =~ s/\047/\047\\\047\047/g;
- my $cmd;
- $filename .= "-$hash$known_snapshot_formats{$format}{'suffix'}";
- $cmd = quote_command(
+ my ($name, $prefix) = snapshot_name($project, $hash);
+ my $filename = "$name$known_snapshot_formats{$format}{'suffix'}";
+ my $cmd = quote_command(
git_cmd(), 'archive',
"--format=$known_snapshot_formats{$format}{'format'}",
- "--prefix=$name/", $hash);
+ "--prefix=$prefix/", $hash);
if (exists $known_snapshot_formats{$format}{'compressor'}) {
$cmd .= ' | ' . quote_command(@{$known_snapshot_formats{$format}{'compressor'}});
}
+ $filename =~ s/(["\\])/\\$1/g;
print $cgi->header(
-type => $known_snapshot_formats{$format}{'type'},
- -content_disposition => 'inline; filename="' . "$filename" . '"',
+ -content_disposition => 'inline; filename="' . $filename . '"',
-status => '200 OK');
open my $fd, "-|", $cmd
@@ -5423,7 +5537,12 @@ sub git_log {
my @commitlist = parse_commits($hash, 101, (100 * $page));
my $paging_nav = format_paging_nav('log', $hash, $head, $page, $#commitlist >= 100);
-
+ my $next_link;
+ if ($#commitlist >= 100) {
+ $next_link =
+ $cgi->a({-href => href(-replay=>1, page=>$page+1),
+ -accesskey => "n", -title => "Alt-n"}, "next");
+ }
my ($patch_max) = gitweb_get_feature('patches');
if ($patch_max) {
if ($patch_max < 0 || @commitlist <= $patch_max) {
@@ -5442,39 +5561,9 @@ sub git_log {
git_print_header_div('summary', $project);
print " Last change $co{'age_string'}.
\n";
}
- my $to = ($#commitlist >= 99) ? (99) : ($#commitlist);
- 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);
- my %ad = parse_date($co{'author_epoch'});
- git_print_header_div('commit',
- "$co{'age_string'}" .
- esc_html($co{'title'}) . $ref,
- $commit);
- print "\n" .
- "
\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") .
- "
\n" .
- "
\n";
- git_print_authorship(\%co, -tag => 'span');
- print "
\n
\n";
- print "\n";
- git_print_log($co{'comment'}, -final_empty_line=> 1);
- print "
\n";
- }
- if ($#commitlist >= 100) {
- print "\n";
- print $cgi->a({-href => href(-replay=>1, page=>$page+1),
- -accesskey => "n", -title => "Alt-n"}, "next");
- print "
\n";
- }
+ git_log_body(\@commitlist, 0, 99, $refs, $next_link);
+
git_footer_html();
}
@@ -5510,7 +5599,7 @@ sub git_commit {
} @$parents ) .
')';
}
- if (gitweb_check_feature('patches')) {
+ if (gitweb_check_feature('patches') && @$parents <= 1) {
$formats_nav .= " | " .
$cgi->a({-href => href(action=>"patch", -replay=>1)},
"patch");
@@ -5798,7 +5887,7 @@ sub git_commitdiff {
$formats_nav =
$cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},
"raw");
- if ($patch_max) {
+ if ($patch_max && @{$co{'parents'}} <= 1) {
$formats_nav .= " | " .
$cgi->a({-href => href(action=>"patch", -replay=>1)},
"patch");
@@ -6006,7 +6095,7 @@ sub git_commitdiff_plain {
# format-patch-style patches
sub git_patch {
- git_commitdiff(-format => 'patch', -single=> 1);
+ git_commitdiff(-format => 'patch', -single => 1);
}
sub git_patches {