| 1 |
uqs |
309420 |
#! /bin/sh |
| 2 |
|
|
HOME=/home/svnmir |
| 3 |
|
|
export HOME |
| 4 |
|
|
PATH=/usr/local/bin:$PATH |
| 5 |
|
|
export PATH |
| 6 |
|
|
|
| 7 |
|
|
# svnsync is non-atomic. Every commit is done in two distinct steps. |
| 8 |
|
|
# 1: the commit is replayed as a transaction. |
| 9 |
|
|
# 2: after the commit, the metadata is copied as a *separate* transaction. |
| 10 |
|
|
# This makes svnsync -> svnsync chains annoying as there is a brief window |
| 11 |
|
|
# between #1 and #2 where the repo is unlocked and bogus metadata is |
| 12 |
|
|
# visible. (!!!) |
| 13 |
|
|
# As a workaround, recheck the svn:author property of the last few |
| 14 |
|
|
# revisions and re-copy as needed. This reduces the window to a few |
| 15 |
|
|
# seconds. Still not good but better than no recovery at all. |
| 16 |
|
|
|
| 17 |
|
|
#MAILTO=clusteradm-updates@FreeBSD.org |
| 18 |
|
|
#@reboot /usr/sbin/daemon -cf lockf -s -t 0 /home/svnmir/dosync.lock /home/svnmir/dosync.sh |
| 19 |
|
|
#* * * * * /usr/sbin/daemon -cf lockf -s -t 0 /home/svnmir/dosync.lock /home/svnmir/dosync.sh |
| 20 |
|
|
#7 * * * * /home/svnmir/update.sh |
| 21 |
|
|
|
| 22 |
|
|
usage() { |
| 23 |
|
|
echo "Usage: $0 [-1] [-l logdir ] [-r repodirs] [-s setlist]" 1>&2 |
| 24 |
|
|
exit 1 |
| 25 |
|
|
} |
| 26 |
|
|
|
| 27 |
|
|
umask 002 |
| 28 |
|
|
me=$(id -un) |
| 29 |
|
|
|
| 30 |
|
|
once=false |
| 31 |
|
|
logdir=/var/log |
| 32 |
|
|
repodirs=/home/svn |
| 33 |
|
|
setlist="" |
| 34 |
|
|
|
| 35 |
|
|
while getopts "1l:r:s:" _opt; do |
| 36 |
|
|
case "$_opt" in |
| 37 |
|
|
1) once=true ;; |
| 38 |
|
|
l) logdir="$OPTARG" ;; |
| 39 |
|
|
r) repodirs="$OPTARG" ;; |
| 40 |
|
|
s) setlist="$OPTARG" ;; |
| 41 |
|
|
*) usage ;; |
| 42 |
|
|
esac |
| 43 |
|
|
done |
| 44 |
|
|
shift $(($OPTIND - 1)) |
| 45 |
|
|
if [ $# -ne 0 ]; then |
| 46 |
|
|
usage |
| 47 |
|
|
fi |
| 48 |
|
|
|
| 49 |
|
|
if [ -z "${setlist}" ]; then |
| 50 |
|
|
for r in base doc ports socsvn; do |
| 51 |
|
|
if [ -d ${repodirs}/$r ]; then |
| 52 |
|
|
setlist="${setlist} $r" |
| 53 |
|
|
fi |
| 54 |
|
|
done |
| 55 |
|
|
fi |
| 56 |
|
|
|
| 57 |
|
|
# Only ever run this under the dosync.lock |
| 58 |
|
|
for r in ${setlist}; do |
| 59 |
|
|
echo "Startup: $(date)" >> ${logdir}/svnsync-$r.log |
| 60 |
|
|
done |
| 61 |
|
|
|
| 62 |
|
|
t0=$(date +%s) |
| 63 |
|
|
|
| 64 |
|
|
# Pack repo once at startup |
| 65 |
|
|
for r in ${setlist}; do |
| 66 |
|
|
svnadmin pack ${repodirs}/$r >> ${logdir}/svnsync-$r.log 2>&1 |
| 67 |
|
|
done |
| 68 |
|
|
|
| 69 |
|
|
while : |
| 70 |
|
|
do |
| 71 |
|
|
for r in ${setlist}; do |
| 72 |
|
|
locked=$(svn propget --revprop -r 0 svn:sync-lock file://${repodirs}/$r 2>/dev/null) |
| 73 |
|
|
if [ -n "$locked" ]; then |
| 74 |
|
|
svn propdel --revprop -r 0 svn:sync-lock file://${repodirs}/$r >>${logdir}/svnsync-$r.log 2>&1 |
| 75 |
|
|
fi |
| 76 |
|
|
oldrev=$(svn propget --revprop -r 0 svn:sync-last-merged-rev file://${repodirs}/$r 2>>${logdir}/svnsync-$r.log) |
| 77 |
|
|
svnsync --non-interactive sync file://${repodirs}/$r >> ${logdir}/svnsync-$r.log 2>&1 |
| 78 |
|
|
newrev=$(svn propget --revprop -r 0 svn:sync-last-merged-rev file://${repodirs}/$r 2>>${logdir}/svnsync-$r.log) |
| 79 |
|
|
oldrev=$(($oldrev - 10)) |
| 80 |
|
|
numrev=$(($newrev - $oldrev + 1)) |
| 81 |
|
|
for rev in $(jot $numrev $oldrev); do |
| 82 |
|
|
a=$(svn propget --revprop -r $rev svn:author file://${repodirs}/$r 2>>${logdir}/svnsync-$r.log) |
| 83 |
|
|
if [ "x$a" == "x$me" ]; then |
| 84 |
|
|
svnsync copy-revprops -r $rev file://${repodirs}/$r >> ${logdir}/svnsync-$r.log 2>&1 |
| 85 |
|
|
fi |
| 86 |
|
|
done |
| 87 |
|
|
done |
| 88 |
|
|
if $once; then |
| 89 |
|
|
exit 0 |
| 90 |
|
|
fi |
| 91 |
|
|
# exit and restart once an hour in case of a script update |
| 92 |
|
|
now=$(date +%s) |
| 93 |
|
|
elapsed=$(( $now - $t0 )) |
| 94 |
|
|
# slightly less than 1 hour so we catch the cron restart asap |
| 95 |
|
|
if [ ${elapsed} -gt 3590 ]; then |
| 96 |
|
|
exit 0 |
| 97 |
|
|
fi |
| 98 |
|
|
sleep 5 |
| 99 |
|
|
done |