ossp-pkg/svs/svs.sh
#!/bin/sh
##
## OSSP svs -- Stupid/Silly/Simple Versioning System
## Copyright (c) 2003-2009 Ralf S. Engelschall <rse@engelschall.com>
## Copyright (c) 2003-2009 The OSSP Project <http://www.ossp.org/>
##
## This file is part of OSSP svs, a stupid/silly/simple versioning
## system which can found at http://www.ossp.org/pkg/tool/svs/
##
## Permission to use, copy, modify, and distribute this software for
## any purpose with or without fee is hereby granted, provided that
## the above copyright notice and this permission notice appear in all
## copies.
##
## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
## svs.sh: program (language: Bourne Shell)
##
# check command line
if [ $# -eq 0 ]; then
echo "Usage: svs vi <file> [...]"
echo "Usage: svs diff [<file>|<dir> [...]]"
echo "Usage: svs backout [<file>|<dir> [...]]"
echo "Usage: svs status [<file>|<dir> [...]]"
exit 1
fi
# helper function for portable creating a file difference
do_diff () {
diff -U3 "$1" "$2" 2>/dev/null
if [ $? -gt 1 ]; then
diff -u "$1" "$2" 2>/dev/null
if [ $? -gt 1 ]; then
diff -C3 "$1" "$2" 2>/dev/null
if [ $? -gt 1 ]; then
diff "$1" "$2"
fi
fi
fi
}
# a newline character
NL='
'
# dispatch into commands
cmd="$1"
shift
case "$cmd" in
v|vi|vim | e|em|ema|emac|emacs )
##
## EDIT ONE OR MORE FILES
##
# iterate over all files
for file in "$@"; do
# preserve original file
if [ ! -f "$file.orig" ]; then
cp -p "$file" "$file.orig"
orig=new
else
orig=old
fi
# edit file
chmod u+w "$file"
if [ ".${EDITOR-vi}" = .vim -a -f "$file.rej" ]; then
${EDITOR-vi} -o2 "$file" "$file.rej"
else
${EDITOR-vi} "$file"
fi
# check for editing results
if cmp "$file.orig" "$file" >/dev/null 2>&1; then
if [ ".$orig" = .new ]; then
echo "svs: no changes made (keeping original)"
else
echo "svs: changes reversed (restoring original)"
fi
cp -p "$file.orig" "$file"
rm -f "$file.orig"
else
echo "svs: changes made (preserving original)"
if [ -f "$file.rej" ]; then
rm -f "$file.rej"
fi
fi
done
;;
d|di|dif|diff )
##
## GENERATE PATCHING DIFFERENCE
##
# determine file list
if [ $# -eq 0 ]; then
set -- .
fi
files=""
for file in "$@"; do
if [ -d "$file" ]; then
OIFS=$IFS; IFS=$NL
for f in `find "$file" -type f -name "*.orig" -print | sort`; do
files="$files \"$f\""
done
IFS=$OIFS
elif [ -f "$file" ]; then
files="$files \"$file\""
else
echo "svs:ERROR: \"$file\" neither regular file nor directory" 1>&2
exit 1
fi
done
# generate patch
eval set -- $files
for file; do
file=`echo "$file" | sed -e 's;^\./;;' -e 's;/\./;/;g' -e 's;\([^/][^/]*\)/\.\.;;g' -e 's;//*;/;g'`
orig=`echo "$file" | sed -e 's;\.orig$;;' -e 's;$;.orig;'`
edit=`echo "$file" | sed -e 's;\.orig$;;'`
if [ ! -f "$orig" ]; then
echo "svs:WARNING: original file \"$orig\" not found" 1>&2
continue
fi
if [ ! -f "$edit" ]; then
# special case: removed file
echo "Index: $edit"
do_diff "$orig" /dev/null | sed -e "1s/^--- $orig/--- $edit/"
elif [ ! -r "$orig" ] && [ ! -s "$orig" ]; then
# special case: new file
echo "Index: $edit"
do_diff /dev/null "$edit"
else
# regular case: edited file
if cmp "$orig" "$edit" >/dev/null 2>&1; then
:
else
echo "Index: $edit"
do_diff "$orig" "$edit"
fi
fi
done
;;
b|ba|bac|back|backo|backou|backout )
##
## BACKOUT EDITING CHANGES
##
# determine file list
if [ $# -eq 0 ]; then
set -- .
fi
files=""
for file in "$@"; do
if [ -d "$file" ]; then
OIFS=$IFS; IFS=$NL
for f in `find "$file" -type f -name "*.orig" -print | sort`; do
files="$files \"$f\""
done
IFS=$OIFS
elif [ -f "$file" ]; then
files="$files \"$file\""
else
echo "svs:ERROR: \"$file\" neither regular file nor directory" 1>&2
exit 1
fi
done
# backout changes
eval set -- $files
for file; do
file=`echo "$file" | sed -e 's;^\./;;' -e 's;/\./;/;g' -e 's;\([^/][^/]*\)/\.\.;;g' -e 's;//*;/;g'`
orig=`echo "$file" | sed -e 's;\.orig$;;' -e 's;$;.orig;'`
edit=`echo "$file" | sed -e 's;\.orig$;;'`
if [ ! -f "$orig" ]; then
echo "svs:WARNING: original file \"$orig\" not found" 1>&2
continue
fi
echo "svs: backing out changes to \"$edit\""
if [ ! -f "$edit" ]; then
# special case: removed file
cp -p "$orig" "$edit"
rm -f "$orig"
elif [ ! -r "$orig" ] && [ ! -s "$orig" ]; then
# special case: new file
chmod u+w "$orig"
rm -f "$orig"
rm -f "$edit"
else
# regular case: edited file
cp -p "$orig" "$edit"
rm -f "$orig"
fi
done
;;
s|st|sta|stat|statu|status )
##
## CHANGE STATUS
##
# determine file list
if [ $# -eq 0 ]; then
set -- .
fi
files=""
for file in "$@"; do
if [ -d "$file" ]; then
OIFS=$IFS; IFS=$NL
for f in `find "$file" -type f \( -name "*.orig" -or -name "*.rej" \) -print | sort`; do
base=`echo "$f" | sed -e 's;\.orig$;;' -e 's;\.rej$;;'`
if [ ".$f" = ".$base.orig" ] && [ -f "$base.orig" ] && [ -f "$base.rej" ]; then
continue
fi
files="$files \"$f\""
done
IFS=$OIFS
elif [ -f "$file" ]; then
files="$files \"$file\""
else
echo "svs:ERROR: \"$file\" neither regular file nor directory" 1>&2
exit 1
fi
done
# show status on files
eval set -- $files
for file; do
file=`echo "$file" | sed -e 's;^\./;;' -e 's;/\./;/;g' -e 's;\([^/][^/]*\)/\.\.;;g' -e 's;//*;/;g'`
base=`echo "$file" | sed -e 's;\.orig$;;' -e 's;\.rej$;;'`
prefix="?"
case "$file" in
*.orig ) prefix="M" ;;
*.rej ) prefix="C" ;;
esac
echo "$prefix $base"
done
;;
* )
echo "svs:ERROR: invalid command \"$cmd\"" 1>&2
exit 1
;;
esac