Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[tools] git vault-move. Fixes MER#932
Signed-off-by: Denis Zalevskiy <denis.zalevskiy@jolla.com>
- Loading branch information
Denis Zalevskiy
committed
Jul 20, 2015
1 parent
97ea6fe
commit 4b3086e
Showing
4 changed files
with
336 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters