commit 92189fd599a89fab7bd33e3e9ec6408f77ebe494
parent 41e185c3a457d2b746b05ab601b9ce0c0a7b4e2b
Author: Jan Pobrislo <ccx@webprojekty.cz>
Date: Fri, 21 Feb 2014 00:18:54 +0100
posixify
Diffstat:
5 files changed, 162 insertions(+), 51 deletions(-)
diff --git a/bin/snap.missing b/bin/snap.missing
@@ -0,0 +1,19 @@
+#!/bin/awk -f
+BEGIN {
+ if (ARGC != 2) {
+ print "usage: snap.missing source destination"
+ exit 2
+ }
+
+ while ("snap.list " ARGV[1] | getline) {
+ snapshots[$0] = 1
+ }
+
+ while ("snap.list " ARGV[2] | getline) {
+ snapshots[$0] = 0
+ }
+
+ for (ts in snapshots) {
+ if (snapshots[ts]) print ts
+ }
+}
diff --git a/bin/snap.push b/bin/snap.push
@@ -1,33 +1,37 @@
-#!/bin/zsh
+#!/bin/sh
+: ${SNAP_SRCS:=.}
+
+usage() {
+ printf >&2 "Usage: %s: [-S SNAP_SRCS] [-D SNAP_DST] [-] [RSYNC_ARGS]\n" $(basenam "$0")
+ exit 2
+}
+
die() {
- print -r - "$@"
+ printf "%s" "$*"
exit 1
}
-if [[ -z $SNAP_SRCS ]]; then
- SNAP_SRCS=$1;shift
-fi
-SNAP_SRCS=${SNAP_SRCS%%/}
+while getopts S:D: opt; do
+ case $opt in
+ (S) SNAP_SRCS=$OPTARG;;
+ (D) SNAP_DST=$OPTARG;;
+ (?) usage;;
+ (h) usage;;
+ esac
+done
-if [[ -z $SNAP_DST ]]; then
- SNAP_DST=$1;shift
-fi
-SNAP_DST=${SNAP_DST%%/}
+case $1 in
+ (-) shift;;
+ (--) shift;;
+esac
-typeset -A snapshots
-for ts in ${(f)"$(snap.list $SNAP_SRCS/)"}; do
- snapshots[$ts]=$SNAP_SRCS/$ts
-done
+if test -z "$SNAP_DST"; then
+ echo >&2 "SNAP_DST is required either as env var or argument"
+ usage
+fi
-for ts in ${(f)"$(snap.list $SNAP_DST/)"}; do
- unset "snapshots[$ts]"
-done
+export SNAP_DST
-export SNAP_SRC SNAP_DST
-for SNAP_SRC in $snapshots; do
- if [[ -o xtrace ]]; then
- zsh -x $commands[snap.push.single] "$@"
- else
- snap.push.single "$@"
- fi
+snap.missing "$SNAP_SRCS" "$SNAP_DST" | while read ts; do
+ snap.push.single -S "$SNAP_SRCS/$ts" - "$@"
done
diff --git a/bin/snap.push.single b/bin/snap.push.single
@@ -1,39 +1,88 @@
-#!/bin/zsh
+#!/bin/sh
+: ${SNAP_SRC:=.}
+
+usage() {
+ printf >&2 "Usage: %s: [-S SNAP_SRC] [-D SNAP_DST] [-] [RSYNC_ARGS]\n" $(basenam "$0")
+ exit 2
+}
+
die() {
- print -r - "$@"
+ printf "%s" "$*"
exit 1
}
-if [[ -z $SNAP_SRC ]]; then
- SNAP_SRC=$1;shift
-fi
-SNAP_SRC=${SNAP_SRC%%/}
+while getopts S:D: opt; do
+ case $opt in
+ (S) SNAP_SRC=$OPTARG;;
+ (D) SNAP_DST=$OPTARG;;
+ (?) usage;;
+ (h) usage;;
+ esac
+done
-if [[ -z $SNAP_DST ]]; then
- SNAP_DST=$1;shift
+case $1 in
+ (-) shift;;
+ (--) shift;;
+esac
+
+if test -z "$SNAP_DST"; then
+ echo >&2 "SNAP_DST is required either as env var or argument"
+ usage
fi
-SNAP_DST=${SNAP_DST%%/}
-rsync=( rsync -aA --delete "$@" )
+check_local() {
+ for m in $SNAP_SRC/.snapshot.[0-9]*; do
+ test -f "$m" || continue
+ test -n "$mark" && die "duplicate snapshot mark"
+ mark=$m
+ done
+
+ test -f "$mark" || die "snapshot mark not found"
+ ts=${mark##*.}
+}
+
+check_remote() {
+ snap.list "$SNAP_SRC/" | while read m; do
+ test -n "$ts" && die "duplicate snapshot mark"
+ ts=$m
+ done
+ test -n "$ts" || die "snapshot mark not found"
+}
-marks=( $SNAP_SRC/.snapshot.[0-9]*(N) )
-(( $#marks != 1 )) && die invalid marks ${(qqq)marks}
+rs() {
+ rsync -aA --delete
+}
-if [[ $SNAP_DST == *:* ]]; then
+push_remote() {
# remote
- [[ $SNAP_DST == *.push ]] || $SNAP_DST=$SNAP_DST.push
- $rsync --exclude=/.snapshot.\* $SNAP_SRC/ $SNAP_DST/ && \
- $rsync $SNAP_SRC/ $SNAP_DST/
-else
- # local
- [[ -d $SNAP_DST ]] || die destination not a directory: ${(qqq)SNAP_DST}
- ts=${marks##*.}
- snapshots=( ${SNAP_DST}/.snapshot.[1-9]*(N) )
- if (($#snapshots)); then
- link=${SNAP_DST}/${${snapshots[-1]}##*.}
- $rsync --link-dest=$link $SNAP_SRC/ $SNAP_DST/$ts/ || exit $?
+ case "$SNAP_DST" in
+ (*.push) ;;
+ (*) SNAP_DST=${SNAP_DST}.push;;
+ esac
+ rs "$@" --exclude=/.snapshot.\* "$SNAP_SRC/" "$SNAP_DST/" && \
+ rs "$@" "$SNAP_SRC/" "$SNAP_DST/"
+}
+
+push_local() {
+ test -d "$SNAP_DST" || die "destination not a directory: ${SNAP_DST}"
+ snapshot=$(snap.list "$SNAP_DST" | tail -1)
+ if test -n $snapshot; then
+ link=${SNAP_DST}/${snapshots}
+ rs "$@" "--link-dest=$link" "$SNAP_SRC/" "$SNAP_DST/$ts/" || exit $?
else
- $rsync $SNAP_SRC/ $SNAP_DST/$ts/ || exit $?
+ rs "$@" "$SNAP_SRC/" "$SNAP_DST/$ts/" || exit $?
fi
- touch ${SNAP_DST}/$marks:t
-fi
+ touch "${SNAP_DST}/${marks##*/}"
+}
+
+case "$SNAP_SRC" in
+ (*:*) check_remote;;
+ (*) check_local;;
+esac
+
+case "$SNAP_DST" in
+ (rsync:*) push_remote;;
+ (*::*) push_remote;;
+ (*:*) die "pushing via remote shell directly not supported, use -e with rsync:// instead";;
+ (*) push_local;;
+esac
diff --git a/bin/snap.push.single.zsh b/bin/snap.push.single.zsh
@@ -0,0 +1,39 @@
+#!/bin/zsh
+die() {
+ print -r - "$@"
+ exit 1
+}
+
+if [[ -z $SNAP_SRC ]]; then
+ SNAP_SRC=$1;shift
+fi
+SNAP_SRC=${SNAP_SRC%%/}
+
+if [[ -z $SNAP_DST ]]; then
+ SNAP_DST=$1;shift
+fi
+SNAP_DST=${SNAP_DST%%/}
+
+rsync=( rsync -aA --delete "$@" )
+
+marks=( $SNAP_SRC/.snapshot.[0-9]*(N) )
+(( $#marks != 1 )) && die invalid marks ${(qqq)marks}
+
+if [[ $SNAP_DST == *:* ]]; then
+ # remote
+ [[ $SNAP_DST == *.push ]] || SNAP_DST=$SNAP_DST.push
+ $rsync --exclude=/.snapshot.\* $SNAP_SRC/ $SNAP_DST/ && \
+ $rsync $SNAP_SRC/ $SNAP_DST/
+else
+ # local
+ [[ -d $SNAP_DST ]] || die destination not a directory: ${(qqq)SNAP_DST}
+ ts=${marks##*.}
+ snapshots=( ${SNAP_DST}/.snapshot.[1-9]*(N) )
+ if (($#snapshots)); then
+ link=${SNAP_DST}/${${snapshots[-1]}##*.}
+ $rsync --link-dest=$link $SNAP_SRC/ $SNAP_DST/$ts/ || exit $?
+ else
+ $rsync $SNAP_SRC/ $SNAP_DST/$ts/ || exit $?
+ fi
+ touch ${SNAP_DST}/$marks:t
+fi
diff --git a/bin/snap.push b/bin/snap.push.zsh