[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Creating a new working copy in an existing directory (/etc)

From: Ross Mark <rossm_at_controllingedge.com.au>
Date: 2003-03-31 03:32:51 CEST

Jani Averbach wrote:

>On 30 Mar 2003, Nicolas Bonnefon wrote:
>
>
>>>In my setup, there is also a file where is pretty printed my etc's
>>>symlinks layout, and that file is also under version control.
>>>
>>>
>>Fine, do you have a script to generate this file?
>>
>>
>
>Yep, shameless find+sed+sort. My ls generates output like that:
>$ ls -l /etc/passwd
>-rw-r--r-- 1 root root 1929 2003-03-11 23:16 /etc/passwd
>
>And here is the script:
>
>#!/bin/sh
>etc_links=/etc/etc_links.dat
>
>find /etc -type l -exec ls -l {} \; | \
> sed 's/.*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9] //'| \
> sort > $etc_links
>
>
>Does anybody know how I would tell to gnu's ls that it should print out
>only reference info of the symlink, and nothing more? Or is the 'symlinks'
>the way to go?
>
>
You were close before, try 'find /etc/ -type l -printf "%l\n"'

>BR, Jani
>
>

While I don't think it is exactly what you are after I've attached a
wrapper script that I use around svn that will allows full file systems
to be stored, including symlinks, devices, user and group id plus
permissions. Of course this will only run under *nix and there may be
command problems with the different variants out there. I run it under
RH7.2 and use it to keep file systems systems for some embedded work
under revision control. It is quite possible that there will be cases
that this script does not work. I basically was only built to satisfy my
cases for small limited file systems.

The idea is that when you do a ci, co or update run this 'asvn'

The only problem that I know of is that if you try run 'depmod' and
/lib/modules is under svn controll there are a lot of problems as depmod
tries to obtain info on all the files under the .svn directories.

Hope some one might find this of use.

Ross

#!/bin/bash
#-------------------------------------------------------------------------
#ident $Header$
#-------------------------------------------------------------------------
#
# $Source$
# $Revision$
# $Machine$
#
# Author: Ross Mark
# Date: Tue Mar 11 10:02:57 EST 2003
#
# Document Id: 104.733.737
#
# $Locker$
# $State$
# $Date$
#
# Copyright (C) 2003 Controlling Edge Pty Ltd
#
#-------------------------------------------------------------------------
#
# Description:
#
#
#-------------------------------------------------------------------------
#
# $Log$
#
#-------------------------------------------------------------------------
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]*\) "`
                chown $user:$group $dir/$file
                chmod $mode $dir/$file
            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

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Mar 31 03:33:42 2003

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.