Skip to contentSkip to conversation

PATCH: Allow format-patch to attach patches

PATCH Mike McCormack 3 participants 4 messages Jun 15, 2016

lore
Share & tools
lore
#0 lore raw

The --attach patch to git-format-patch to attach patches instead of inlining them. Some mailers linewrap inlined patches (eg. Mozilla).

---

 git-format-patch.sh |   52 
++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 45 insertions(+), 7 deletions(-)

b17ef6b06ebaaf9b6d1f47c6a788cffd77e2b927

git-format-patch.sh +45 -7
index bbd2e55..2ebf7e8 100755
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-USAGE='[-n | -k] [-o <dir> | --stdout] [--signoff] [--check] [--diff-options] <his> [<mine>]'
+USAGE='[-n | -k] [-o <dir> | --stdout] [--signoff] [--check] [--diff-options] [--attach] <his> [<mine>]'
 LONG_USAGE='Prepare each commit with its patch since <mine> head forked from
 <his> head, one file per patch formatted to resemble UNIX mailbox
 format, for e-mail submission or use with git-am.
@@ -18,7 +18,9 @@ is ignored if --stdout is specified.
 
 When -n is specified, instead of "[PATCH] Subject", the first
 line is formatted as "[PATCH N/M] Subject", unless you have only
-one patch.'
+one patch.
+
+When --attach is specified, patches are attached, not inlined.'
 
 . git-sh-setup
 
@@ -40,6 +42,8 @@ do
     -d|--d|--da|--dat|--date|\
     -m|--m|--mb|--mbo|--mbox) # now noop
     ;;
+    --at|--att|--atta|--attac|--attach)
+    attach=t ;;
     -k|--k|--ke|--kee|--keep|--keep-|--keep-s|--keep-su|--keep-sub|\
     --keep-subj|--keep-subje|--keep-subjec|--keep-subject)
     keep_subject=t ;;
@@ -150,6 +154,11 @@ done >$series
 
 me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
 headers=`git-repo-config --get format.headers`
+case "$attach" in
+"") ;;
+*)
+	mimemagic="050802040500080604070107"
+esac
 
 case "$outdir" in
 */) ;;
@@ -174,7 +183,7 @@ titleScript='
 
 process_one () {
 	perl -w -e '
-my ($keep_subject, $num, $signoff, $headers, $commsg) = @ARGV;
+my ($keep_subject, $num, $signoff, $headers, $mimemagic, $commsg) = @ARGV;
 my ($signoff_pattern, $done_header, $done_subject, $done_separator, $signoff_seen,
     $last_was_signoff);
 
@@ -229,6 +238,16 @@ while (<FH>) {
 	    print "$headers\n";
 	}
         print "Subject: $_";
+	if ($mimemagic) {
+	    print "MIME-Version: 1.0\n";
+	    print "Content-Type: multipart/mixed;\n";
+	    print " boundary=\"------------$mimemagic\"\n";
+	    print "\n";
+	    print "This is a multi-part message in MIME format.\n";
+	    print "--------------$mimemagic\n";
+	    print "Content-Type: text/plain; charset=UTF-8; format=fixed\n";
+	    print "Content-Transfer-Encoding: 8bit\n";
+	}
 	$done_subject = 1;
 	next;
     }
@@ -254,14 +273,33 @@ if (!$signoff_seen && $signoff ne "") {
 }
 print "\n---\n\n";
 close FH or die "close $commsg pipe";
-' "$keep_subject" "$num" "$signoff" "$headers" $commsg
+' "$keep_subject" "$num" "$signoff" "$headers" "$mimemagic" $commsg
 
 	git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
 	echo
+	case "$mimemagic" in
+	'');;
+	*)
+		echo "--------------$mimemagic"
+		echo "Content-Type: text/x-patch;"
+		echo " name=\"$commit.diff\""
+		echo "Content-Transfer-Encoding: 8bit"
+		echo "Content-Disposition: inline;"
+		echo " filename=\"$commit.diff\""
+		echo
+	esac
 	git-diff-tree -p $diff_opts "$commit"
-	echo "-- "
-	echo "@@GIT_VERSION@@"
-
+	case "$mimemagic" in
+	'')
+		echo "-- "
+		echo "@@GIT_VERSION@@"
+		;;
+	*)
+		echo
+		echo "--------------$mimemagic--"
+		echo
+		;;
+	esac
 	echo
 }
 
#1 lore raw

Nicely done.

Especially I like the part that you explicitly set charset to UTF-8 to the primary part.

The only two and half minor issues I might have about this are:

(1) is the type text/x-patch appropriate?

(2) is it possible to cheaply come up with a safe mime-magic, instead of a hardcoded long string and hope it does not clash?

You can just say "Yes it is an established practice, widely accepted and that is what you are responding to so obviously you can grok it ;-)" to (1). About (2), you would probably need to read the "diff-tree -p" output beforehand if we want to be absolutely sure, so punting on the issue like this might be the best practical approach for now, but I am asking it anyway because people may have better ideas.

The remaining half issue is if would it make sense to sometimes optionally use non 8-bit CTE for the patch part. I do _NOT_ want to receive CTE=QP patch myself, nor I want to encourage it (actually I would want to actively discourage it), but I do not mind if people find use of such a patch in a distant corner of the galaxy where I do not have to touch such a patch.

#2 lore raw
Quoted 3 lines · Junio C Hamano

The only two and half minor issues I might have about this are:

(1) is the type text/x-patch appropriate?

I'm no expert on MIME types, unfortunately. Maybe text/x-diff makes more sense? A few different projects require one of those two types for diffs sent as attachments. My main concern is that mailers can recognize that the attachment is text, then displayed with the message so that people can see the patch without opening the attachment.

Quoted 3 lines

(2) is it possible to cheaply come up with a safe mime-magic, instead of a hardcoded long string and hope it does not clash?

I agree that using a hardcoded long string isn't that great. Reading all of the "diff-tree -p" output seems a bit expensive. How about using
some part of the patch's SHA1 combined with date/time?

Quoted 2 lines

The remaining half issue is if would it make sense to sometimes optionally use non 8-bit CTE for the patch part.

Maybe allow something like:

git-format-patch --attach=quoted-printable

where the default would be 8bit. This require adding a perl script for each Content-Transfer-Encoding that we support.

Mike

#3 lore raw
In reply to Junio C Hamano
Quoted 1 line · Junio C Hamano

Nicely done.

...

Quoted 2 lines

The only two and half minor issues I might have about this are:

...

Quoted 4 lines

(2) is it possible to cheaply come up with a safe mime-magic, instead of a hardcoded long string and hope it does not clash?

Base64 encode a large number (160?) of bits from /dev/urandom.