-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathgit-submodule-helper
executable file
·273 lines (239 loc) · 6.75 KB
/
git-submodule-helper
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#!/bin/bash
if [ "`which md5`" == "" ]; then
if [ "`which md5sum`" == "" ]; then
echo "Couldn't find md5 or md5sum. Aborting"
exit 1
fi
md5 () {
md5sum | cut -f 1 -d " "
}
fi
list_submodules () {
git ls-files --stage | grep "^160000 " | cut -f 2
}
submodule_url () {
git config "submodule.$1.url"
}
submodule_md5 () {
local path="$1"
local url=`submodule_url "$path"`
local string="$path $url"
printf "$string" | md5
}
submodule_stash_path () {
local path="$1"
[ ! -d "$GIT_DIR/submodule_cache/" ] && mkdir "$GIT_DIR/submodule_cache"
printf "$GIT_DIR/submodule_cache/`submodule_md5 "$path"`"
}
submodule_helper_stash () {
list_submodules | while read submodule; do
[ ! -d "$submodule/.git" ] && continue
stash_path="`submodule_stash_path "$submodule"`"
if [ -d "$stash_path" ]; then
echo "'$stash_path' already exists: it appears that the submodule $submodule has already been stashed"
else
mv "$submodule" "$stash_path"
echo "Stashed '$submodule' to '$stash_path'"
fi
done
}
submodule_helper_unstash () {
list_submodules | while read submodule; do
[ -d "$submodule/.git" ] && continue
stash_path="`submodule_stash_path "$submodule"`"
if [ ! -d "$stash_path" ]; then
echo "'$stash_path' doesn't exist, can't restore from stash (maybe it was never stashed?)"
else
if [ -d "$submodule" ] && ! rmdir "$submodule"; then
echo "Path '$submodule' is in the way. Leaving stashed."
continue
fi
mv "$stash_path/" "$submodule/"
echo "Unstashed '$submodule' from '$stash_path'"
fi
done
}
submodule_helper_stash_status () {
list_submodules | while read submodule; do
stash_path="`submodule_stash_path "$submodule"`"
if [ -d "$submodule/.git" ]; then
status="checked out"
elif [ -d "$stash_path" ]; then
status="stashed"
else
status="????"
fi
if [ "$status" == "stashed" ]; then
display_stash_path="$stash_path"
else
display_stash_path=""
fi
printf "(%s)\t%s\t%s\n" "$status" "$display_stash_path" "$submodule"
done
}
submodule_helper_attach () {
if (cat $GIT_DIR/HEAD | grep ref: 1> /dev/null) ; then
echo "You're already on a branch"
return 1
fi
current_rev=$(git rev-parse HEAD)
line=$(git 'for-each-ref' | egrep -v 'HEAD$' | grep $current_rev)
if [ $? != 0 ]; then
echo "no known branch is currently at ${current_rev}"
echo "here are some suggestions: "
git branch --contains $current_rev -a | egrep -v 'no branch|HEAD'
return 1
fi
rev=$(echo $line | awk '{print $1}')
ref=$(echo $line | awk '{print $3}')
if ( echo $ref | egrep '^refs/heads/' > /dev/null ); then
echo "ref: $ref" > $GIT_DIR/HEAD
return 0
fi
if ( echo $ref | egrep '^refs/remotes/' > /dev/null ); then
echo "Remote branch ${ref} matches"
short_ref=${ref#refs/remotes/}
local_ref=${ref#*/*/*/}
divergent_commits=$(git rev-list $ref..$local_ref)
if [ "$divergent_commits" == "" ]; then
echo "fastforwarding $local_ref to $ref"
git branch -f "$local_ref" "$ref"
git checkout "$local_ref"
fi
return 1
fi
}
submodule_helper_status () {
local prefix="$1"
local status=$(git status)
if [ "$(printf "$status" | grep "nothing to commit (working directory clean)")" == "" ]; then
echo
echo "${prefix}"
echo ----------------------------------------
echo "$status"
fi
list_submodules | while read submodule; do
pushd $submodule > /dev/null
submodule_helper_status "${prefix}${submodule}"
popd > /dev/null
done
}
submodule_helper_add_folder () {
local folder="$1"
pushd $folder > /dev/null
url=$(git config remote.origin.url)
popd > /dev/null
if [ -z "$url" ]; then
echo "Repository in $folder does not have remote named origin."
exit 1
fi
git submodule add "$url" "$folder"
}
submodule_helper_fetch () {
local prefix="$1"
local status=$(git status)
echo
echo "${prefix}"
echo ----------------------------------------
git fetch
list_submodules | while read submodule; do
pushd $submodule > /dev/null
submodule_helper_fetch "${prefix}${submodule}"
popd > /dev/null
done
}
submodule_helper_update () {
git ls-files --stage | grep "^160000 " | while read line; do
submodule=$(printf "$line" | cut -f 2 )
version=$(printf "$line" | cut -f 1 | cut -f 2 -d ' ' )
pushd $submodule > /dev/null
current_version=$(git rev-parse HEAD)
if [ ! "$current_version" == "$version" ]; then
echo
echo "${submodule}"
echo ----------------------------------------
if [ "$1" != "--offline" ]; then
(git show "$version" 2> /dev/null 1> /dev/null) || git fetch
fi
git checkout $version
submodule_helper_attach
fi
popd > /dev/null
done
}
submodule_helper_checkout () {
echo 1
}
submodule_helper_help () {
cat <<EOF
$0
V 0.2
By Tim Harper
http://tim.theenchanter.com/
A script to help you manage submodules
commands:
stash - Takes all of your submodules, and stashes them temporarily
to .git/submodule_cache/ Useful if you want to switch to a
branch that with a file that gets in the way of of your
submodule
unstash - Takes any stashed modules that are referenced by the
current branch, and puts them back in their place
stash-status
- Show the stashed status of any submodules (and the path
where they were stashed at)
fetch - Fetch all submodules (good for if you plan on going offline and
want to make sure you have everything
update - Optimized submodule update - only tries to fetch when needed. Use
--offline to prevent it from trying to fetch when encountering a
non-existing revision.
status - See the status for all submodules
attach - Re-attach your HEAD to a branch that matches your current rev.
add-folder
- add a folder that has been cloned as a submodule already
DISCLAIMER: Make sure you back things up first in case things go horribly wrong
EOF
}
GIT_DIR=".git"
if [ -f "$GIT_DIR" ]; then
GIT_DIR=$(cat $GIT_DIR | awk '{print $2}')
fi
if [ ! -d "$GIT_DIR" ]; then
echo "This must be run from the root directory of the git working copy"
exit 1
fi
case "$1" in
stash)
submodule_helper_stash
;;
unstash)
submodule_helper_unstash
;;
stash-status)
submodule_helper_stash_status
;;
add-folder)
submodule_helper_add_folder $2
;;
update)
submodule_helper_update $2
;;
fetch)
submodule_helper_fetch /
;;
checkout)
submodule_helper_checkout
;;
status)
submodule_helper_status /
;;
attach)
submodule_helper_attach
;;
help)
submodule_helper_help
;;
*)
submodule_helper_help
;;
esac
exit $?