-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgit-new-workdir
executable file
·144 lines (122 loc) · 3.59 KB
/
git-new-workdir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/bin/sh
# Source: https://raw.githubusercontent.com/git/git/master/contrib/workdir/git-new-workdir
# Adjusted by K. Potamianos <[email protected]> to support no checkout (for sparse checkouts)
usage () {
echo "usage:" "$@"
exit 127
}
die () {
echo $@
exit 128
}
failed () {
die "unable to create new workdir '$new_workdir'!"
}
# Processing options first
# Todo: allow for --sparse to be specified before --no-checkout
no_checkout=false
if test "$1" = "--no-checkout"
then
no_checkout=true
shift
fi
sparse=false
if test "$1" = "--sparse"
then
sparse=true
shift
fi
if test $# -lt 2 || test $# -gt 3
then
usage "git new-workdir [options] <repository> <new_workdir> [<branch>]
--no-checkout: skips checking out a branch in the new workdir
--sparse: copies over the contents of the repository's .git/info/sparse-checkout
(and other files from .git/info) and prompts the user to modify the sparse-checkout file"
fi
orig_git=$1
new_workdir=$2
branch=$3
# want to make sure that what is pointed to has a .git directory ...
git_dir=$(cd "$orig_git" 2>/dev/null &&
git rev-parse --git-dir 2>/dev/null) ||
die "Not a git repository: \"$orig_git\""
case "$git_dir" in
.git)
git_dir="$orig_git/.git"
;;
.)
git_dir=$orig_git
;;
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"
then
die "\"$git_dir\" has core.bare set to true," \
" remove from \"$git_dir/config\" to use $0"
fi
# don't link to a workdir
if test -h "$git_dir/config"
then
die "\"$orig_git\" is a working directory only, please specify" \
"a complete repository."
fi
# 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
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
mkdir -p "$new_workdir/.git" || failed
cleandir=$(cd "$cleandir" && pwd) || failed
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 "$new_workdir/.git/${x%/*}"
;;
esac
ln -s "$git_dir/$x" "$new_workdir/.git/$x" || failed
done
# 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 || failed
# the workdir is set up. if the checkout fails, the user can fix it.
trap - $siglist
# offer the possibility to edit the .git/info/sparse-checkout
if test z$sparse = ztrue
then
rm "$new_workdir/.git/info"
rsync -aP "$git_dir/info/" "$new_workdir/.git/info/" 2>&1 >/dev/null
if test -e ${EDITOR/ *}
then
$EDITOR .git/info/sparse-checkout
else
echo "EDITOR is not set, please edit .git/info/sparse-checkout by hand"
fi
fi
# checkout the branch (either the same as HEAD from the original repository,
# or the one that was asked for)
if test z$no_checkout = zfalse
then
git checkout -f $branch
else
echo "Skipping the checkout as requested."
fi