shithub: riscv

ref: d1cebf608b05e45b148108ac6c16ae94f6862097
dir: /sys/src/cmd/git/import/

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

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


fn apply @{
	git/fs
	amail=''
	aname=''
	msg=''
	whoami
	parents='-p'^`{git/query HEAD}
	branch=`{git/branch}
	if(test -e $gitfs/branch/$branch/tree)
		refpath=.git/refs/$branch
	if not if(test -e $gitfs/object/$branch/tree)
		refpath=.git/HEAD
	if not
		die 'invalid branch:' $branch
	awk '
	BEGIN{
		state="headers"
	}
	state=="headers" && /^From:/ {
		sub(/^From:[ \t]*/, "", $0);
		aname=$0;
		amail=$0;
		sub(/[ \t]*<.*$/, "", aname);
		sub(/^[^<]*</, "", amail);
		sub(/>[^>]*$/, "", amail);
	}
	state=="headers" && /^Date:/{
		sub(/^Date:[ \t]*/, "", $0)
		date=$0
	}
	state=="headers" && /^Subject:/{
		sub(/^Subject:[ \t]*(\[[^\]]*\][ \t]*)*/, "", $0);
		gotmsg = 1
		print > "/env/msg"
	}
	state=="headers" && /^$/ {
		state="body"
	}
	(state=="headers" || state=="body") && (/^diff / || /^---( |$)/){
		state="diff"
	}
	state=="body" && /^[ 	]*$/ {
		empty=1
		next
	}
	state=="body" {
		if(empty)
			printf "\n" > "/env/msg"
		empty=0
		sub(/[ 	]+$/, "")
		print > "/env/msg"
	}
	state=="diff" {
		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
			}
		}
		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
				rm -f .git/index9/removed/$files
			}
		}
		status=''''
	'
}

gitup

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

patches=(/fd/0)
if(! ~ $#* 0)
	patches=`{cleanname -d $gitrel $*}
for(p in $patches){
	# upas serves the decoded header and body separately,
	# so we cat them together when applying a upas message.
	#
	# this allows mime-encoded or line-wrapped patches.
	if(test -d $p && test -f $p/header && test -f $p/body)
		{{cat $p/header; echo; cat $p/body} | apply} || die $status
	if not
		apply < $p
}
exit ''