Skip to content

Commit

Permalink
[tools] git vault-move. Fixes MER#932
Browse files Browse the repository at this point in the history
Signed-off-by: Denis Zalevskiy <denis.zalevskiy@jolla.com>
  • Loading branch information
Denis Zalevskiy committed Jul 20, 2015
1 parent 97ea6fe commit 4b3086e
Show file tree
Hide file tree
Showing 4 changed files with 336 additions and 14 deletions.
133 changes: 133 additions & 0 deletions tools/git-vault-move
@@ -0,0 +1,133 @@
#!/bin/bash

src=$(dirname $0)
src=$(cd $src;pwd)
source $src/vault-misc $src

init_root_and_enter
ensure_param_count_exit_usage $# 1 "<new_git_dir>" $@

dst=$1

out_of_tree="out"
in_the_tree="in"
src_location=
src=
dotgit=$(readlink -f $root/.git)

if [ -f $dotgit ]; then
re="s|gitdir: \(.*\)$|\1|"
src=$(cat $root/.git | sed -e "$re")
[ -d $src ] || error 42 "Current src isn't a dir: $src"
src_location=$out_of_tree
trace "External source: $src"
elif [ -d $dotgit ]; then
src_location=$in_the_tree
src=$dotgit
trace "Internal source: $src"
else
error 10 "Not dir|file $src/.git"
fi

dst=$(readlink -f $dst)
src=$(readlink -f $src)

[ "$dst" == "$src" ] && error 23 "$src=$dst"

dst_location=
if [ "$dotgit" == "$dst" ]; then
trace "Moving .git into the tree"
[ -f "$dotgit" ] || error 48 "Destination $dotgit should be file"
dst_location=$in_the_tree
else
[ -e "$dst" ] && error 22 "Dst should not exist: $dst"
dst_location=$out_of_tree
fi

for f in "$dotgit.old" "$dotgit.new"; do
[ -e "$f" ] && (rm "$f" || error 15 "Can't rm $f")
done

if [ $dst_location == $out_of_tree ]; then
mkdir -p $dst || error 24 "Can't create dst dir: $dst"
fi

for d in "$root" "$src" "$dst" "$dotgit"; do
[ -w "$d" ] || error 29 "'$d' is not writable"
done

src_dev=$(stat -c "%d" $src)
dst_dev=$(stat -c "%d" $dst)
is_same_dev=false
if [ $src_dev -eq $dst_dev ]; then
trace "Same device"
is_same_dev=true
fi

trace "Going to do: $src->$dst, .git=$dotgit"

function rollback_dotgit {
trace "Rollback .git"
if [ $dst_location == $in_the_tree ]; then
[ -d "$dotgit" ] && rmdir "$dotgit"
[ -e "$dotgit.old" ] && mv "$dotgit.old" "$dotgit"
[ -e "$dotgit.new" ] && rm "$dotgit.new"
fi
error $@
}

function prepare_dotgit {
if [ -e $dotgit ]; then
mv $dotgit $dotgit.old || error 13 "Can't mv $dotgit $dotgit.old"
fi
echo "gitdir: $dst" > $dotgit.new || rollback_dotgit 31 "Can't write gitdir to $dotgit.new"
}

if [ $dst_location == $in_the_tree ]; then
prepare_dotgit
mkdir $dotgit || rollback_dotgit 32 "Can't create dir $gitdir"
fi

([ -d "$src" ] && [ -d "$dst" ]) || rollback_dotgit 33 "$src and $dst should be dirs"

cmd=false
if $is_same_dev; then
trace "Same device, move"
cmd="mv -T '$src' '$dst'"
else
trace "Different devices, copy"
cmd="cp -rTLpuf '$src' '$dst'"
fi

trace "Command: $cmd"

function rollback {
msg="$1. Aux info:"
if $is_same_dev; then
msg="$msg Can't move $src, check $dst"
else
if ! rm -rf "$dst"; then
msg="$msg Can't rm $dst"
fi
fi
rollback_dotgit 55 $msg
}

if eval "$cmd"; then
if [ $dst_location == $out_of_tree ]; then
prepare_dotgit
fi
mv $dotgit.new $dotgit || rollback "Failed to mv $dotgit.new $dotgit"
if [ $src_location == $out_of_tree ] && ! $is_same_dev; then
if [ -d "$src" ]; then
rm -rf "$src" || warn "Can't remove $src"
else
warn "Source should still exists but it doesn't: $src"
fi
fi
[ -e $dotgit.old ] && rm $dotgit.old -rf
else
rollback "Failed to execute $cmd"
exit 1 # just to be sure it exits
fi
trace "Successfully moved $src->$dst"
2 changes: 1 addition & 1 deletion tools/git-vault-sync
Expand Up @@ -108,7 +108,7 @@ case $cp_tool in
rsync)
if [ $src_type == "local" ]; then
cp_cmd="$cp_tool -avz"
src_prefix=$src_repo/
src_prefix="$src_repo/"
else
src_prefix=$user@$host:$src_repo/
if [ "x$port" == "x" ]; then
Expand Down
148 changes: 148 additions & 0 deletions tools/test-vault-move
@@ -0,0 +1,148 @@
#!/bin/bash

initial_dir=$(pwd)

src=$(dirname $0)
src=$(cd $src;pwd)
source $src/vault-misc $src

cur_test="Begin"
function next_test {
trace $@
cur_test=$1
}

function test_failed {
echo 'stdout {' >&2;
cat $test_out >&2;
echo '} stderr {' >&2;
cat $test_err >&2;
echo '}' >&2;
error $1 "Test: $cur_test." ${@:2}
}

function check_is_vault_storage {
d=$1
[ -d $d ] || test_failed 7 "Not a dir $d"
[ -f $d/config ] || test_failed 7 "Not a git storage"
[ -d $d/blobs ] || test_failed 7 "Not a vault storage $d?"
}

trace "Test run in $TOP_PID"

empty_repo_archive=$src/../tests/empty-repo.tar.gz
[ -f $empty_repo_archive ] || test_failed 1 "No test vault archive"

is_success=true

test_dir=$(mktemp -t -d vault.XXXXXXXXXX)
test_out=$test_dir/stdout.txt
test_err=$test_dir/stderr.txt
cd $test_dir || test_failed 1 "Can't enter $test_dir"
normal_cleanup="$normal_cleanup; echo 'OK' 1>&2; cd $initial_dir; rm -rf $test_dir"
failed_cleanup="warn 'Dir $test_dir is left';$failed_cleanup;"


r1=$test_dir/v1
rout=$test_dir/external1
rout2=$test_dir/external2

next_test "Prepare $test_dir"
mkdir $r1 || test_failed 2 "Can't create $r1"
tar xf $empty_repo_archive -C $r1 || test_failed 4 "Can't extract archive"
cd $r1 || test_failed 5 "Can't enter $r1"
init_root_and_enter
storage_now=$r1/.git

next_test "Move to exiting dir"
mkdir $rout || test_failed 10 "Can't create $rout"
git-vault-move $rout 1>$test_out 2>$test_err \
&& test_failed 6 "Move to existing $rout shouldn't succeed"

next_test "Move to read-only dir"
chmod ug-w $rout || test_failed 12 "Can't chown $rout"
ro_dir=$rout/inaccessible
git-vault-move $ro_dir 1>$test_out 2>$test_err \
&& test_failed 6 "Move to RO dir $ro_dir shouldn't succeed"
[ -d $r1/.git ] || test_failed 7 "Not a dir $r1/.git"
check_is_vault_storage $storage_now
rmdir $rout || test_failed 11 "Dir $rout is not empty?"

next_test "Move out"
git-vault-move $rout \
|| test_failed 6 "Move to $rout"
storage_now=$rout
[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git"
check_is_vault_storage $storage_now

next_test "Move out-of-tree dir to itself"
git-vault-move $rout 1>$test_out 2>$test_err \
&& test_failed 14 "Moving into self shouldn't succeed for $rout"

next_test "Move out to another dir"
git-vault-move $rout2 \
|| test_failed 6 "Move to $rout2"
storage_now=$rout2
[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git"
check_is_vault_storage $storage_now

next_test "Move to read-only in-tree .git"
chmod ug-w $r1/.git || test_failed 12 "Can't chown $r1/.git"
git-vault-move $r1/.git 1>$test_out 2>$test_err \
&& test_failed 16 "Move to RO $r1/.git shouldn't succeed"
[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git"
check_is_vault_storage $storage_now
chmod ug+w $r1/.git || test_failed 12 "Can't chown back $r1/.git"

next_test "Move in"
git-vault-move $r1/.git \
|| test_failed 6 "Move to $r1/.git"
storage_now=$r1/.git
[ -d $rout ] && test_failed 7 "Dir $rout is left"
[ -d $r1/.git ] || test_failed 7 "Not a dir $r1/.git"
check_is_vault_storage $storage_now

next_test "Move in-tree dir to itself"
git-vault-move $r1 1>$test_out 2>$test_err \
&& test_failed 8 "Moving into self shouldn't succeed $r1.git"

next_test "Setup to check moving between filesystems"
other_fs=/dev/shm
[ -d /dev/shm ] || error 20 "Can't test further w/o /dev/shm used as other fs"
other_test_dir=$other_fs/$(basename $test_dir)
mkdir $other_test_dir || error 20 "Can't create $other_test_dir"
normal_cleanup="$normal_cleanup; rm -rf $other_test_dir"
failed_cleanup="warn 'Dir $other_test_dir is left';$failed_cleanup"

next_test "Move to other fs"

out_repo=$other_test_dir/v1

git-vault-move $out_repo \
|| test_failed 6 "Move to $out_repo"
storage_now=$out_repo
[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git"
check_is_vault_storage $storage_now

next_test "Move from other fs"
git-vault-move $r1/.git \
|| test_failed 6 "Move from $out_repo"
[ -d $out_repo ] && error 23 "Dir should not be left: $out_repo"
storage_now=$r1/.git
[ -d $r1/.git ] || test_failed 7 "Not a dir $r1/.git"
check_is_vault_storage $storage_now

next_test "Move back to other fs"
git-vault-move $out_repo \
|| test_failed 6 "Move to $out_repo"
storage_now=$out_repo
[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git"
check_is_vault_storage $storage_now

next_test "Move from other fs to out-of-tree"
git-vault-move $rout \
|| test_failed 6 "Move to $rout"
storage_now=$rout
[ -d $out_repo ] && test_failed 7 "Out dir is left: $out_repo"
[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git"
check_is_vault_storage $storage_now
67 changes: 54 additions & 13 deletions tools/vault-misc
Expand Up @@ -5,19 +5,8 @@ scripts_branch=scripts
root_version=3
root=

trap "exit 1" TERM
export TOP_PID=$$

function warn {
echo "`basename $0`: Warning: ${@:1}" 1>&2;
}

function error {
TOP_RC=$1
echo "`basename $0`: Error: ${@:2}" 1>&2;
kill -s TERM $TOP_PID
}

is_trace=false
if [ "x$VAULT_TRACE" != "x" ]; then
is_trace=true
Expand All @@ -29,6 +18,58 @@ function trace {
fi
}


normal_cleanup="true"
failed_cleanup="true"
is_failed=false

function on_normal_exit
{
if $is_failed; then
exit 1
else
trace "Normal exit from $BASHPID"
trace "Exec: $normal_cleanup"
eval "$normal_cleanup"
exit 0
fi
}

is_exit_on_failure=true
is_expect_success=true
function on_failure
{
if $is_expect_success; then
trace "Failure cleanup in $BASHPID"
trace "Exec: $failed_cleanup"
is_failed=true
eval "$failed_cleanup"
$is_exit_on_failure && exit 1
else
trace "Failure is expected"
is_failed=true
fi
}
trap on_failure TERM
trap on_normal_exit EXIT
#trap on_failure ERR

function warn {
echo "`basename $0`: Warning: ${@:1}" 1>&2;
}

function error {
TOP_RC=$1
echo "`basename $0`: Error #$1: ${@:2}" 1>&2;
if [ $BASHPID -ne $TOP_PID ]; then
trace "Not a top script"
is_exit_on_failure=false
on_failure
fi
warn "Killing $TOP_PID"
kill -s TERM $TOP_PID
}

if [ $# -eq 1 ]; then
src=$1
else
Expand All @@ -39,7 +80,7 @@ trace "SCRIPTS DIR: $src"
export PATH=$src:$PATH

function ensure_param_count_op_exit_usage {
[ $@ -ge 3 ] || error 22 "Call as Num#0 OP Num#1"
[ $# -ge 3 ] || error 22 "Call as Num#0 OP Num#1"
if ! [ $1 $2 $3 ]; then
local name=`basename $0`
echo "Expecting param count: $1 $2 $3" 1>&2;
Expand Down Expand Up @@ -72,7 +113,7 @@ function init_root {
if [ "x$root" == "x" ]; then
root=$(git vault-root)
if [ $? -ne 0 ]; then
error $? "Not a vault?"
error $? "Not inside vault? $(pwd)"
fi
if [ "x$root" == "x" ]; then
error 54 "Root is empty"
Expand Down

0 comments on commit 4b3086e

Please sign in to comment.