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=''''
+ }
'
}
--
⑨