Update the mkdevbranch script for new Trac location, don't clobber existing paths The script has been cleaned up, adjusted to avoid clobbering an SVN path that already exists when running it for a single sprinter login, and run with the new locations for the Trac system. This is a decently huge rewrite of the script. It's pulled a lot of logic into functions, excised the python code into its own file, etc. - Legacy-Id: 19076 Note: SVN reference [19071] has been migrated to Git commit 537b76eb76170d69036999f8a8ef20fd81caca93
230 lines
7 KiB
Bash
Executable file
230 lines
7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
version="0.34"
|
|
program=$(basename $0)
|
|
|
|
NEW="" # If there are more than $NEW % new lines, skip update
|
|
OLD="" # If there are more than $OLD % deleted lines, skip update
|
|
FILE=""
|
|
verbose=""
|
|
silent=""
|
|
|
|
# ----------------------------------------------------------------------
|
|
function usage() {
|
|
cat <<EOF
|
|
NAME
|
|
$program - conditionally update target file.
|
|
|
|
SYNOPSIS
|
|
$program [OPTIONS] FILE
|
|
|
|
DESCRIPTION
|
|
$program reads input from a pipe or file and saves it to a target
|
|
(FILE) if there are changes. If the new content is the same as the
|
|
old, the target is left untouched. By default, the target is also
|
|
left untouched if the new content is empty. There are options to
|
|
also abstain from applying an update if the changes are too large,
|
|
and to back up the previous version.
|
|
|
|
The purpose is to handle files with dynamically generated content in
|
|
such a manner that timestamps don't change if the content doesn't change,
|
|
and mistakes in content generation doesn't unnecessarily propagate to
|
|
the target.
|
|
|
|
OPTIONS
|
|
EOF
|
|
if [ "$(uname)" = "Linux" ]; then
|
|
egrep "^[ ]+[-][A-Za-z| -]+\*?\)[ ]+[A-Za-z].+#" $0 | tr -s "\t|" "\t," | sed -r -e 's/\)[ \t]+([A-Z]+)="\$2"[^#]*#/=\1\t/' -e 's/\)[^#]*#/\t/'
|
|
else
|
|
egrep "^[ ]+[-][A-Za-z| -]+\*?\)[ ]+[A-Za-z].+#" $0 | sed 's/\|.*"\$2"[^#]*#/ /'| sed -E 's/\|.*\)[^#]*#/ /'
|
|
fi
|
|
cat <<EOF
|
|
|
|
AUTHOR
|
|
Henrik Levkowetz <henrik@levkowetz.com>
|
|
EOF
|
|
exit
|
|
}
|
|
|
|
|
|
# ----------------------------------------------------------------------
|
|
function note() {
|
|
if [ -n "$verbose" ]; then
|
|
echo -e "$program: $*"
|
|
fi
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
function warn() {
|
|
[ "$QUIET" ] || echo -e "$program: $*"
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
function err() {
|
|
echo -e "$program: $*" > /dev/stderr
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
function leave() {
|
|
errcode=$1; shift
|
|
if [ "$errcode" -ge "2" ]; then warn "$*"; else note "$*"; fi
|
|
if [ -f "$tempfile" ]; then rm $tempfile; fi
|
|
if [ -f "$difffile" ]; then rm $difffile; fi
|
|
if [ "$errcode" = "1" -a "$RESULT" = "0" ]; then exit 0; else exit $errcode; fi
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Set up error trap
|
|
trap 'leave 127 "$program($LINENO): Command failed with error code $? while processing '$origfile'."' ERR
|
|
|
|
# exit with a message if a command fails
|
|
set -e
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Get any options
|
|
#
|
|
|
|
# Default values
|
|
PAT="\$path\$base.%Y-%m-%d_%H%M"
|
|
RESULT="0"
|
|
QUIET=""
|
|
|
|
# Based on the sample code in /usr/share/doc/util-linux/examples/parse.bash.gz
|
|
if [ "$(uname)" = "Linux" ]; then
|
|
GETOPT_RESULT=$(getopt -o bc:ef:hn:o:p:qrvV --long backup,maxchg:,empty,file:,help,maxnew:,maxold:,prefix:,report,quiet,verbose,version -n "$program" -- "$@")
|
|
else
|
|
GETOPT_RESULT=$(getopt bc:ef:hn:o:p:qrvV "$@")
|
|
fi
|
|
|
|
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
|
|
|
note "GETOPT_RESULT: $GETOPT_RESULT"
|
|
eval set -- "$GETOPT_RESULT"
|
|
|
|
while true ; do
|
|
case "$1" in
|
|
-b|--backup) backup=1; shift ;; # Back up earlier versions by creating a backup file
|
|
-c|--maxchg) CHG="$2"; shift 2 ;; # Limit on percentage of changed lines
|
|
-e|--empty) empty=1; shift ;; # Permit the update to be empty (default: discard)
|
|
-f|--file) FILE="$2"; shift 2 ;; # Read input from FILE instead of standard input
|
|
-h|--help) usage; shift ;; # Show this text and exit
|
|
-n|--maxnew) NEW="$2"; shift 2 ;; # Limit on percentage of new (added) lines
|
|
-o|--maxold) OLD="$2"; shift 2 ;; # Limit on percentage of old (deleted) lines
|
|
-p|--pat*) PAT="$2"; shift 2 ;; # Backup name base ('$path$base.%Y%m%d_%H%M')
|
|
-q|--quiet) QUIET=1; shift;; # Be less verbose
|
|
-r|--result) RESULT=1; shift ;; # Return 1 if update not done
|
|
-v|--verbose) verbose=1; shift ;; # Be more verbose about what's happening
|
|
-V|--version) echo -e "$program\t$version"; exit;; # Show version and exit
|
|
--) shift ; break ;;
|
|
*) echo "$program: Internal error, inconsistent option specification." ; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [ $CHG ]; then OLD=$CHG; NEW=$CHG; fi
|
|
|
|
if [ $# -lt 1 ]; then echo -e "$program: Missing output filename\n"; usage; fi
|
|
|
|
origfile=$1
|
|
tempfile=$(mktemp)
|
|
difffile=$(mktemp)
|
|
|
|
if [ -e "$origfile" ]; then
|
|
cp -p $origfile $tempfile # For ownership and permissions
|
|
cat $FILE > $tempfile
|
|
[ "$FILE" ] && touch -r $FILE $tempfile
|
|
# This won't work if we don't have sufficient privileges:
|
|
#chown --reference=$origfile $tempfile
|
|
#chmod --reference=$origfile $tempfile
|
|
else
|
|
cat $FILE > $origfile
|
|
[ "$FILE" ] && touch -r $FILE $tempfile
|
|
leave 0 "Created file '$origfile'"
|
|
fi
|
|
|
|
origlen=$(wc -c < $origfile)
|
|
newlen=$(wc -c < $tempfile)
|
|
|
|
if [ $origlen = 0 -a $newlen = 0 ]; then
|
|
rm $tempfile
|
|
leave 1 "New content is identical (and void) - not updating '$origfile'."
|
|
fi
|
|
if [ $newlen = 0 -a -z "$empty" ]; then
|
|
leave 1 "New content is void - not updating '$origfile'."
|
|
fi
|
|
|
|
diff $origfile $tempfile > $difffile || [ $? -le 1 ] && true # suppress the '1' error code on differences
|
|
difflen=$(wc -l < $difffile)
|
|
if [ $difflen = 0 ]; then
|
|
leave 1 "New content is identical - not updating '$origfile'."
|
|
fi
|
|
|
|
if [ "$OLD" -o "$NEW" ]; then
|
|
|
|
if [ "$NEW" ]; then maxnew=$(( $origlen * $NEW / 100 )); fi
|
|
if [ "$OLD" ]; then maxdel=$(( $origlen * $OLD / 100 )); fi
|
|
|
|
newcount=$(grep "^> " $difffile | wc -c)
|
|
outcount=$(grep "^< " $difffile | wc -c)
|
|
delcount=$(grep "^! " $difffile | wc -c)
|
|
delcount=$(( $outcount + $delcount ))
|
|
rm $difffile
|
|
|
|
if [ "$OLD" ]; then
|
|
if [ "$delcount" -ge "$maxdel" ]; then
|
|
cp $tempfile $origfile.update
|
|
leave 2 "New content has too many removed lines ($delcount/$origlen)\n - not updating '$origfile'.\nNew content placed in '$origfile.update' instead"
|
|
fi
|
|
fi
|
|
if [ "$NEW" ]; then
|
|
if [ "$newcount" -ge "$maxnew" ]; then
|
|
cp $tempfile $origfile.update
|
|
leave 2 "New content has too many added lines ($newcount/$origlen)\n - not updating '$origfile'.\nNew content placed in '$origfile.update' instead"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ "$backup" ]; then
|
|
|
|
path=${origfile%/*}
|
|
name=${origfile##*/}
|
|
base=${name%.*}
|
|
ext=${origfile##*.}
|
|
|
|
if [ "$ext" = "$origfile" ]; then
|
|
ext=""
|
|
elif [ ! "${ext%/*}" = "$ext" ]; then
|
|
ext=""
|
|
else
|
|
ext=".$ext"
|
|
fi
|
|
|
|
if [ "$path" = "$origfile" ]; then
|
|
path=""
|
|
else
|
|
path="$path/"
|
|
fi
|
|
|
|
ver=1
|
|
backfile=$(eval date +"$PAT")
|
|
backpath="${backfile%/*}"
|
|
if [ "$backpath" = "$backfile" ]; then
|
|
backpath="."
|
|
fi
|
|
if [ ! -d $backpath ]; then
|
|
if [ -e $backpath ]; then
|
|
leave 3 "The backup path '$backpath' exists but isn't a directory"
|
|
else
|
|
mkdir -p $backpath
|
|
fi
|
|
fi
|
|
while [ -e "$backfile,$ver$ext" ]; do
|
|
ver=$(( $ver+1 ))
|
|
done
|
|
note "Saving backup: $backfile,$ver$ext"
|
|
cp -p "$origfile" "$backfile,$ver$ext"
|
|
chmod -w "$backfile,$ver$ext" || true
|
|
fi
|
|
|
|
if ! mv $tempfile $origfile; then cp -p $tempfile $origfile; fi
|
|
leave 0 "Updated file '$origfile'"
|