#!/bin/bash
SVN=/usr/bin/svn
ACTION=""
DEV_PROP="dir:devices"
SYM_PROP="dir:symlinks"
FILE_PROP="file:permissions"
TMPFILE=/tmp/asvn.tmp.$$
TMPFILE1=/tmp/asvn.tmp1.$$
TMPFILE2=/tmp/asvn.tmp2.$$
PCWD=`/bin/pwd`
SKIPSVN='\( -name .svn -prune -false \)'
PRINTDETAILS="-printf \"file='%p' mode=%m user=%u(%U) group=%g(%G)\n\""
trap cleanup 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
function cleanup()
{
rm -f $TMPFILE $TMPFILE1 $TMPFILE2
}
function basedirname()
{
refname="$1"
dir="`dirname \"$2\"`"
ref="`expr \"$dir\" : \"$refname/\(.*\)\"`"
if [ -z "$ref" ]
then
echo .
else
echo $ref
fi
}
function addignorefile()
{
file="`basename \"$1\"`"
dir="`dirname \"$1\"`"
efile="`echo $file |sed -e 's!\([\[\(\$]\)!\\\\\1!g'`"
gefile="`echo $efile |sed -e 's!\(\\\\\)!\\\\\\\\\1!g'`"
if ! ($SVN propget svn:ignore "$dir" | grep -q "^$gefile\$")
then
$SVN propget svn:ignore "$dir" |sed -e '/^$/d' >$TMPFILE2
echo "$efile" >>$TMPFILE2
$SVN propset svn:ignore -F $TMPFILE2 "$dir"
echo setting ignore
fi
}
function deleteignorefile()
{
file="`basename \"$1\"`"
dir="`dirname \"$1\"`"
efile="`echo $file |sed -e 's!\([\[\(\$]\)!\\\\\1!g'`"
gefile="`echo $efile |sed -e 's!\(\\\\\)!\\\\\\\\\1!g'`"
echo "deleting ignore setting for '$file'"
if ($SVN propget svn:ignore "$dir" | grep -q "^$gefile\$")
then
$SVN propget svn:ignore "$dir" |sed -e '/^$/d' |grep -v "^$gefile\$" >$TMPFILE2
$SVN propset svn:ignore -F $TMPFILE2 "$dir"
fi
}
function recorddirinfo
{
eval "find $PCWD $SKIPSVN -o \( -type d ! -name .svn -print \)" |while read dirlist
do
updatedirsymlinks $1 "$dirlist"
updatedirdevices $1 "$dirlist"
done
}
function updatedirdevices()
{
CHECKIN=false
if [ "$1" = "-ci" ]
then
CHECKIN=true
shift
fi
dir="$1"
echo checking $dir for devices
find "$dir" \( \( -type b -o -type c -o -type p \) -print \) -o -type d ! -name "`basename \"$dir\"`" -prune | while read file
do
echo -n `find "$file" -printf "file='%f' mode=%m user=%u(%U) group=%g(%G)"`
[ -b "$file" ] && echo -n ' type=b'
[ -c "$file" ] && echo -n ' type=c'
[ -p "$file" ] && echo ' type=p'
if [ -b "$file" -o -c "$file" ]
then
ls -l "$file" |
sed -e 's/^[-lcpbrdwxXstugoTS]* *[0-9] [^ ]* *[^ ]* *\([0-9]*\), *\([0-9]*\) .*/ major=\1 minor=\2/'
fi
addignorefile "$file"
done | sort >$TMPFILE
$SVN propget $DEV_PROP "$dir" >$TMPFILE1
if /usr/bin/cmp $TMPFILE1 $TMPFILE >/dev/null
then
return
fi
if [ -s $TMPFILE ]
then
if [ "$CHECKIN" = "true" ]
then
$SVN propset $DEV_PROP "$dir" -F $TMPFILE
else
cat $TMPFILE |while read line
do
file="`expr \"$line\" : \"file='\(.*\)' mode\"`"
if ! grep -q "file='$file'" $TMPFILE1
then
rm "$file"
deleteignorefile "$file"
fi
done
fi
else
if [ "$CHECKIN" = "true" ]
then
$SVN propdel $DEV_PROP "$dir"
fi
fi
if [ "$CHECKIN" != "true" ]
then
cat $TMPFILE1 |while read info
do
[ -z "$info" ] && continue
grep -q "$info" $TMPFILE && continue file="`expr \"$info\" : \"file='\(.*\)' \"`"
mode=`expr "$info" : ".*' mode=\([0-9]*\) "`
user=`expr "$info" : ".* user=\([^(]*\)("`
uid=`expr "$info" : ".* user=[^(]*(\([0-9]*\) "`
group=`expr "$info" : ".* group=\([^(]*\)("`
gid=`expr "$info" : ".* group=[^(]*(\([0-9]*\) "`
type=`expr "$info" : ".* type=\(.\)"`
major=`expr "$info" : ".* major=\([0-9]*\)"`
minor=`expr "$info" : ".* minor=\([0-9]*\)"`
rm -f "$dir/$file"
mknod --mode=$mode "$dir/$file" $type $major $minor
chown $user:$group "$dir/$file"
addignorefile "$dir/$file"
done
fi
}
function updatedirsymlinks()
{
CHECKIN=false
if [ "$1" = "-ci" ]
then
CHECKIN=true
shift
fi
dir="$1"
echo checking $dir for symlinks
cp /dev/null $TMPFILE
find "$dir" \( -type l -printf "file='%f' dest='%l'\n" \) -o -type d ! -name "`basename \"$dir\"`" -prune |
sort >$TMPFILE
cat $TMPFILE |while read line
do
file="`expr \"$line\" : \"file='\(.*\)' dest\"`"
addignorefile "$dir/$file"
done
$SVN propget $SYM_PROP "$dir" >$TMPFILE1
if cmp $TMPFILE1 $TMPFILE >/dev/null
then
return
fi
if [ -s $TMPFILE ]
then
if [ "$CHECKIN" = "true" ]
then
$SVN propset $SYM_PROP "$dir" -F $TMPFILE
else
cat $TMPFILE |while read line
do
file="`expr \"$line\" : \"file='\(.*\)' dest\"`"
efile="`echo \"$file\" |sed -e 's!\([\[\(\$]\)!\\\\\1!g'`"
if ! grep -q "file='$efile'" $TMPFILE1
then
rm "$dir/$file"
deleteignorefile "$dir/$file"
fi
done
fi
else
if [ "$CHECKIN" = "true" ]
then
$SVN propdel $SYM_PROP "$dir"
fi
fi
if [ "$CHECKIN" != "true" ]
then
cat $TMPFILE1 |while read info
do
[ -z "$info" ] && continue
file="`expr \"$info\" : \"file='\(.*\)' dest\"`"
dest="`expr \"$info\" : \".*' dest='\(.*\)'$\"`"
if [ -L "$dir/$file" ]
then
[ "`find \"$dir/$file\" -printf '%l'`" = "$dest" ] && continue
fi
rm -f "$dir/$file"
ln -s "$dest" "$dir/$file"
done
fi
}
function recordpermissions()
{
CHECKIN=false
if [ "$1" = "-ci" ]
then
CHECKIN=true
shift
fi
cp /dev/null $TMPFILE
eval "find $PCWD $SKIPSVN -o \( \( -type d ! -name .svn \) -o -type f \) $PRINTDETAILS" | while read info
do
device=`expr "$info" : "file='\(.*\)' mode"`
info=`expr "$info" : "file='.*' \(mode.*\)"`
if [ "$PCWD" = "$device" ]
then
dir="."
file=""
else
dir="`basedirname \"$PCWD\" \"$device\"`"
file="`basename \"$device\"`"
fi
if [ "`$SVN propget $FILE_PROP \"$dir/$file\"`" != "$info" ]
then
if [ "$CHECKIN" = "true" ]
then
$SVN propset $FILE_PROP "$info" "$dir/$file"
else
info=`$SVN propget $FILE_PROP "$dir/$file"`
mode=`expr "$info" : "mode=\([0-9]*\) "`
user=`expr "$info" : ".* user=\([^(]*\)("`
uid=`expr "$info" : ".* user=[^(]*(\([0-9]*\) "`
group=`expr "$info" : ".* group=\([^(]*\)("`
gid=`expr "$info" : ".* group=[^(]*(\([0-9]*\) "`
if [ "$user" = "" -o "$group" = "" -o "$mode" = "" ]
then
echo "property $FILE_PROP not set for $dir/$file"
else
chown $user:$group "$dir/$file"
chmod $mode "$dir/$file"
fi
fi
fi
done
}
function pre_checkin()
{
echo this is the pre checkin process
recorddirinfo -ci
recordpermissions -ci
}
function post_checkout()
{
echo this is the post checkout process
if [ "$CHDIR" = "true" ]
then
shift $(($ cd "`basename \"$1\"`"
PCWD="$PCWD/`basename \"$1\"`"
fi
recorddirinfo
recordpermissions
}
CHDIR=false
case "$1" in
checkout|co) CHDIR=true; ACTION="post";;
commit|ci) ACTION="pre";;
switch|sw) ACTION="post";;
update|up) ACTION="post";;
*);;
esac
[ "$ACTION" = "pre" ] && pre_checkin $@
$SVN $@
[ $? = 0 -a "$ACTION" = "post" ] && post_checkout $@
cleanup