Git: git9

git9 @ dd4015a1b71b38a94586d538bcd48debc3dab7d6

#!/bin/rc
rfork ne
. /sys/lib/git/common.rc

diffpath=/tmp/gitimport.$pid.diff
fn sigexit {
	rm -f $diffpath
}

fn apply @{
	git/fs
	email=''
	name=''
	msg=''
	parents='-p'^`{git/query HEAD}
	branch=`{git/branch}
	if(test -e /mnt/git/branch/$branch/tree)
		refpath=.git/refs/$branch
	if not if(test -e /mnt/git/object/$branch/tree)
		refpath=.git/HEAD
	if not
		die 'invalid branch:' $branch
	awk '
	BEGIN{
		state="headers"
	}
	state=="headers" && /^From:/ {
		sub(/^From:[ \t]*/, "", $0);
		name=$0;
		email=$0;
		sub(/[ \t]*<.*$/, "", name);
		sub(/.*</, "", email);
		sub(/>/, "", email);
	}
	state=="headers" && /^Date:/{
		sub(/^Date:[ \t]*/, "", $0)
		date=$0
	}
	state=="headers" && /^Subject:/{
		sub(/^Subject:[ \t]*(\[PATCH( [0-9]+\/[0-9]+)?\])*[ \t]*/, "", $0);
		gotmsg = 1
		print > "/env/msg"
	}
	state=="headers" && /^$/ {
		state="body"
		next
	}
	(state=="headers" || state=="body") && (/^diff/ || /^---[ 	]*$/){
		state="diff"
	}
	state=="body" {
		print > "/env/msg"
	}
	state=="diff" {
		print > ENVIRON["diffpath"]
	}
	END{
		if(state != "diff")
			exit("malformed patch: " state);
		if(name == "" || email == "" || date == "" || gotmsg == "")
			exit("missing headers");
		printf "%s", name > "/env/name"
		printf "%s", email > "/env/email"
		printf "%s", date > "/env/date"
	}
	' || die 'could not import:' $status

	# force re-reading env
	rc -c '
		echo applying $msg | sed 1q
		date=`{seconds $date}
		if(! files=`$nl{ape/patch -Ep1 < $diffpath | grep ''^patching file'' | sed ''s/^patching file `(.*)''''/\1/''})
			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){
			hash=`{git/save -n $name -e $email -m $msg -d $date $parents $files}
			echo $hash > $refpath
		}
		status=''''
	'
}

gitup

flagfmt='n:nocommit'; args='file ...'
eval `''{aux/getflags $*} || exec aux/usage

patches=(/fd/0)
if(! ~ $#* 0)
	patches=$*
for(f in $patches)
	apply < $f || die $status 
exit ''