175 lines · 3.2 KB · Text
RawDownload
#!/bin/rcrfork e . /rc/bin/apatch/defs fn xchmod { 	chmod $* >[2]/dev/null} fn validate{	if(! echo $2 | grep -s $3){		echo bad $1: $3 only >[1=2];		exit usage	}} flagfmt='f,v,y,Y ndays'args='name email file ... [<description]'if(! ifs=() eval `{aux/getflags $*} || ~ $#* 0 1 2){	aux/usage	exit usage}~ $flagf 1 && force=y || force=n~ $flagY '' || flagy=$flagY patch=$1email=$2* = $*(3-) validate 'patch name' $patch '^[a-zA-Z][a-z_0-9.\-]+$'validate email $email '^(-|[A-Za-z0-9.\-+]+@[A-Za-z0-9.\-+]+)$' mountfs # define our sourcesource = $SDif(! ~ $flagy ''){	9fs dump || fail 9fs	source=`{yesterday -n $flagy /}	test -d $source || fail no yesterday} rooted=()p=`{pwd}for(i)	~ $i /* && rooted=($rooted $i) || rooted=($rooted $p/$i) removed=()changed=() for(i in `{cleanname $rooted})	test -e $i && changed=($changed $i) || removed=($removed $i)if(! ~ $#changed 0)	changed=`{find $changed || fail file collection errors}if(echo $changed | grep -s '(^[01258769kqv]\.)|(\.a?[01258769kqv]$)'){	echo there are object or library files. clean it first >[1=2]	exit fail}c=$changedchanged=()for(i in $c){	if(test -d $i)		changed = ($changed $i)	if not{		if(cmp -s $i $source/$i)			echo unchanged: $i >[1=2]		if not			changed = ($changed $i)	}}c=() r=$removedremoved=()for(i in $r){	if(test -e $source/$i)		removed=($removed $i)	if not		echo not removed: $i >[1=2]} if(~ $#changed 0 && ~ $#removed 0)	fail patch not created: nothing changed, nothing added, nothing deleted if(~ $flagv 1){	echo removed	echo -n '	'	echo $removed | sed 's: :\n	:g'	echo changed	echo -n '	'	echo $changed | sed 's: :\n	:g'} ~ $flagv 1 && echo patchd $PD/$patch >[1=2] if(test -e $PD/$patch){	if(~ $force n){		echo patch $patch already exists.		echo Use flag -f to force and redefine it		exit fail	} >[1=2]	for(i in `{seq 1 100}){		if(! test -e $PD/$patch.$i){			patch = $patch.$i			break		}	}	echo new name: $patch>[1=2]}d=$PD/$patchfn sigexit sigint{	echo removing $PD/$patch >[1=2]	rm -rf $PD/$patch}if(! mkdir $d){	echo mkdir $d failed >[1=2]	exit mkdir} xchmod o-w $decho $removed | tr ' ' \xa > $d/removedecho $email >$d/emailtouch $d/^(readme files) fn genu {	echo $changed | tr ' ' \xa |	awk '{		base = $0		sub("/$", "", base)		# already have cleanname		sub(".*/", "", base)		i = length(a[base]);		if(i > 0)			print $0 "\t" base "." i		else			print $0 "\t" base		a[base]++;	}'} ~ $flagv 1 && genu uniqlist = `{genu}genu >> $d/fileswhile(! ~ $#uniqlist 0){	file=$uniqlist(1)	base=$uniqlist(2)	uniqlist = $uniqlist(3-)	test -e $SD/$file && cpfile $SD/$file $d/$base.orig	cpfile $file $d/$base	|| fail cpfile # we need to back out } @{builtin cd $d && xchmod ug+rw * && xchmod a+r *} if(~ `{cat /proc/$pid/fd | awk 'NR==2{print $NF}'} */dev/cons && test -w /dev/consctl){	>/dev/consctl {		echo holdon		cat >$d/readme	}}if not	cat >$d/readme if(! test -s $d/readme)	fail no description given # add the patch name to the applied list, so that it is not pull# when it's $patch/Applied in the future.must mkdir -p /dist/apatchecho $patch >> /dist/apatch/appliedecho $d locally applied. fn sigexit sigint exit ''