Skip to content

Commit

Permalink
Switch mv-merge to use rsync
Browse files Browse the repository at this point in the history
Add tests too.
  • Loading branch information
aspiers committed Nov 2, 2012
1 parent 2480006 commit 1fd4141
Show file tree
Hide file tree
Showing 20 changed files with 103 additions and 39 deletions.
1 change: 1 addition & 0 deletions .stow-local-ignore
Expand Up @@ -25,3 +25,4 @@ COPYING
/doc

lib/perl5/Sh\.t
t
107 changes: 68 additions & 39 deletions bin/mv-merge
@@ -1,9 +1,9 @@
#!/bin/sh
#!/bin/bash
#
# Moves the entire contents of one directory to another, even if some
# subdirectories are common to both source and destination directories.
#
# Uses cp-merge and rm-src-dups.
# Uses rsync and rm-src-dups.
#
# Adam Spiers <me@adamspiers.org>
#
Expand All @@ -12,57 +12,86 @@ set -e
me=`basename $0`

usage () {
cat <<EOF >&2
Usage: $me [--dry-run|-n] [-f|-u] [-s SUBPATH] SRCDIR DESTDIR
# Call as: usage [EXITCODE] [USAGE MESSAGE]
exit_code=1
if [[ "$1" == [0-9] ]]; then
exit_code="$1"
shift
fi
if [ -n "$1" ]; then
echo "$*" >&2
echo
fi

cat <<EOF >&2
Usage: $me [OPTIONS] SRC [SRC ...] DESTDIR
SRCs should be relative to the current directory.
DESTDIR can be relative or absolute.
Options (must be in order specified above!)
-f Force overwrites of existing files in dest tree
(does not overwrite by default)
-u Update existing files in dest tree only if source is newer
-n, --dry-run Don't actually do anything.
-s SUBPATH Only act on subpath of SRCDIR/DESTDIR
EOF
exit 1
exit "$exit_code"
}

if [ "$1" == -h ] || [ "$1" == --help ]; then
usage
fi
parse_opts () {
overwrite="--ignore-existing"

if [ "$1" = '--dry-run' ] || [ "$1" = '-n' ]; then
dry_run=--dry-run
shift
fi
while [ $# != 0 ]; do
case "$1" in
-h|--help)
usage 0
;;
-n|--dry-run)
dry_run=--dry-run
shift
;;
-f)
overwrite=""
shift
;;
-u)
# takes precedence over -f
overwrite="--update"
shift
;;
-*)
usage "Unrecognized option $1"
;;
*)
break
;;
esac
done

# Pass overwriting policy on to cp-merge
if [ "$1" == -f ] || [ "$1" == -u ]; then
overwrite="$1"
shift
fi
if [ $# -lt 2 ]; then
usage "Need at least two parameters"
fi

if [ "$1" = '-s' ]; then
subpath="$2"
subpath_args="-s $2"
echo "Operating on subpath $subpath"
shift; shift
fi
srcs=( "${@:1:$(($#-1))}" )
dst="${@: -1:1}"

if [ $# != 2 ]; then
echo "ARGV after options: $*"
usage
fi
if ! [ -d "$dst" ]; then
usage "$dst is not a directory"
fi
}

if ! which cp-merge 2>&1 >/dev/null; then
echo "cp-merge must be on \$PATH for $me to work." >&2
exit 1
if ! which rsync 2>&1 >/dev/null; then
echo "rsync must be on \$PATH for $me to work." >&2
exit 1
fi

oldpwd=`pwd`

cp-merge -l $dry_run $overwrite $subpath_args "$@"

echo "cd $oldpwd"
cd "$oldpwd"
parse_opts "$@"

echo rm-src-dups $dry_run $subpath_args "$@"
rm-src-dups $dry_run $subpath_args "$@"
abs_cwd=`pwd`
for src in "${srcs[@]}"; do
echo rsync -Rav --link-dest=$abs_cwd $dry_run $overwrite "$src" "$dst"
rsync -Rav --link-dest=$abs_cwd $dry_run $overwrite "$src" "$dst"

echo rm-src-dups $dry_run "$src" "$dst"
rm-src-dups $dry_run "$src" "$dst"
done
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/a/b/both1
@@ -0,0 +1 @@
newer
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/a/b/both2
@@ -0,0 +1 @@
older
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/a/b/only-dst
@@ -0,0 +1 @@
only-dst
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/a/b/same
@@ -0,0 +1 @@
same
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/c/both1
@@ -0,0 +1 @@
newer
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/c/both2
@@ -0,0 +1 @@
older
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/c/only-dst
@@ -0,0 +1 @@
only-dst
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/dst/c/same
@@ -0,0 +1 @@
same
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/a/b/both1
@@ -0,0 +1 @@
older
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/a/b/both2
@@ -0,0 +1 @@
newer
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/a/b/only-src
@@ -0,0 +1 @@
only-src
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/a/b/same
@@ -0,0 +1 @@
same
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/c/both1
@@ -0,0 +1 @@
older
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/c/both2
@@ -0,0 +1 @@
newer
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/c/only-src
@@ -0,0 +1 @@
only-src
1 change: 1 addition & 0 deletions t/mv-merge/mv-merge-test.vanilla/src/c/same
@@ -0,0 +1 @@
same
Empty file.
18 changes: 18 additions & 0 deletions t/mv-merge/test.sh
@@ -0,0 +1,18 @@
#!/bin/bash

here=`dirname $0`
cd "$here"

rm -rf mv-merge-test
cp -a mv-merge-test{.vanilla,}

for opts in '' '-u' '-f'; do
(
cd mv-merge-test/src
echo "Testing: mv-merge $opts a/b c ../dst"
mv-merge $opts a/b c ../dst && \
diff -ur $here/mv-merge-test{.vanilla,}
)

div
done

0 comments on commit 1fd4141

Please sign in to comment.