Jani Averbach wrote:
>Would you like to post it again as an attachment? That would be
>marvelous.
>
Done. The only difference between this version and the original is that
it doesn't generate an error message if a file didn't have a
file:permissions property (the actual error was from the chmod and chown
calls).
>
>Moreover, I am interested in hearing what kind of name you would
>choose for properties today if your hands were not bound?
>
If I was rewriting the script now I would put the properties under the
"asvn" name space, so it was obvious that were all associated with the
script. However if there our thoughts of using the same properties in
other tools then possibly a different name space may be more
appropriate, but then again I like the term Archive SVN so maybe asvn
isn't so bad :->
>
>Secondly, in the original thread, Sander was willing to put your
>script in /contrib, so this time that would even happen, if there aren't
>any concerns among other developers. =)
>
Since posting the script I've had a few inquiries from people wanting to
use it so I think there is some demand for something like this.
>
>BR, Jani
>
>
>
Ross
#!/bin/bash
#-------------------------------------------------------------------------
# Author: Ross Mark (rossm@controllingedge.com.au)
# Date: Tue Mar 11 10:02:57 EST 2003
#
# Document Id: 104.733.737
#
# Copyright (C) 2003 Controlling Edge Pty Ltd
#
#-------------------------------------------------------------------------
#
# Description:
# Archive SVN (asvn) will allow the recording of file types not
# normally handled by svn. Currently this includes devices,
# symlinks and file ownership/permissions.
#
# Every file and directory has a 'file:permissions' property set and
# every directory has a 'dir:devices' and 'dir:symlinks' for
# recording the extra information.
#
# Run this script instead of svn with the normal svn arguments.
#
# This script worked for me yesterday on my machine and I hope it will
# continue to work tomorrow. If you run this program then
# risk and blame are yours.
#
#-------------------------------------------------------------------------
SVN=/usr/local/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
}
#
# Modifies TMPFILE2
#
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
#cat $TMPFILE2 >&2
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"
#cat $TMPFILE2 >&2
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
#
# Obtain the list of devices in this directory
#
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
# In this case file is the full path.
addignorefile "$file"
done | sort >$TMPFILE
#
# Obtain the currently defined devices
#
$SVN propget $DEV_PROP $dir >$TMPFILE1
#
# If the two list are the same then there is nothing to do.
#
if /usr/bin/cmp $TMPFILE1 $TMPFILE >/dev/null
then
return
fi
if [ -s $TMPFILE ]
then
# There are devices in this directory
if [ "$CHECKIN" = "true" ]
then
# Add the current devices to the property
$SVN propset $DEV_PROP $dir -F $TMPFILE
else
# Delete all the unwanted devices ie not in TMPFILE1
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
# There are no devices in this directory
if [ "$CHECKIN" = "true" ]
then
$SVN propdel $DEV_PROP $dir
fi
fi
#
# If we are not a checkin then make sure all the devices are defined
#
if [ "$CHECKIN" != "true" ]
then
cat $TMPFILE1 |while read info
do
#echo info = $info
[ -z "$info" ] && continue
grep -q "$info" $TMPFILE && continue # This line still matches
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]*\)"`
#
# This file is either missing or wrong
# Delete the old and create it anew.
#
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
#
# Obtain the list of symlinks in this directory
#
find "$dir" \( -type l -printf "file='%f' dest='%l'\n" \) -o -type d ! -name "`basename $dir`" -prune |
sort >$TMPFILE
#
# Make sure all the symlinks are being ignored.
#
cat $TMPFILE |while read line
do
file=`expr "$line" : "file='\(.*\)' dest"`
addignorefile "$dir/$file"
done
#
# Obtain the currently defined symlinks
#
$SVN propget $SYM_PROP $dir >$TMPFILE1
#
# If the two list are the same then there is nothing to do.
#
if cmp $TMPFILE1 $TMPFILE >/dev/null
then
return
fi
if [ -s $TMPFILE ]
then
# There are symlinks in this directory
if [ "$CHECKIN" = "true" ]
then
# Add the current symlinks to the property
$SVN propset $SYM_PROP $dir -F $TMPFILE
else
# Delete all the unwanted symlinks
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
# There are no symlinks in this directory
if [ "$CHECKIN" = "true" ]
then
$SVN propdel $SYM_PROP $dir
fi
fi
#
# If we are not a checkin then make sure all the symlinks are defined
#
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
# Find all the directories and files
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
# see if the properties have changed.
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 $(($# -1))
cd $1
PCWD="$PCWD/$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
#
# vim: set ai ts=8 sw=4
#
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Thu Mar 18 04:26:16 2004