git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFCv3 1/2] gitweb: add patch view

From
Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Date
Dec 3, 2008, 22:59 UTC
Message-ID
<1228345188-15125-2-git-send-email-giuseppe.bilotta@gmail.com>
In-Reply-To
<1228345188-15125-1-git-send-email-giuseppe.bilotta@gmail.com>
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@gmail.com>
---
 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
Previous: Giuseppe BilottaNext: Giuseppe Bilotta
Message 2 of 20 in “[RFCv3 0/2] gitweb: patch view”
  1. Giuseppe BilottaDec 3, 2008
  2. 1/2 gitweb: add patch viewGiuseppe Bilotta, Dec 3, 2008
  3. 2/2 gitweb: links to patch action in commitdiff and shortlog viewGiuseppe Bilotta, Dec 3, 2008
  4. Jakub NarebskiDec 6, 2008
  5. Giuseppe BilottaDec 6, 2008
  6. Jakub NarebskiDec 6, 2008
  7. Junio C HamanoDec 3, 2008
  8. Giuseppe BilottaDec 4, 2008
  9. Junio C HamanoDec 4, 2008
  10. Jakub NarebskiDec 4, 2008
  11. Giuseppe BilottaDec 4, 2008
  12. Jakub NarebskiDec 6, 2008
  13. Junio C HamanoDec 6, 2008
  14. Jakub NarebskiDec 6, 2008
  15. Junio C HamanoDec 6, 2008
  16. Giuseppe BilottaDec 6, 2008
  17. Petr BaudisDec 6, 2008
  18. Giuseppe BilottaDec 6, 2008
  19. Jakub NarebskiDec 6, 2008
  20. Giuseppe BilottaDec 6, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.