git-new-workdir: don't fail if the target directory is empty

Allow new workdirs to be created in an empty directory (similar to "git
clone").  Provide more error checking and clean up on failure.

Signed-off-by: Paul Smith <paul@mad-scientist.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Paul Smith 2014-11-26 15:38:28 -05:00 committed by Junio C Hamano
parent e69b1ce000
commit e32afab7b0

View File

@ -10,6 +10,10 @@ die () {
exit 128
}
failed () {
die "unable to create new workdir '$new_workdir'!"
}
if test $# -lt 2 || test $# -gt 3
then
usage "$0 <repository> <new_workdir> [<branch>]"
@ -35,7 +39,7 @@ esac
# don't link to a configured bare repository
isbare=$(git --git-dir="$git_dir" config --bool --get core.bare)
if test ztrue = z$isbare
if test ztrue = "z$isbare"
then
die "\"$git_dir\" has core.bare set to true," \
" remove from \"$git_dir/config\" to use $0"
@ -48,35 +52,54 @@ then
"a complete repository."
fi
# don't recreate a workdir over an existing repository
if test -e "$new_workdir"
# make sure the links in the workdir have full paths to the original repo
git_dir=$(cd "$git_dir" && pwd) || exit 1
# don't recreate a workdir over an existing directory, unless it's empty
if test -d "$new_workdir"
then
die "destination directory '$new_workdir' already exists."
if test $(ls -a1 "$new_workdir/." | wc -l) -ne 2
then
die "destination directory '$new_workdir' is not empty."
fi
cleandir="$new_workdir/.git"
else
cleandir="$new_workdir"
fi
# make sure the links use full paths
git_dir=$(cd "$git_dir"; pwd)
mkdir -p "$new_workdir/.git" || failed
cleandir=$(cd "$cleandir" && pwd) || failed
# create the workdir
mkdir -p "$new_workdir/.git" || die "unable to create \"$new_workdir\"!"
cleanup () {
rm -rf "$cleandir"
}
siglist="0 1 2 15"
trap cleanup $siglist
# create the links to the original repo. explicitly exclude index, HEAD and
# logs/HEAD from the list since they are purely related to the current working
# directory, and should not be shared.
for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn
do
# create a containing directory if needed
case $x in
*/*)
mkdir -p "$(dirname "$new_workdir/.git/$x")"
mkdir -p "$new_workdir/.git/${x%/*}"
;;
esac
ln -s "$git_dir/$x" "$new_workdir/.git/$x"
ln -s "$git_dir/$x" "$new_workdir/.git/$x" || failed
done
# now setup the workdir
cd "$new_workdir"
# commands below this are run in the context of the new workdir
cd "$new_workdir" || failed
# copy the HEAD from the original repository as a default branch
cp "$git_dir/HEAD" .git/HEAD
# checkout the branch (either the same as HEAD from the original repository, or
# the one that was asked for)
cp "$git_dir/HEAD" .git/HEAD || failed
# the workdir is set up. if the checkout fails, the user can fix it.
trap - $siglist
# checkout the branch (either the same as HEAD from the original repository,
# or the one that was asked for)
git checkout -f $branch