-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathlibcheckout
executable file
·277 lines (225 loc) · 7.43 KB
/
libcheckout
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
274
275
276
277
function checkout() {
local use_cache=${1:-""}
if [ -z "${SEMAPHORE_GIT_BRANCH}" ] || [ -z "${SEMAPHORE_GIT_URL}" ] || [ -z "${SEMAPHORE_GIT_DIR}" ] || [ -z "${SEMAPHORE_GIT_SHA}" ]; then
checkout::validation_message
return 1
fi
rm -rf "$SEMAPHORE_GIT_DIR"
if [ "$use_cache" = "--use-cache" ]; then
echo "[Experimental stability] Using cached Git repository."
checkout::use_cache
else
if [ -n "${SEMAPHORE_GIT_REF_TYPE:-}" ]; then
checkout::refbased
else
checkout::shallow
fi
exit_code=$?
if [ "$exit_code" -ne "0" ]; then
checkout::metric 0
fi
return $exit_code
fi
}
function checkout::validation_message() {
echo "[CHECKOUT ERROR] Some of these variables are unset:"
echo "SEMAPHORE_GIT_URL=$SEMAPHORE_GIT_URL"
echo "SEMAPHORE_GIT_DIR=$SEMAPHORE_GIT_DIR"
echo "SEMAPHORE_GIT_BRANCH=$SEMAPHORE_GIT_BRANCH"
echo "SEMAPHORE_GIT_SHA=$SEMAPHORE_GIT_SHA"
}
function checkout::use_cache() {
export CACHE_FAIL_ON_ERROR="true"
if ! cache restore git-cache-; then
echo "Failed to restore from the cache"
rm -rf "${SEMAPHORE_GIT_DIR}"
fi
if [ -d "$HOME/$SEMAPHORE_GIT_DIR" ]; then
checkout::fetch
else
checkout::clone
fi
# SC2181: checking the last command's exit code
# with $? simplifies the control flow of this function.
# shellcheck disable=SC2181
if [ "$?" -eq "0" ]; then
checkout::cache_store
else
return 1
fi
}
function checkout::fetch() {
echo "Restored cache"
cd "${HOME}/${SEMAPHORE_GIT_DIR}" || exit
git remote prune origin
retry git fetch --tags origin
checkout::switch_revision
}
function checkout::clone() {
retry git clone "${SEMAPHORE_GIT_URL}" "${SEMAPHORE_GIT_DIR}"
cd "${SEMAPHORE_GIT_DIR}" || exit
checkout::switch_revision
}
function checkout::reset_to_sha {
if checkout::checkrevision; then
git reset --hard "${SEMAPHORE_GIT_SHA}" 2>/dev/null
checkout::metric "$(du -s . | awk '{ print $1 }')"
return 0
else
return 1
fi
}
function checkout::switch_revision() {
if [ "${SEMAPHORE_GIT_REF_TYPE:-""}" = "pull-request" ]; then
if ! retry git fetch origin +"${SEMAPHORE_GIT_REF}": 2>/dev/null; then
echo "Reference: ${SEMAPHORE_GIT_REF} not found .... Exiting"
return 1
else
checkout::reset_to_sha
fi
elif [ "${SEMAPHORE_GIT_REF_TYPE:-''}" = "tag" ]; then
if ! git checkout -qf "${SEMAPHORE_GIT_TAG_NAME}"; then
echo "Release $SEMAPHORE_GIT_TAG_NAME not found .... Exiting"
return 1
else
checkout::metric "$(du -s . | awk '{ print $1 }')"
echo "HEAD is now at ${SEMAPHORE_GIT_SHA} Release ${SEMAPHORE_GIT_TAG_NAME}"
return 0
fi
else
local branch_origin="origin/$SEMAPHORE_GIT_BRANCH"
if [[ -n $(git show-ref "${SEMAPHORE_GIT_REF}") ]]; then
git checkout "${SEMAPHORE_GIT_BRANCH}"
else
git checkout -b "${SEMAPHORE_GIT_BRANCH}" -t "${branch_origin}";
fi
checkout::reset_to_sha
fi
}
function checkout::cache_store() {
# update cache if older then 72h -> 25920s
SEMAPHORE_GIT_CACHE_AGE="${SEMAPHORE_GIT_CACHE_AGE:-259200}"
local cache_key
local cache_age
cache_key="$(cache list 2>&1 | grep git-cache- || true )"
if [[ -n "$cache_key" ]];then
cache_key=$(echo "${cache_key}" | awk '{ print $1 }'| head -1)
fi
cache_age=$(echo "${cache_key}" | cut -d'-' -f8)
if [[ -n "$cache_age" ]] && [[ $cache_age =~ ^[0-9]+$ ]]; then
local diff=$(($(date +%s) - cache_age))
echo "diff: $diff"
if (( diff > SEMAPHORE_GIT_CACHE_AGE )); then
echo "Git cache outdated, refreshing..."
cd ..
checkout::cleanupcache
cache store "git-cache-$SEMAPHORE_JOB_ID-$(date +%s)" "${SEMAPHORE_GIT_DIR}"
cd "${SEMAPHORE_GIT_DIR}" || exit
else
echo "Git cache up-to-data."
fi
else
echo "No git cache... caching"
cd ..
cache store "git-cache-${SEMAPHORE_JOB_ID}-$(date +%s)" "${SEMAPHORE_GIT_DIR}"
cd "${SEMAPHORE_GIT_DIR}" || exit
fi
}
function checkout::cleanupcache {
if [ -z "${SEMAPHORE_GIT_CACHE_KEEP:-""}" ]; then
SEMAPHORE_GIT_CACHE_KEEP=0
fi
local k=$SEMAPHORE_GIT_CACHE_KEEP
local list=()
while IFS='' read -r line; do list+=("$line"); done < <(cache list 2>&1 | grep git-cache- | awk '{ print $1 }')
for i in "${list[@]:$k}"; do
cache delete "${i}"
done
}
function checkout::checkrevision {
if ! git rev-list HEAD.."${SEMAPHORE_GIT_SHA}" 2>/dev/null; then
echo "Revision: ${SEMAPHORE_GIT_SHA} not found .... Exiting"
return 1
fi
}
function checkout::branch_checkout {
if ! git checkout -f "$SEMAPHORE_GIT_BRANCH"; then
echo "Branch: ${SEMAPHORE_GIT_BRANCH} not found .... Exiting"
return 1
fi
}
function checkout::shallow() {
if [ -z "${SEMAPHORE_GIT_DEPTH:-""}" ]; then
SEMAPHORE_GIT_DEPTH=50
fi
echo "Performing shallow clone with depth: $SEMAPHORE_GIT_DEPTH"
if ! retry git clone --depth "${SEMAPHORE_GIT_DEPTH}" -b "${SEMAPHORE_GIT_BRANCH}" "${SEMAPHORE_GIT_URL}" "${SEMAPHORE_GIT_DIR}"; then
echo "Branch not found performing full clone"
retry git clone "${SEMAPHORE_GIT_URL}" "${SEMAPHORE_GIT_DIR}"
cd "$SEMAPHORE_GIT_DIR" || exit
if ! checkout::branch_checkout; then
return 1
fi
if checkout::checkrevision; then
git reset --hard "${SEMAPHORE_GIT_SHA}" 2>/dev/null
else
return 1
fi
else
cd "${SEMAPHORE_GIT_DIR}" || exit
if ! git reset --hard "${SEMAPHORE_GIT_SHA}" 2>/dev/null; then
echo "SHA: $SEMAPHORE_GIT_SHA not found performing full clone"
retry git fetch --unshallow
if checkout::checkrevision; then
git reset --hard "${SEMAPHORE_GIT_SHA}" 2>/dev/null
else
return 1
fi
fi
fi
checkout::metric "$(du -s . | awk '{ print $1 }')"
}
function checkout::refbased() {
if [ -z "${SEMAPHORE_GIT_DEPTH:-""}" ]; then
SEMAPHORE_GIT_DEPTH=50
fi
if [ "${SEMAPHORE_GIT_REF_TYPE:-""}" = "pull-request" ]; then
retry git clone --depth "${SEMAPHORE_GIT_DEPTH}" "${SEMAPHORE_GIT_URL}" "${SEMAPHORE_GIT_DIR}"
cd "${SEMAPHORE_GIT_DIR}" || exit
# Try fetching refs/objects with a depth.
if retry git fetch --depth "${SEMAPHORE_GIT_DEPTH}" origin +"${SEMAPHORE_GIT_REF}": 2>/dev/null; then
git checkout -qf FETCH_HEAD
echo "HEAD is now at ${SEMAPHORE_GIT_SHA}"
return 0
fi
# Fetch with depth failed, fallback to not using a depth.
if retry git fetch origin +"${SEMAPHORE_GIT_REF}": 2>/dev/null; then
git checkout -qf FETCH_HEAD
echo "HEAD is now at ${SEMAPHORE_GIT_SHA}"
return 0
fi
echo "Revision: ${SEMAPHORE_GIT_SHA} not found .... Exiting"
return 1
fi
if [ "${SEMAPHORE_GIT_REF_TYPE:-""}" = "tag" ]; then
if ! retry git clone --depth "${SEMAPHORE_GIT_DEPTH}" -b "${SEMAPHORE_GIT_TAG_NAME}" "${SEMAPHORE_GIT_URL}" "${SEMAPHORE_GIT_DIR}"; then
echo "Release $SEMAPHORE_GIT_TAG_NAME not found .... Exiting"
return 1
else
cd "${SEMAPHORE_GIT_DIR}" || exit
git checkout -qf "${SEMAPHORE_GIT_TAG_NAME}"
echo "HEAD is now at ${SEMAPHORE_GIT_SHA} Release ${SEMAPHORE_GIT_TAG_NAME}"
return 0
fi
fi
checkout::shallow
}
function checkout::metric() {
if [[ "${SEMAPHORE_TOOLBOX_METRICS_ENABLED:-''}" == "true" ]]; then
ref_type=${SEMAPHORE_GIT_REF_TYPE:-""}
size=${1:-"0"}
[[ $size -gt 0 ]] && status='success' || status='fail'
echo "libcheckout,provider='$SEMAPHORE_GIT_PROVIDER',reftype='$ref_type',status=$status size=$1" >> /tmp/toolbox_checkout
fi
}
export -f checkout