--- asvn.org 2006-10-16 11:24:15.000000000 -0500 +++ new-asvn 2006-10-30 09:48:53.000000000 -0600 @@ -34,6 +34,26 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +#------------------------------------------------------------------------- +# +# Modified 10/12/2006 by Scott L. Miller (scott.l.miller@gmail.com) +# +# Commented out the code dealing with symbolic links since subversion +# now has that capability built in. +# +# Eliminated the need to traverse the directory tree more than once. +# It now does a single pass, checking each file for device type and +# file permissions. +# +# Modified some of the 'find' calls as needed to eliminate processing +# entire subdirectory trees that are not under subversion control. +# +# Changed indentation to follow a consistent style. +# +# FURTHER THOUGHTS, AND SUGGESTIONS: Use a subversion status call +# to directly collect the files that we need to process for device +# and permission properties, rather than recursing through the +# directory tree ourselves. # #------------------------------------------------------------------------- SVN=/usr/local/bin/svn @@ -58,7 +78,7 @@ function basedirname() { refname="$1" - dir="`dirname $2`" + dir="`dirname \"$2\"`" ref=`expr "$dir" : "$refname/\(.*\)"` if [ -z "$ref" ] then @@ -69,46 +89,59 @@ } # +# Escapes all "special" filename characters. SED magic was modified from +# the original found at the website: +# http://elonen.iki.fi/code/misc-notes/remove-duplicate-files/index.html +# +function escapename() +{ + echo "`echo $1 | sed -r 's/([^a-zA-Z0-9./_-])/\\\\\1/g'`" +} + +# # Modifies TMPFILE2 # function addignorefile() { - file=`basename $1` - dir=`dirname $1` + file=`basename "$1"` + dir=`dirname "$1"` - efile="`echo $file |sed -e 's!\([\[\(\$]\)!\\\\\1!g'`" - gefile="`echo $efile |sed -e 's!\(\\\\\)!\\\\\\\\\1!g'`" + efile="`escapename \"$file\"`" + gefile="`echo $efile |sed -e 's!\([\\]\)!\1\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 + $SVN propset svn:ignore -F $TMPFILE2 "$dir" > /dev/null 2>&1 + # 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'`" + file=`basename "$1"` + dir=`dirname "$1"` + + efile="`escapename \"$file\"`" + gefile="`echo $efile |sed -e 's!\([\\]\)!\1\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" + $SVN propset svn:ignore -F $TMPFILE2 "$dir" > /dev/null 2>&1 #cat $TMPFILE2 >&2 fi } function recorddirinfo { - eval "find $PCWD $SKIPSVN -o \( -type d ! -name .svn -print \)" |while read dirlist + find "$PCWD" \( -type d -name .svn -print \) | sed -e 's/\/\.svn//' | while read dirlist do - updatedirsymlinks $1 $dirlist - updatedirdevices $1 $dirlist +# updatedirsymlinks $1 $dirlist + updatedirdevices $1 "$dirlist" + recordpermissions $1 "$dirlist" done } @@ -126,15 +159,17 @@ # # 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 + find "$dir" -maxdepth 1 \( -type b -o -type c -o -type p \) -printf "file='%p' mode=%m user=%u(%U) group=%g(%G)\n" | + sed -r 's#\\#\\\\#g' | sort | while read devinfo 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 ] + file=`expr "$devinfo" : "file='\(.*\)' mode"` + echo -n "$devinfo" + [ -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 | + 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. @@ -145,10 +180,10 @@ # # Obtain the currently defined devices # - $SVN propget $DEV_PROP $dir >$TMPFILE1 + $SVN propget $DEV_PROP "$dir" >$TMPFILE1 # - # If the two list are the same then there is nothing to do. + # If the two lists are the same then there is nothing to do. # if /usr/bin/cmp $TMPFILE1 $TMPFILE >/dev/null then @@ -161,7 +196,7 @@ if [ "$CHECKIN" = "true" ] then # Add the current devices to the property - $SVN propset $DEV_PROP $dir -F $TMPFILE + $SVN propset $DEV_PROP "$dir" -F $TMPFILE else # Delete all the unwanted devices ie not in TMPFILE1 cat $TMPFILE |while read line @@ -169,8 +204,8 @@ file=`expr "$line" : "file='\(.*\)' mode"` if ! grep -q "file='$file'" $TMPFILE1 then - rm $file - deleteignorefile $file + rm "$file" + deleteignorefile "$file" fi done fi @@ -178,7 +213,7 @@ # There are no devices in this directory if [ "$CHECKIN" = "true" ] then - $SVN propdel $DEV_PROP $dir + $SVN propdel $DEV_PROP "$dir" fi fi @@ -205,14 +240,15 @@ # 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 + rm -f "$dir/$file" + mknod --mode=$mode "$dir/$file" $type $major $minor + chown $user:$group "$dir/$file" + addignorefile "$dir/$file" done fi } +# No longer needed. function updatedirsymlinks() { CHECKIN=false @@ -310,27 +346,44 @@ CHECKIN=true shift fi + dir="$1" - # Find all the directories and files + echo checking $dir for permissions cp /dev/null $TMPFILE - eval "find $PCWD $SKIPSVN -o \( \( -type d ! -name .svn \) -o -type f \) $PRINTDETAILS" | while read info + # + # Obtain the list of files and subdirectories in this directory + # We also need to fix the backslash characters before the 'while read' or + # they will get interepreted within the read. + # + find "$dir" -maxdepth 1 \( -type f -o \( -type d ! -name \.svn \) \) -printf "file='%p' mode=%m user=%u(%U) group=%g(%G)\n" | + sed -r 's#\\#\\\\#g' | sort | while read info do - device=`expr "$info" : "file='\(.*\)' mode"` + file=`expr "$info" : "file='\(.*\)' mode"` info=`expr "$info" : "file='.*' \(mode.*\)"` - if [ "$PCWD" = "$device" ] + + if [ "$PCWD" = "$file" ] then dir="." file="" else - dir="`basedirname $PCWD $device`" - file="`basename $device`" + dir="`basedirname \"$PCWD\" \"$file\"`" + file="`basename \"$file\"`" + # All chars except spaces and tabs seem to be handled correctly + # within the double quotes, so we just fix the spaces and tabs + file="`echo \"$file\" | sed -r 's#\([\ \ ]\)#\\\\\1#g'`" fi + + props="`$SVN propget $FILE_PROP \"$dir/$file\"`" + if [ $? -eq 0 ] + then + #file is under svn control + # see if the properties have changed. - if [ "`$SVN propget $FILE_PROP $dir/$file`" != "$info" ] + if [ "$props" != "$info" ] then if [ "$CHECKIN" = "true" ] then - $SVN propset $FILE_PROP "$info" $dir/$file + $SVN propset $FILE_PROP "$info" "$dir/$file" else info=`$SVN propget $FILE_PROP "$dir/$file"` mode=`expr "$info" : "mode=\([0-9]*\) "` @@ -338,15 +391,24 @@ 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" + echo "property $FILE_PROP not set for \"$dir/$file\"" else - chown $user:$group $dir/$file - chmod $mode $dir/$file + echo "changing owner/group mode on \"$dir/$file\"" + chown $user:$group "$dir/$file" + chmod $mode "$dir/$file" fi fi fi + + else + #file is not under svn control + # echo -n "" is just a no-op allowing this else block to exist + echo -n "" + fi + done } @@ -355,7 +417,8 @@ { echo this is the pre checkin process recorddirinfo -ci - recordpermissions -ci +# recordpermissions is called from recorddirinfo now +# recordpermissions -ci } function post_checkout() @@ -368,13 +431,17 @@ PCWD="$PCWD/$1" fi recorddirinfo - recordpermissions +# recordpermissions is called from recorddirinfo now +# recordpermissions } CHDIR=false +DOSVN=true case "$1" in checkout|co) CHDIR=true; ACTION="post";; commit|ci) ACTION="pre";; +import) ACTION="pre";; +prework|pre) DOSVN=false; ACTION="pre";; switch|sw) ACTION="post";; update|up) ACTION="post";; *);; @@ -382,11 +449,15 @@ [ "$ACTION" = "pre" ] && pre_checkin $@ -$SVN $@ +if [ "$DOSVN" = "true" ] +then + echo $SVN "$@" + $SVN "$@" +fi [ $? = 0 -a "$ACTION" = "post" ] && post_checkout $@ cleanup # -# vim: set ai ts=8 sw=4 +# vim:ai:ts=4:sw=4 #