aboutsummaryrefslogtreecommitdiffstats
path: root/bitpocket
diff options
context:
space:
mode:
Diffstat (limited to 'bitpocket')
-rwxr-xr-xbitpocket96
1 files changed, 62 insertions, 34 deletions
diff --git a/bitpocket b/bitpocket
index a0dbbd6..f1df649 100755
--- a/bitpocket
+++ b/bitpocket
@@ -50,16 +50,16 @@ fi
# Specify certain files to include
if [ -f "$DOT_DIR/include" ]; then
user_include="--include-from $DOT_DIR/include"
-fi
-
+fi
+
# Specify rsync filter rules
if [ -f "$DOT_DIR/filter" ]; then
# The underscore (_) is required for correct operation
user_filter="--filter merge_$DOT_DIR/filter"
-fi
+fi
USER_RULES="$user_filter $user_include $user_exclude"
-
+
TIMESTAMP=$(date "+%Y-%m-%d.%H%M%S")
export RSYNC_RSH
@@ -70,8 +70,8 @@ function init {
exit 128
fi
- if [[ $# != 2 ]]; then
- echo "usage: bitpocket init <REMOTE_HOST> <REMOTE_PATH>"
+ if [[ -z "$2" || -n "$3" ]]; then
+ echo "usage: bitpocket init {<REMOTE_HOST> | \"\"} <REMOTE_PATH>"
exit 128
fi
@@ -82,12 +82,15 @@ function init {
REMOTE_HOST=$1
REMOTE_PATH="$2"
-## SSH command with options for connecting to \$REMOTE
+## SSH command with options for connecting to \$REMOTE_HOST
# RSYNC_RSH="ssh -p 22 -i $DOT_DIR/id_rsa"
## Uncomment following line to follow symlinks (transform it into referent file/dir)
# RSYNC_OPTS="-L"
+## Use the following if a FAT or VFAT filesystem is being synchronized
+# RSYNC_OPTS="--no-perms --no-owner --no-group --modify-window=2"
+
## Uncomment following lines to get sync notifications
# SLOW_SYNC_TIME=10
# SLOW_SYNC_START_CMD="notify-send 'BitPocket sync in progress...'"
@@ -103,6 +106,14 @@ function log {
tail -f "$DOT_DIR/log"
}
+function pull {
+ sync onlypull
+}
+
+function push {
+ sync onlypush
+}
+
# Do the actual synchronization
function sync {
assert_dotdir
@@ -124,7 +135,7 @@ function sync {
# Must be done with rsync itself (rather than find) to respect includes/excludes
# Order of includes/excludes/filters is EXTREMELY important
echo "# Saving current state and backing up files (if needed)"
- echo " | Root dir: $(pwd)"
+ echo " | Root dir: $(pwd)"
rsync -av --list-only --exclude "/$DOT_DIR" $RSYNC_OPTS $USER_RULES . | grep "^-\|^d" \
| sed "s:^\S*\s*\S*\s*\S*\s*\S*\s*:/:" | sed "s:^/\.::" | sort > "$STATE_DIR/tree-current"
@@ -136,28 +147,38 @@ function sync {
# we always create it, but remove it if it is empty afterwards.
mkdir --parents $DOT_DIR/backups/$TIMESTAMP
- # Determine what will be fetched from server and make backup
+ # Determine what will be fetched from server and make backup
# copies of any local files to be deleted or overwritten.
# Order of includes/excludes/filters is EXTREMELY important
rsync --dry-run \
- -auvzxi --delete $RSYNC_OPTS --exclude "/$DOT_DIR" --exclude-from "$TMP_DIR/fetch-exclude" $USER_RULES $REMOTE/ . \
+ -auvzxi --delete $RSYNC_OPTS --exclude "/$DOT_DIR" --exclude-from "$TMP_DIR/fetch-exclude" $USER_RULES "$REMOTE/" . \
| grep "^[ch<>\.\*][f]\|\*deleting" | sed "s:^\S*\s*::" | sed 's:\d96:\\\`:g' | sed "s:\(.*\):if [ -f \"\1\" ]; then cp --parents \"\1\" $DOT_DIR/backups/$TIMESTAMP; fi:" | sh || die "BACKUP"
[ "$(ls -A $DOT_DIR/backups/$TIMESTAMP)" ] && echo " | Some files were backed up to $DOT_DIR/backups/$TIMESTAMP"
[ "$(ls -A $DOT_DIR/backups/$TIMESTAMP)" ] || rmdir $DOT_DIR/backups/$TIMESTAMP
- # Actual fetch
- # Pulling changes from server
- # Order of includes/excludes/filters is EXTREMELY important
- echo
- echo "# Pulling changes from server"
- rsync -auvzxi --delete $RSYNC_OPTS --exclude "/$DOT_DIR" --exclude-from "$TMP_DIR/fetch-exclude" $USER_RULES $REMOTE/ . | sed "s/^/ | /" || die "PULL"
+ if [ "$1" != "onlypush" ]
+ then
- # Actual push
- # Send new and updated, remotely remove files deleted locally
- # Order of includes/excludes/filters is EXTREMELY important
- echo
- echo "# Pushing changes to server"
- rsync -auvzxi --delete $RSYNC_OPTS --exclude "/$DOT_DIR" $USER_RULES . $REMOTE/ | sed "s/^/ | /" || die "PUSH"
+ # Actual fetch
+ # Pulling changes from server
+ # Order of includes/excludes/filters is EXTREMELY important
+ echo
+ echo "# Pulling changes from server"
+ rsync -auvzxi --delete $RSYNC_OPTS --exclude "/$DOT_DIR" --exclude-from "$TMP_DIR/fetch-exclude" $USER_RULES "$REMOTE/" . | sed "s/^/ | /" || die "PULL"
+
+ fi
+
+ if [ "$1" != "onlypull" ]
+ then
+
+ # Actual push
+ # Send new and updated, remotely remove files deleted locally
+ # Order of includes/excludes/filters is EXTREMELY important
+ echo
+ echo "# Pushing changes to server"
+ rsync -auvzxi --delete $RSYNC_OPTS --exclude "/$DOT_DIR" $USER_RULES . "$REMOTE/" | sed "s/^/ | /" || die "PUSH"
+
+ fi
# Save after-sync state
# Must be done with rsync itself (rather than find) to respect includes/excludes
@@ -167,6 +188,7 @@ function sync {
rsync -av --list-only --exclude "/$DOT_DIR" $USER_RULES . | grep "^-\|^d" \
| sed "s:^\S*\s*\S*\s*\S*\s*\S*\s*:/:" | sed "s:^/\.::" | sort > "$TMP_DIR/tree-after"
+
# Save all newly created files for next run (to prevent deletion of them)
# This includes files created by user in parallel to sync and files fetched from remote
comm -23 "$TMP_DIR/tree-after" "$STATE_DIR/tree-current" >"$STATE_DIR/added-prev"
@@ -190,7 +212,7 @@ function pack {
assert_dotdir
# Git is required for backup packing
- if [ ! `builtin type -p git` ]; then
+ if [ ! `builtin type -p git` ]; then
echo "fatal: For backup packing, git must be installed"
exit 128
fi
@@ -201,7 +223,7 @@ function pack {
mkdir $DOT_DIR/pack
git init $DOT_DIR/pack
touch $DOT_DIR/pack/.git-init-marker
- (cd $DOT_DIR/pack && git add .)
+ (cd $DOT_DIR/pack && git add .)
(cd $DOT_DIR/pack && git commit -a -q -m "INIT")
fi
@@ -211,11 +233,11 @@ function pack {
for DIR in $DOT_DIR/backups/*
do
TSTAMP=$(echo $DIR | sed "s|.*/||")
- if [ "$(ls -A $DIR)" ]
+ if [ "$(ls -A $DIR)" ]
then
echo -n "Processing: $TSTAMP ... "
echo -n "Moving ... "
- (cp -rfl $DIR/* $DOT_DIR/pack && rm -rf $DIR) || die MV
+ (cp -rfl $DIR/* $DOT_DIR/pack && rm -rf $DIR) || die MV
echo -n "Adding ... "
(cd $DOT_DIR/pack && git add .) || die ADD
echo -n "Committing ... "
@@ -279,8 +301,8 @@ function acquire_lock {
exit 1
else
echo -e "\x1b\x5b1;31mbitpocket error:\x1b\x5b0m Bitpocket found a stale lock directory:"
- echo " | Root dir: $(pwd)"
- echo " | Lock dir: $LOCK_DIR"
+ echo " | Root dir: $(pwd)"
+ echo " | Lock dir: $LOCK_DIR"
echo " | Command: LOCK_PATH=$(pwd)/$LOCK_DIR && rm \$LOCK_PATH/pid && rmdir \$LOCK_PATH"
echo "Please remove the lock directory and try again."
exit 2
@@ -298,7 +320,7 @@ function acquire_remote_lock {
$REMOTE_RUNNER "mkdir -p \"$REMOTE_TMP_DIR\"; cd \"$REMOTE_PATH\" && mkdir \"$LOCK_DIR\" 2>/dev/null"
if [[ $? != 0 ]]; then
- echo "Couldn't acquire remote lock. Another client is syncing with $REMOTE or lock file couldn't be created. Exiting."
+ echo "Couldn't acquire remote lock. Another client is syncing with \"$REMOTE\" or lock file couldn't be created. Exiting."
release_lock
exit 3
fi
@@ -341,14 +363,17 @@ function die {
function list {
echo -e "\x1b\x5b1;32mbitpocket\x1b\x5b0m will sync the following files:"
rsync -av --list-only --exclude "/$DOT_DIR" $USER_RULES . | grep "^-\|^d" \
- | sed "s:^\S*\s*\S*\s*\S*\s*\S*\s*:/:" | sed "s:^/\.::" | sort
+ | sed "s:^\S*\s*\S*\s*\S*\s*\S*\s*:/:" | sed "s:^/\.::" | sort
}
function usage {
- echo "usage: bitpocket [sync|help|pack|log|cron|list|init <REMOTE_HOST> <REMOTE_PATH>]"
+ echo "usage: bitpocket [sync | push | pull | pack | log | cron | list | help]"
+ echo " bitpocket init {<REMOTE_HOST> | \"\"} <REMOTE_PATH>"
echo ""
echo "Available commands:"
echo " sync Run the sync process. If no command is specified, sync is run by default."
+ echo " push Only push new files to the server."
+ echo " pull Only pull new files from the server."
echo " init Initialize a new bitpocket folder. Requires remote host and path params."
echo " pack Pack any existing (automatic) backups into a git repository."
echo " cron Run sync optimized for cron, logging output to file instead of stdout."
@@ -359,12 +384,15 @@ function usage {
echo "Note: All commands (apart from help), must be run in the root of a"
echo " new or existing bitpocket directory structure."
echo ""
-
}
if [ "$1" = "init" ]; then
# Initialize bitpocket directory
- init $2 $3 $4
+ init "$2" "$3" "$4"
+elif [ "$1" = "pull" ]; then
+ sync onlypull
+elif [ "$1" = "push" ]; then
+ sync onlypush
elif [ "$1" = "pack" ]; then
# Pack backups using git
pack
@@ -376,7 +404,7 @@ elif [ "$1" = "cron" ]; then
cron
elif [ "$1" = "list" ]; then
# List all file in sync set (honoring .bitpocket/include & .bitpocket/exclude)
- list
+ list
elif [ "$1" != "" ] && [ "$1" != "sync" ]; then
# Show help
usage

© 2014-2024 Faster IT GmbH | imprint | privacy policy