#!/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 ''
#!/bin/rc
rfork 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=$1
email=$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 source
source = $SD
if(! ~ $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=$changed
changed=()
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=$removed
removed=()
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/$patch
fn 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 $d
echo $removed | tr ' ' \xa > $d/removed
echo $email >$d/email
touch $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/files
while(! ~ $#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/apatch
echo $patch >> /dist/apatch/applied
echo $d locally applied.
fn sigexit sigint
exit ''