forked from concourse/git-resource
/
in
executable file
·214 lines (169 loc) · 6.25 KB
/
in
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
#!/bin/bash
# vim: set ft=sh
set -e
exec 3>&1 # make stdout available as fd 3 for the result
exec 1>&2 # redirect all output to stderr for logging
source $(dirname $0)/common.sh
destination=$1
if [ -z "$destination" ]; then
echo "usage: $0 <path/to/destination>" >&2
exit 1
fi
# for jq
PATH=/usr/local/bin:$PATH
payload=$(mktemp $TMPDIR/git-resource-request.XXXXXX)
cat > $payload <&0
load_pubkey $payload
load_git_crypt_key $payload
configure_https_tunnel $payload
configure_git_ssl_verification $payload
configure_credentials $payload
uri=$(jq -r '.source.uri // ""' < $payload)
branch=$(jq -r '.source.branch // ""' < $payload)
git_config_payload=$(jq -r '.source.git_config // []' < $payload)
ref=$(jq -r '.version.ref // "HEAD"' < $payload)
depth=$(jq -r '(.params.depth // 0)' < $payload)
fetch=$(jq -r '(.params.fetch // [])[]' < $payload)
submodules=$(jq -r '(.params.submodules // "all")' < $payload)
submodule_recursive=$(jq -r '(.params.submodule_recursive // true)' < $payload)
submodule_remote=$(jq -r '(.params.submodule_remote // false)' < $payload)
commit_verification_key_ids=$(jq -r '(.source.commit_verification_key_ids // [])[]' < $payload)
commit_verification_keys=$(jq -r '(.source.commit_verification_keys // [])[]' < $payload)
tag_filter=$(jq -r '.source.tag_filter // ""' < $payload)
gpg_keyserver=$(jq -r '.source.gpg_keyserver // "hkp://ipv4.pool.sks-keyservers.net/"' < $payload)
disable_git_lfs=$(jq -r '(.params.disable_git_lfs // false)' < $payload)
clean_tags=$(jq -r '(.params.clean_tags // false)' < $payload)
short_ref_format=$(jq -r '(.params.short_ref_format // "%s")' < $payload)
configure_git_global "${git_config_payload}"
if [ -z "$uri" ]; then
echo "invalid payload (missing uri):" >&2
cat $payload >&2
exit 1
fi
branchflag=""
if [ -n "$branch" ]; then
branchflag="--single-branch --branch $branch"
fi
depthflag=""
if test "$depth" -gt 0 2> /dev/null; then
depthflag="--depth $depth"
fi
tagflag=""
if [ -d $tag_filter ]; then
tagflag="--tags"
fi
git clone $depthflag $uri $branchflag $destination $tagflag
cd $destination
git fetch origin refs/notes/*:refs/notes/*
# A shallow clone may not contain the Git commit $ref:
# 1. The depth of the shallow clone is measured backwards from the latest
# commit on the given head (master or branch), and in the meantime there may
# have been more than $depth commits pushed on top of our $ref.
# 2. If there's a path filter (`paths`/`ignore_paths`), then there may be more
# than $depth such commits pushed to the head (master or branch) on top of
# $ref that are not affecting the filtered paths.
#
# In either case we try to deepen the shallow clone until we find $ref, reach
# the max depth of the repo, or give up after a given depth and resort to deep
# clone.
if [ "$depth" -gt 0 ]; then
readonly max_depth=128
d="$depth"
while ! git checkout -q $ref &>/dev/null; do
# once the depth of a shallow clone reaches the max depth of the origin
# repo, Git silenty turns it into a deep clone
if [ ! -e .git/shallow ]; then
echo "Reached max depth of the origin repo while deepening the shallow clone, it's a deep clone now"
break
fi
echo "Could not find ref ${ref} in a shallow clone of depth ${d}"
(( d *= 2 ))
if [ "$d" -gt $max_depth ]; then
echo "Reached depth threshold ${max_depth}, falling back to deep clone..."
git fetch --unshallow origin $tagflag
break
fi
echo "Deepening the shallow clone to depth ${d}..."
git fetch --depth $d origin $tagflag
done
fi
git checkout -q $ref
invalid_key() {
echo "Invalid GPG key in: ${commit_verification_keys}"
exit 2
}
commit_not_signed() {
commit_id=$(git rev-parse ${ref})
echo "The commit ${commit_id} is not signed"
exit 1
}
if [ ! -z "${commit_verification_keys}" ] || [ ! -z "${commit_verification_key_ids}" ] ; then
if [ ! -z "${commit_verification_keys}" ]; then
echo "${commit_verification_keys}" | gpg --batch --import || invalid_key "${commit_verification_keys}"
fi
if [ ! -z "${commit_verification_key_ids}" ]; then
echo "${commit_verification_key_ids}" | \
xargs --no-run-if-empty -n1 gpg --batch --keyserver $gpg_keyserver --recv-keys
fi
git verify-commit $(git rev-list -n 1 $ref) || commit_not_signed
fi
if [ "$disable_git_lfs" != "true" ]; then
git lfs fetch
git lfs checkout
fi
git log -1 --oneline
git clean --force --force -d
git submodule sync
if [ -f $GIT_CRYPT_KEY_PATH ]; then
echo "unlocking git repo"
git-crypt unlock $GIT_CRYPT_KEY_PATH
fi
submodule_parameters=""
if [ "$submodule_remote" != "false" ]; then
submodule_parameters+=" --remote "
fi
if [ "$submodule_recursive" != "false" ]; then
submodule_parameters+=" --recursive "
fi
if [ "$submodules" == "all" ]; then
git submodule update --init $depthflag $submodule_parameters
elif [ "$submodules" != "none" ]; then
submodules=$(echo $submodules | jq -r '(.[])')
for submodule in $submodules; do
git submodule update --init $depthflag $submodule_parameters $submodule
done
fi
if [ "$disable_git_lfs" != "true" ]; then
git submodule foreach "git lfs fetch && git lfs checkout"
fi
for branch in $fetch; do
git fetch origin $branch
git branch $branch FETCH_HEAD
done
if [ "$ref" == "HEAD" ]; then
return_ref=$(git rev-parse HEAD)
else
return_ref=$ref
fi
# Store committer email in .git/committer. Can be used to send email to last committer on failed build
# Using https://github.com/mdomke/concourse-email-resource for example
git --no-pager log -1 --pretty=format:"%ae" > .git/committer
# Store git-resource returned version ref .git/ref. Useful to know concourse
# pulled ref in following tasks and resources.
echo "${return_ref}" > .git/ref
# Store short ref with templating. Useful to build Docker images with
# a custom tag
echo "${return_ref}" | cut -c1-7 | awk "{ printf \"${short_ref_format}\", \$1 }" > .git/short_ref
# Store commit message in .git/commit_message. Can be used to inform about
# the content of a successfull build.
# Using https://github.com/cloudfoundry-community/slack-notification-resource
# for example
git log -1 --format=format:%B > .git/commit_message
metadata=$(git_metadata)
if [ "$clean_tags" == "true" ]; then
git tag | xargs git tag -d
fi
jq -n "{
version: {ref: $(echo $return_ref | jq -R .)},
metadata: $metadata
}" >&3