path: root/contrib/workdir
diff options
authorPaul Smith <>2014-11-26 20:38:28 (GMT)
committerJunio C Hamano <>2014-12-03 20:49:24 (GMT)
commite32afab7b0376a7b07601a87cd5c6841ff2a811a (patch)
treec4a2bd6dfffbbbb28eca977858aaddafa43bd336 /contrib/workdir
parente69b1ce000e6c530ac8bf06470742456277e2a36 (diff)
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 <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'contrib/workdir')
1 files changed, 38 insertions, 15 deletions
diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir
index 75e8b25..888c34a 100755
--- a/contrib/workdir/git-new-workdir
+++ b/contrib/workdir/git-new-workdir
@@ -10,6 +10,10 @@ die () {
exit 128
+failed () {
+ die "unable to create new workdir '$new_workdir'!"
if test $# -lt 2 || test $# -gt 3
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"
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."
-# 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"
- 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"
+ cleandir="$new_workdir"
-# 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
+ # create a containing directory if needed
case $x in
- mkdir -p "$(dirname "$new_workdir/.git/$x")"
+ mkdir -p "$new_workdir/.git/${x%/*}"
- ln -s "$git_dir/$x" "$new_workdir/.git/$x"
+ ln -s "$git_dir/$x" "$new_workdir/.git/$x" || failed
-# 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