-
Notifications
You must be signed in to change notification settings - Fork 144
/
getsrc.sh
executable file
·237 lines (202 loc) · 7.33 KB
/
getsrc.sh
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
#!/bin/bash
#
# Skip's "universal" lookaside grabber
# Updated by Peter Ajamian
#
# Run this in a Fedora/Rocky/CentOS/CentOS Stream source directory, and it will retrieve the lookaside sources (tarballs) into the current directory
#
shopt -s nullglob extglob
# List of lookaside locations and their patterns
# This can be easily edited to add more distro locations, or change their order for less 404 misses:
lookasides=(
https://rocky-linux-sources-staging.a1.rockylinux.org/%HASH%
https://sources.build.resf.org/%HASH%
https://git.centos.org/sources/%PKG%/%BRANCH%/%HASH%
https://sources.stream.centos.org/sources/rpms/%PKG%/%FILENAME%/%SHATYPE%/%HASH%/%FILENAME%
https://src.fedoraproject.org/repo/pkgs/%PKG%/%FILENAME%/%SHATYPE%/%HASH%/%FILENAME%
https://ax8edlmsvvfp.compat.objectstorage.us-phoenix-1.oraclecloud.com/mship-srpm1/%HASH%
)
# These are glob patterns. They should be in the same order as the lookasides
# above and need to be quoted to avoid early glob expansion.
remotes=(
'@(git@|http?(s)://)git.rockylinux.org*'
'@(git@|http?(s)://)git.rockylinux.org*'
'@(ssh://git@|http?(s)://)git.centos.org/*'
'@(ssh://git@|http?(s)://)gitlab.com[:/]redhat/centos-stream/*'
'@(ssh://git@|http?(s)://)src.fedoraproject.org/*'
'@(git@|http?(s)://)github.com[:/]openela-main/*'
)
# These are branch names that will be glob-matched to to the lookasides above.
# Missing entries or empty strings will default to matching any branch.
branches=(
r8
r9
''
''
''
''
)
declare -A macros
#
# Get the hash type for a given hash. Based on the length of the hash.
#
shasizes=(
[32]=md5
[40]=sha1
[64]=sha256
[96]=sha384
[128]=sha512
)
hashtype () {
printf '%s' "${shasizes[${#1}]}"
}
#
# Validate a file against the passed hash.
# Synopsis: check_file filename hash [hashtype]
#
check_file () {
[[ -r $1 ]] || return
local type
if (( $# >= 3 )); then
type=$3
else
type=$(hashtype "$2")
fi
# We use one of the "sum" commands, so the command name is the type followed
# by "sum".
"${type}sum" --status -c - <<<"$2 $1"
}
###
# Function that actually downloads a lookaside source
# Takes HASH / FILENAME / BRANCH / PKG / SHATYPE as arguments $1 / $2 / $3 / $4 / $5
function download {
# If the file already exists and matches the checksum then we don't need to
# download it again.
if check_file "${macros[FILENAME]}" "${macros[HASH]}" "${macros[SHATYPE]}"
then
printf 'File %s already exists and matches the passed hash ... %s\n' \
"${macros[FILENAME]}" 'skipping.'
return
fi
# We need to re-order the lookasides according to the remote and branch
# macro entries.
local -a urls
local -A tried
# Start by looking for matching entries
if [[ ${macros[REMOTE]} ]]; then
shopt -s nocasematch
for ((i=0; i<${#lookasides[@]}; i++)); do
# shellcheck disable=SC2053
[[ ${macros[REMOTE]} == ${remotes[i]} ]] || continue
# shellcheck disable=SC2053
[[ ${macros[BRANCH]} == ${branches[i]:=\*} ]] || continue
urls+=("${lookasides[i]}")
tried[${lookasides[i]}]=1
done
shopt -u nocasematch
fi
# Then pile the rest of the URLs onto the end.
for url in "${lookasides[@]}"; do
[[ ${tried[$url]} ]] && continue
urls+=("$url")
tried[$url]=1
done
for url in "${urls[@]}"; do
# Substitute each of our macros (%PKG%, %HASH%, etc.):
for k in "${!macros[@]}"; do
v=${macros[$k]}
url=${url//"%$k%"/$v}
done
# Download the file with curl, return if successful.
printf 'Trying: %s\n' "$url"
curl --create-dirs -sfLRo "${macros[FILENAME]}" "$url" || continue
check_file "${macros[FILENAME]}" "${macros[HASH]}" \
"${macros[SHATYPE]}" || {
printf 'Invalid or corrupted file downloaded. Trying next URL.\n'
continue
}
printf 'Downloaded: %s -----> %s\n' "$url" "${macros[FILENAME]}"
return
done
echo "ERROR: Unable to find lookaside file with the following HASH / FILENAME / BRANCH / PKG / SHATYPE :"
echo "${macros[HASH]} / ${macros[FILENAME]} / ${macros[BRANCH]} / ${macros[PKG]} / ${macros[SHATYPE]}"
exit 1
}
###
# discover our list of lookaside sources. They are either in a "sources" file (new), or the older ".packagename.metadata" format (old)
sourcesfiles=(.*.metadata sources)
mapfile -t sourcelines < <(cat "${sourcesfiles[@]}" 2>/dev/null)
if (( ${#sourcelines[@]} == 0 )); then
echo "ERROR: Cannot find .*.metadata or sources file listing sources. Are you in the right directory?"
exit 1
fi
# Current git branch. We don't error out if this fails, as we may not necessarily need this info
macros[BRANCH]=$(git status | sed -n 's/.*On branch //p')
# Source package name should match the specfile - we'll use that in lieu of parsing "Name:" out of it
# There could def. be a better way to do this....
# UPDATE: The better way is to use rpmspec, but this may not be installed, so
# fall back to the old way if it isn't.
specfile=(*.spec SPECS/*.spec)
if (( ${#specfile[@]}!= 1 )); then
echo "ERROR: Exactly one spec file expected, ${#specfile[@]} found."
exit 1
fi
macros[PKG]=$(rpmspec -q --qf '%{NAME}\n' --srpm "${specfile[0]}" 2>/dev/null) || {
pkg=${specfile[0]##*/}
macros[PKG]=${pkg%.spec}
}
if (( ${#macros[PKG]} < 2 )); then
echo "ERROR: Having trouble finding the name of the package based on the name of the .spec file."
exit 1
fi
# Get the remote origin from git if we can. This is not required but it will
# help us to determine which lookaside URL to try first.
# We look for a fetch remote tagged with origin, otherwise we get the first
# fetch remote that is returned.
macros[REMOTE]=""
while read -r name url direction; do
# Make sure the direction is fetch.
[[ $direction == '(fetch)' ]] || continue
# If the name is "origin" we need to use this url.
if [[ $name == 'origin' ]]; then
macros[REMOTE]=$url
break
fi
# Otherwise we set the first url we encounter here.
[[ ${macros[REMOTE]} ]] || macros[REMOTE]=$url
done < <(git remote -v)
# Loop through each line of our looksaide, and download the file:
# Regexes to determine which type of line it is and match the fields.
new_re='^([a-z]+[0-9]+) \(([^\)]+)\) = ([0-9a-f]+)$'
old_re='^([0-9a-f]+) ([^ ]+)$'
# Regex used for skipping lines with only whitespace.
skip_re='^[[:space:]]*$'
for line in "${sourcelines[@]}"; do
macros[SHATYPE]=""
shopt -s nocasematch
if [[ $line =~ $new_re ]]; then
# This is a new-style line: "SHATYPE (NAME) = HASH"
macros[SHATYPE]=${BASH_REMATCH[1],,}
macros[FILENAME]=${BASH_REMATCH[2]}
macros[HASH]=${BASH_REMATCH[3]}
elif [[ $line =~ $old_re ]]; then
# This is an old-style line: "HASH NAME"
macros[HASH]=${BASH_REMATCH[1]}
macros[FILENAME]=${BASH_REMATCH[2]}
elif [[ $line =~ $skip_re ]]; then
# This line just has whitespace, skip it.
continue
else
echo "ERROR: This lookaside line does not appear to have 2 or 4 space-separated fields. I don't know how to parse this line:"
printf '%s\n' "$line"
exit 1
fi
shopt -u nocasematch
# We have a hash and a filename, now we need to find the hash type (based on string length):
# UPDATE: We don't need to do this if we already have it from the line.
if [[ ! ${macros[SHATYPE]} ]]; then
macros[SHATYPE]=$(hashtype "${macros[HASH]}")
fi
# Finally, we have all our information call the download function with the relevant variables:
download
done