shithub: riscv

Download patch

ref: 5dcb8d92ff849359a164b7c0d7ecae64594d6db6
parent: cc8e899df73f9b368faf7d6e9e98f0e0494af2bd
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Mar 9 14:38:04 EDT 2025

git/import: add support for concatenated patches

git/export could export multiple patches at once to stdout,
but git/import would only handle one patch on stdin at a time.
This fixes the asymmetry, and makes it possible for mutliple
patches to get passed to git/import at once.

--- a/sys/man/1/git
+++ b/sys/man/1/git
@@ -430,6 +430,8 @@
 exports a list of commits in a format that
 .I git/import
 can apply.
+If multiple patches are generated,
+they are separated with a ⑨ character.
 .PP
 .I Git/import
 imports a commit with message, author, and
@@ -436,8 +438,10 @@
 date information.
 When passed the
 .B -n
-option, applies the contents of the commit without
-committing to the branch.
+option,
+it applies the contents of the commit without committing to the branch.
+Git/import can accept multiple patches on stdin.
+When multiple patches are supplied, each patch must be separated with a ⑨ character.
 .PP
 .I Git/merge
 takes two branches and merges them filewise using
--- a/sys/src/cmd/git/export
+++ b/sys/src/cmd/git/export
@@ -73,6 +73,8 @@
 				b=/dev/null
 			diff -ur $a $b
 		}
+		echo '-- '
+		echo '⑨'
 	} >$patchfile
 	if(~ $#patchdir 0){
 		cat $patchfile
--- a/sys/src/cmd/git/import
+++ b/sys/src/cmd/git/import
@@ -7,6 +7,36 @@
 	rm -f $diffpath
 }
 
+fn apply1 {
+	adate=`{seconds $adate}
+	files=`$nl{patch -np1 < $diffpath}
+	if(! git/walk -q $files){
+		>[1=2] {
+			echo patch would clobber files:
+			git/walk $files
+			exit clobber
+		}
+	}
+	echo applying $msg | sed 1q
+	if(! files=`$nl{patch -p1 < $diffpath})
+		die 'patch failed'
+	for(f in $files){
+		if(test -e $f)
+			git/add $f
+		if not
+			git/add -r $f
+	}
+	git/walk -fRMA $files
+	if(~ $#nocommit 0){
+		if(hash=`{git/save -n $aname -e $amail -N $name -E $email -m $msg -d $adate $parents $files}){
+			echo $hash > $refpath
+			for(f in $files)
+				echo T NOQID 0 $f >> .git/INDEX9
+		}
+	}
+	exit ''
+}
+	
 
 fn apply @{
 	git/fs
@@ -23,10 +53,32 @@
 	if not
 		die 'invalid branch:' $branch
 	awk '
+	function doapply(){
+		if(aname == "" || amail == "" || date == "" || gotmsg == "")
+			exit("missing headers");
+		printf "%s", aname > "/env/aname"
+		printf "%s", amail > "/env/amail"
+		printf "%s", date > "/env/adate"
+		if(system("rc -c apply1") != 0)
+			exit("patch failed");
+		close("/env/aname")
+		close("/env/amail")
+		close("/env/adate")
+		close(ENVIRON["diffpath"])
+		applied = 1
+	}
 	BEGIN{
 		state="headers"
 	}
-	state=="headers" && /^From:/ {
+	state=="diff" && !/^[-+ @]|^diff|^$/{
+		state="footers";
+		doapply();
+	}
+	state=="footers" && /^⑨$/{
+		state="headers"
+		next
+	}
+	state=="headers" && /^[fF]rom:/ {
 		sub(/^From:[ \t]*/, "", $0);
 		aname=$0;
 		amail=$0;
@@ -34,7 +86,7 @@
 		sub(/^[^<]*</, "", amail);
 		sub(/>[^>]*$/, "", amail);
 	}
-	state=="headers" && /^Date:/{
+	state=="headers" && /^[Dd]ate:/{
 		sub(/^Date:[ \t]*/, "", $0)
 		date=$0
 	}
@@ -48,6 +100,7 @@
 	}
 	(state=="headers" || state=="body") && (/^diff / || /^---( |$)/){
 		state="diff"
+		next
 	}
 	state=="body" && /^[ 	]*$/ {
 		empty=1
@@ -64,45 +117,11 @@
 		print > ENVIRON["diffpath"]
 	}
 	END{
-		if(state != "diff")
-			exit("malformed patch: " state);
-		if(aname == "" || amail == "" || date == "" || gotmsg == "")
-			exit("missing headers");
-		printf "%s", aname > "/env/aname"
-		printf "%s", amail > "/env/amail"
-		printf "%s", date > "/env/date"
-	}
-	' || die 'could not import:' $status
-
-	# force re-reading env
-	rc -c '
-		date=`{seconds $date}
-		files=`$nl{patch -np1 < $diffpath}
-		if(! git/walk -q $files){
-			>[1=2] {
-				echo patch would clobber files:
-				git/walk $files
-				exit clobber
-			}
+		if(!failed && state == "diff" && doapply() != 0){
+			print "unable to apply patch" > "/fd/2"
+			exit("mispatch")
 		}
-		echo applying $msg | sed 1q
-		if(! files=`$nl{patch -p1 < $diffpath})
-			die ''patch failed''
-		for(f in $files){
-			if(test -e $f)
-				git/add $f
-			if not
-				git/add -r $f
-		}
-		git/walk -fRMA $files
-		if(~ $#nocommit 0){
-			if(hash=`{git/save -n $aname -e $amail -N $name -E $email -m $msg -d $date $parents $files}){
-				echo $hash > $refpath
-				for(f in $files)
-					echo T NOQID 0 $f >> .git/INDEX9
-			}
-		}
-		status=''''
+	}
 	'
 }
 
--