The manually-built email format in commitdiff_plain output is not appropriate for feeding git-am, because of two limitations: * when a range of commits is specified, commitdiff_plain publishes a single patch with the message from the first commit, instead of a patchset, * in either case, the patch summary is replicated both as email subject and as first line of the email itself, resulting in a doubled summary if the output is fed to git-am. We thus create a new view that can be fed to git-am directly by exposing the output of git format-patch directly. This allows patch exchange and submission via gitweb. A configurable limit is imposed on the number of commits which will be included in a patchset, to prevent DoS attacks on the server. Setting the limit to 0 will disable the patch view, setting it to a negative number will remove the limit. Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@xxxxxxxxx> --- gitweb/gitweb.perl | 41 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 40 insertions(+), 1 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 2738643..c9abfcf 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -329,6 +329,13 @@ our %feature = ( 'ctags' => { 'override' => 0, 'default' => [0]}, + + # 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. + 'patches' => { + 'override' => 1, + 'default' => [16]}, ); sub gitweb_get_feature { @@ -503,6 +510,7 @@ our %actions = ( "heads" => \&git_heads, "history" => \&git_history, "log" => \&git_log, + "patch" => \&git_patch, "rss" => \&git_rss, "atom" => \&git_atom, "search" => \&git_search, @@ -5386,6 +5394,12 @@ sub git_blobdiff_plain { sub git_commitdiff { my $format = shift || 'html'; + + my $patch_max = gitweb_check_feature('patches'); + if ($format eq 'patch') { + die_error(403, "Patch view not allowed") unless $patch_max; + } + $hash ||= $hash_base || "HEAD"; my %co = parse_commit($hash) or die_error(404, "Unknown commit object"); @@ -5396,6 +5410,7 @@ sub git_commitdiff { } # we need to prepare $formats_nav before almost any parameter munging my $formats_nav; + if ($format eq 'html') { $formats_nav = $cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)}, @@ -5483,7 +5498,12 @@ sub git_commitdiff { open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, '-p', $hash_parent_param, $hash, "--" or die_error(500, "Open git-diff-tree failed"); - + } elsif ($format eq 'patch') { + open $fd, "-|", git_cmd(), "format-patch", '--encoding=utf8', + '--stdout', $patch_max > 0 ? "-$patch_max" : (), + $hash_parent ? ('-n', "$hash_parent..$hash") : + ('--root', '-1', $hash) + or die_error(500, "Open git-format-patch failed"); } else { die_error(400, "Unknown commitdiff format"); } @@ -5532,6 +5552,15 @@ sub git_commitdiff { print to_utf8($line) . "\n"; } print "---\n\n"; + } 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" . '"'); + # TODO add X-Git-Tag/X-Git-Url headers in a sensible way } # write patch @@ -5553,6 +5582,11 @@ sub git_commitdiff { print <$fd>; close $fd or print "Reading git-diff-tree failed\n"; + } elsif ($format eq 'patch') { + local $/ = undef; + print <$fd>; + close $fd + or print "Reading git-format-patch failed\n"; } } @@ -5560,6 +5594,11 @@ sub git_commitdiff_plain { git_commitdiff('plain'); } +# format-patch-style patches +sub git_patch { + git_commitdiff('patch'); +} + sub git_history { if (!defined $hash_base) { $hash_base = git_get_head_hash($project); -- 1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html