1 |
EGO_SUM mode now supplements the existing EGO_VENDOR mode. |
2 |
|
3 |
EGO_SUM should be populated by the maintainer, directly from the go.sum |
4 |
file of the root package. See eclass and conversion example |
5 |
(dev-go/go-tour & app-admin/kube-bench) for further details. |
6 |
|
7 |
The go-module_set_globals function performs validation of |
8 |
inputs and does die on fatal errors. |
9 |
|
10 |
Signed-off-by: Robin H. Johnson <robbat2@g.o> |
11 |
--- |
12 |
eclass/go-module.eclass | 328 +++++++++++++++++++++++++++++++++++-- |
13 |
profiles/thirdpartymirrors | 1 + |
14 |
2 files changed, 311 insertions(+), 18 deletions(-) |
15 |
|
16 |
diff --git eclass/go-module.eclass eclass/go-module.eclass |
17 |
index d5de5f60ccdf..b8a635d52de7 100644 |
18 |
--- eclass/go-module.eclass |
19 |
+++ eclass/go-module.eclass |
20 |
@@ -4,22 +4,46 @@ |
21 |
# @ECLASS: go-module.eclass |
22 |
# @MAINTAINER: |
23 |
# William Hubbs <williamh@g.o> |
24 |
+# @AUTHOR: |
25 |
+# William Hubbs <williamh@g.o> |
26 |
+# Robin H. Johnson <robbat2@g.o> |
27 |
# @SUPPORTED_EAPIS: 7 |
28 |
# @BLURB: basic eclass for building software written as go modules |
29 |
# @DESCRIPTION: |
30 |
-# This eclass provides basic settings and functions |
31 |
-# needed by all software written in the go programming language that uses |
32 |
-# go modules. |
33 |
+# This eclass provides basic settings and functions needed by all software |
34 |
+# written in the go programming language that uses go modules. |
35 |
+# |
36 |
+# You might know the software you are packaging uses modules because |
37 |
+# it has files named go.sum and go.mod in its top-level source directory. |
38 |
+# If it does not have these files, try use the golang-* eclasses FIRST! |
39 |
+# There ARE legacy Golang packages that use external modules with none of |
40 |
+# go.mod, go.sum, vendor/ that can use this eclass regardless. |
41 |
+# |
42 |
+# Guidelines for usage: |
43 |
+# "go.mod" && "go.sum" && "vendor/": |
44 |
+# - pre-vendored package. Do NOT set EGO_SUM or EGO_VENDOR. |
45 |
+# |
46 |
+# "go.mod" && "go.sum": |
47 |
+# - Populate EGO_SUM with entries from go.sum |
48 |
+# - Do NOT include any lines that contain <version>/go.mod |
49 |
+# |
50 |
+# "go.mod" only: |
51 |
+# - Populate EGO_VENDOR |
52 |
# |
53 |
-# You will know the software you are packaging uses modules because |
54 |
-# it will have files named go.sum and go.mod in its top-level source |
55 |
-# directory. If it does not have these files, use the golang-* eclasses. |
56 |
+# None of the above: |
57 |
+# - Did you try golang-* eclasses first? Upstream has undeclared dependencies |
58 |
+# (perhaps really old source). You can use either EGO_SUM or EGO_VENDOR. |
59 |
+ |
60 |
# |
61 |
-# If it has these files and a directory named vendor in its top-level |
62 |
-# source directory, you only need to inherit the eclass since upstream |
63 |
-# is vendoring the dependencies. |
64 |
+# If it has these files AND a directory named "vendor" in its top-level source |
65 |
+# directory, you only need to inherit the eclass since upstream has already |
66 |
+# vendored the dependencies. |
67 |
+ |
68 |
+# If it does not have a vendor directory, you should use the EGO_SUM |
69 |
+# variable and the go-module_gosum_uris function as shown in the |
70 |
+# example below to handle dependencies. |
71 |
# |
72 |
-# If it does not have a vendor directory, you should use the EGO_VENDOR |
73 |
+# Alternatively, older versions of this eclass used the EGO_VENDOR |
74 |
# variable and the go-module_vendor_uris function as shown in the |
75 |
# example below to handle dependencies. |
76 |
# |
77 |
@@ -28,6 +52,21 @@ |
78 |
# dependencies. So please make sure it is accurate. |
79 |
# |
80 |
# @EXAMPLE: |
81 |
+# @CODE |
82 |
+# |
83 |
+# inherit go-module |
84 |
+# |
85 |
+# EGO_SUM=( |
86 |
+# "github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=" |
87 |
+# "github.com/BurntSushi/toml v0.3.1/go.mod h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=" |
88 |
+# ) |
89 |
+# S="${WORKDIR}/${MY_P}" |
90 |
+# go-module_set_globals |
91 |
+# |
92 |
+# SRC_URI="https://github.com/example/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz |
93 |
+# ${EGO_SUM_SRC_URI}" |
94 |
+# |
95 |
+# @CODE |
96 |
# |
97 |
# @CODE |
98 |
# |
99 |
@@ -35,7 +74,7 @@ |
100 |
# |
101 |
# EGO_VENDOR=( |
102 |
# "github.com/xenolf/lego 6cac0ea7d8b28c889f709ec7fa92e92b82f490dd" |
103 |
-# "golang.org/x/crypto 453249f01cfeb54c3d549ddb75ff152ca243f9d8 github.com/golang/crypto" |
104 |
+# "golang.org/x/crypto 453249f01cfeb54c3d549ddb75ff152ca243f9d8 github.com/golang/crypto" |
105 |
# ) |
106 |
# |
107 |
# SRC_URI="https://github.com/example/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz |
108 |
@@ -64,10 +103,12 @@ export GO111MODULE=on |
109 |
export GOCACHE="${T}/go-build" |
110 |
|
111 |
# The following go flags should be used for all builds. |
112 |
-# -mod=vendor stopps downloading of dependencies from the internet. |
113 |
# -v prints the names of packages as they are compiled |
114 |
# -x prints commands as they are executed |
115 |
-export GOFLAGS="-mod=vendor -v -x" |
116 |
+# -mod=vendor use the vendor directory instead of downloading dependencies |
117 |
+# -mod=readonly do not update go.mod/go.sum but fail if updates are needed |
118 |
+export GOFLAGS="-v -x -mod=readonly" |
119 |
+[[ ${#EGO_VENDOR[@]} -gt 0 ]] && GOFLAGS+=" -mod=vendor" |
120 |
|
121 |
# Do not complain about CFLAGS etc since go projects do not use them. |
122 |
QA_FLAGS_IGNORED='.*' |
123 |
@@ -75,7 +116,23 @@ QA_FLAGS_IGNORED='.*' |
124 |
# Go packages should not be stripped with strip(1). |
125 |
RESTRICT="strip" |
126 |
|
127 |
-EXPORT_FUNCTIONS src_unpack pkg_postinst |
128 |
+EXPORT_FUNCTIONS src_unpack src_prepare pkg_postinst |
129 |
+ |
130 |
+# @ECLASS-VARIABLE: EGO_SUM |
131 |
+# @DESCRIPTION: |
132 |
+# This variable duplicates the go.sum content from inside the target package. |
133 |
+# Entries of the form <version>/go.mod should be excluded. |
134 |
+# |
135 |
+# <module> <version> <hash> |
136 |
+# |
137 |
+# The format is described upstream here: |
138 |
+# https://tip.golang.org/cmd/go/#hdr-Module_authentication_using_go_sum |
139 |
+# |
140 |
+# <hash> is the Hash1 structure used by upstream Go |
141 |
+# Note that Hash1 is MORE stable than Gentoo distfile hashing, and upstream |
142 |
+# warns that it's conceptually possible for the Hash1 value to remain stable |
143 |
+# while the upstream zipfiles change. E.g. it does NOT capture mtime changes in |
144 |
+# files within a zipfile. |
145 |
|
146 |
# @ECLASS-VARIABLE: EGO_VENDOR |
147 |
# @DESCRIPTION: |
148 |
@@ -106,13 +163,202 @@ go-module_vendor_uris() { |
149 |
done |
150 |
} |
151 |
|
152 |
+# @ECLASS-VARIABLE: GOMODULE_GOPROXY_BASEURI |
153 |
+# @DESCRIPTION: |
154 |
+# Golagg module proxy service to fetch module files from. Note that the module |
155 |
+# proxy generally verifies modules via the Hash1 code. |
156 |
+# |
157 |
+# Note: Users in China may find some mirrors in the list blocked, and may wish |
158 |
+# to an explicit entry to /etc/portage/mirrors pointing mirror://goproxy/ to |
159 |
+# https://goproxy.cn/, or change this variable. |
160 |
+# See https://arslan.io/2019/08/02/why-you-should-use-a-go-module-proxy/ for further details |
161 |
+: "${GOMODULE_GOPROXY_BASEURI:=mirror://goproxy/}" |
162 |
+ |
163 |
+# @FUNCTION: go-module_set_globals |
164 |
+# @DESCRIPTION: |
165 |
+# Convert the information in EGO_SUM for other usage in the ebuild. |
166 |
+# - Populates EGO_SUM_SRC_URI that can be added to SRC_URI |
167 |
+# - Exports _EGO_SUM_MAPPING which provides reverse mapping from distfile back |
168 |
+# to the relative part of SRC_URI, as needed for GOPROXY=file:///... |
169 |
+go-module_set_globals() { |
170 |
+ local line error_in_gosum errorlines errormsg exts |
171 |
+ local newline=$'\n' |
172 |
+ error_in_gosum=0 |
173 |
+ errorlines=( ) |
174 |
+ for line in "${EGO_SUM[@]}"; do |
175 |
+ local module version modfile version_modfile hash1 x |
176 |
+ read -r module version_modfile hash1 x <<< "${line}" |
177 |
+ # Validate input |
178 |
+ if [[ -n $hash1 ]] && [[ ${hash1:0:3} != "h1:" ]] ; then |
179 |
+ error_in_gosum=1 |
180 |
+ errorlines+=( "Unknown hash: ${line}" ) |
181 |
+ elif [[ -n $x ]]; then |
182 |
+ error_in_gosum=1 |
183 |
+ errorlines+=( "Trailing data: ${line}" ) |
184 |
+ fi |
185 |
+ |
186 |
+ # Split 'v0.3.0/go.mod' into 'v0.3.0' and '/go.mod' |
187 |
+ version=${version_modfile%%/*} |
188 |
+ modfile=${version_modfile#*/} |
189 |
+ [[ "$modfile" == "${version_modfile}" ]] && modfile= |
190 |
+ |
191 |
+ # The trailing part should be either empty or '/go.mod' |
192 |
+ # There is a chance that upstream Go might add something else here in |
193 |
+ # future, and we should be prepared to capture it. |
194 |
+ exts=() |
195 |
+ errormsg='' |
196 |
+ case "$modfile" in |
197 |
+ '') exts=( mod info zip ) ;; |
198 |
+ 'go.mod'|'/go.mod') exts=( mod info ) ;; |
199 |
+ #'go.mod'|'/go.mod') errormsg="Prohibited file: You must exclude /go.mod lines from EGO_SUM! " ;; |
200 |
+ *) errormsg="Unknown modfile: line='${line}', modfile='${modfile}'" ;; |
201 |
+ esac |
202 |
+ |
203 |
+ # If it was a bad entry, restart the loop |
204 |
+ if [[ -n $errormsg ]]; then |
205 |
+ error_in_gosum=1 |
206 |
+ errorlines+=( "${errormsg} line='${line}', modfile='${modfile}'" ) |
207 |
+ continue |
208 |
+ fi |
209 |
+ |
210 |
+ # Directory structure for Go proxy hosts: |
211 |
+ # - def encode(s): |
212 |
+ # return re.sub('([A-Z]{1})', r'!\1', s).lower() |
213 |
+ # |
214 |
+ # Sed variant: |
215 |
+ # This uses GNU Sed extension \l to downcase the match |
216 |
+ #_dir=$(echo "${module}" |sed 's,[A-Z],!\l&,g') |
217 |
+ # |
218 |
+ # Bash variant: |
219 |
+ re='(.*)([A-Z])(.*)' |
220 |
+ input=${module} |
221 |
+ while [[ $input =~ $re ]]; do |
222 |
+ lower='!'"${BASH_REMATCH[2],}" |
223 |
+ input="${BASH_REMATCH[1]}${lower}${BASH_REMATCH[3]}" |
224 |
+ done |
225 |
+ _dir=$input |
226 |
+ unset lower input re |
227 |
+ |
228 |
+ for _ext in "${exts[@]}" ; do |
229 |
+ # Relative URI within a GOPROXY for a file |
230 |
+ _reluri="${_dir}/@v/${version}.${_ext}" |
231 |
+ # SRC_URI: LHS entry |
232 |
+ _uri="${GOMODULE_GOPROXY_BASEURI}/${_reluri}" |
233 |
+ # SRC_URI: RHS entry, encode any slash in the path as %2F in the filename |
234 |
+ _distfile="${_reluri//\//%2F}" |
235 |
+ |
236 |
+ EGO_SUM_SRC_URI+=" ${_uri} -> ${_distfile}${newline}" |
237 |
+ _EGO_SUM_MAPPING+=" ${_distfile}:${_reluri}${newline}" |
238 |
+ done |
239 |
+ done |
240 |
+ |
241 |
+ if [[ $error_in_gosum != 0 ]]; then |
242 |
+ eerror "Trailing information in EGO_SUM in ${P}.ebuild" |
243 |
+ for line in "${errorlines[@]}" ; do |
244 |
+ eerror "${line}" |
245 |
+ done |
246 |
+ die "Invalid EGO_SUM format" |
247 |
+ fi |
248 |
+ |
249 |
+ # Ensure these variables not not changed past this point |
250 |
+ readonly EGO_SUM |
251 |
+ readonly EGO_SUM_SRC_URI |
252 |
+ readonly _EGO_SUM_MAPPING |
253 |
+ |
254 |
+ # Set the guard that we are safe |
255 |
+ _GO_MODULE_SET_GLOBALS_CALLED=1 |
256 |
+} |
257 |
+ |
258 |
+ |
259 |
# @FUNCTION: go-module_src_unpack |
260 |
# @DESCRIPTION: |
261 |
+# Extract & configure Go modules for consumpations. |
262 |
+# - Modules listed in EGO_SUM are configured as a local GOPROXY via symlinks (fast!) |
263 |
+# - Modules listed in EGO_VENDOR are extracted to "${S}/vendor" (slow) |
264 |
+# |
265 |
+# This function does NOT unpack the base distfile of a Go-based package. |
266 |
+# While the entries in EGO_SUM will be listed in ${A}, they should NOT be |
267 |
+# unpacked, Go will directly consume the files, including zips. |
268 |
+go-module_src_unpack() { |
269 |
+ if [[ "${#EGO_VENDOR[@]}" -gt 0 ]]; then |
270 |
+ _go-module_src_unpack_vendor |
271 |
+ elif [[ "${#EGO_SUM[@]}" -gt 0 ]]; then |
272 |
+ _go-module_src_unpack_gosum |
273 |
+ else |
274 |
+ die "Neither EGO_SUM nor EGO_VENDOR are set!" |
275 |
+ fi |
276 |
+} |
277 |
+ |
278 |
+# @FUNCTION: go-module_src_prepare |
279 |
+# @DESCRIPTION: |
280 |
+# Prepare for building. Presently only needed for EGO_SUM variant. |
281 |
+go-module_src_prepare() { |
282 |
+ # shellcheck disable=SC2120 |
283 |
+ debug-print-function "${FUNCNAME}" "$@" |
284 |
+ |
285 |
+ if [[ "${#EGO_SUM[@]}" -gt 0 ]]; then |
286 |
+ _go-module_src_prepare_gosum |
287 |
+ fi |
288 |
+ |
289 |
+ default |
290 |
+} |
291 |
+ |
292 |
+# @ECLASS-VARIABLE: GOMODULE_GOSUM_PATH |
293 |
+# @DESCRIPTION: |
294 |
+# Path to root go.sum of package. If your ebuild modifies S after inheriting |
295 |
+# the eclass, you may need to update this variable. |
296 |
+: "${GO_MODULE_GOSUM_PATH:=${S}/go.sum}" |
297 |
+ |
298 |
+# @FUNCTION: _go-module_src_unpack_gosum |
299 |
+# @DESCRIPTION: |
300 |
+# Populate a GOPROXY directory hierarchy with distfiles from EGO_SUM |
301 |
+# |
302 |
+# Exports GOPROXY environment variable so that Go calls will source the |
303 |
+# directory correctly. |
304 |
+_go-module_src_unpack_gosum() { |
305 |
+ # shellcheck disable=SC2120 |
306 |
+ debug-print-function "${FUNCNAME}" "$@" |
307 |
+ |
308 |
+ if [[ ! ${_GO_MODULE_SET_GLOBALS_CALLED} ]]; then |
309 |
+ die "go-module_set_globals must be called in global scope" |
310 |
+ fi |
311 |
+ |
312 |
+ local goproxy_dir="${T}/goproxy" |
313 |
+ local goproxy_mod_dir |
314 |
+ mkdir -p "${goproxy_dir}" |
315 |
+ # Convert the list format to an associative array to avoid O(N*M) |
316 |
+ # performance when populating the GOPROXY directory structure. |
317 |
+ declare -A _EGO_SUM_MAPPING_ASSOC |
318 |
+ for s in ${_EGO_SUM_MAPPING}; do |
319 |
+ a=${s//:*} |
320 |
+ b=${s//*:} |
321 |
+ _EGO_SUM_MAPPING_ASSOC["$a"]=$b |
322 |
+ done |
323 |
+ |
324 |
+ # For each Golang module distfile, look up where it's supposed to go, and |
325 |
+ # symlink into place. |
326 |
+ for _A in ${A}; do |
327 |
+ goproxy_mod_path="${_EGO_SUM_MAPPING_ASSOC["${_A}"]}" |
328 |
+ if [[ -n "${goproxy_mod_path}" ]]; then |
329 |
+ einfo "Populating goproxy for $goproxy_mod_path" |
330 |
+ # Build symlink hierarchy |
331 |
+ goproxy_mod_dir=$( dirname "${goproxy_dir}"/"${goproxy_mod_path}" ) |
332 |
+ mkdir -p "${goproxy_mod_dir}" |
333 |
+ ln -sf "${DISTDIR}"/"${_A}" "${goproxy_dir}/${goproxy_mod_path}" || die "Failed to ln" |
334 |
+ fi |
335 |
+ done |
336 |
+ export GOPROXY="file://${goproxy_dir}" |
337 |
+ unset _EGO_SUM_MAPPING_ASSOC |
338 |
+} |
339 |
+ |
340 |
+# @FUNCTION: _go-module_src_unpack_vendor |
341 |
+# @DESCRIPTION: |
342 |
# Extract all archives in ${a} which are not nentioned in ${EGO_VENDOR} |
343 |
# to their usual locations then extract all archives mentioned in |
344 |
# ${EGO_VENDOR} to ${S}/vendor. |
345 |
-go-module_src_unpack() { |
346 |
- debug-print-function ${FUNCNAME} "$@" |
347 |
+_go-module_src_unpack_vendor() { |
348 |
+ # shellcheck disable=SC2120 |
349 |
+ debug-print-function "${FUNCNAME}" "$@" |
350 |
local f hash import line repo tarball vendor_tarballs x |
351 |
vendor_tarballs=() |
352 |
for line in "${EGO_VENDOR[@]}"; do |
353 |
@@ -145,13 +391,59 @@ go-module_src_unpack() { |
354 |
done |
355 |
} |
356 |
|
357 |
+# @FUNCTION: _go-module_src_prepare_gosum |
358 |
+# @DESCRIPTION: |
359 |
+# Validate the Go modules declared by EGO_SUM are sufficent to cover building |
360 |
+# the package, without actually building it yet. |
361 |
+_go-module_src_prepare_gosum() { |
362 |
+ # shellcheck disable=SC2120 |
363 |
+ debug-print-function "${FUNCNAME}" "$@" |
364 |
+ |
365 |
+ if [[ ! ${_GO_MODULE_SET_GLOBALS_CALLED} ]]; then |
366 |
+ die "go-module_set_globals must be called in global scope" |
367 |
+ fi |
368 |
+ |
369 |
+ # go.sum entries ending in /go.mod aren't strictly needed at this phase |
370 |
+ if [[ ! -e "${GO_MODULE_GOSUM_PATH}" ]]; then |
371 |
+ die "Could not find package root go.sum, please update GO_MODULE_GOSUM_PATH" |
372 |
+ fi |
373 |
+ go-module_minimize_gosum "${GO_MODULE_GOSUM_PATH}" |
374 |
+ |
375 |
+ # Verify that all needed modules are present. |
376 |
+ GO111MODULE=on \ |
377 |
+ go get -v -d -mod readonly || die "Some module is missing, update EGO_SUM" |
378 |
+ |
379 |
+ # Need to re-minimize because go-get expands it again |
380 |
+ go-module_minimize_gosum "${GO_MODULE_GOSUM_PATH}" |
381 |
+} |
382 |
+ |
383 |
+# @FUNCTION: go-module_minimize_gosum |
384 |
+# @DESCRIPTION: |
385 |
+# Remove all /go.mod entries from go.sum files |
386 |
+# In most cases, if go.sum only has a /go.mod entry without a corresponding |
387 |
+# direct entry, this is a sign of a weak dependency that is NOT required for |
388 |
+# building the package. |
389 |
+go-module_minimize_gosum() { |
390 |
+ local gosumfile=${1} |
391 |
+ if test ! -e "${gosumfile}".orig; then |
392 |
+ cp -f "${gosumfile}"{,.orig} || die |
393 |
+ fi |
394 |
+ awk -e '$2 ~ /\/go.mod$/{next} {print}' \ |
395 |
+ <"${gosumfile}".orig \ |
396 |
+ >"${gosumfile}" || die |
397 |
+ if grep -sq /go.mod "${gosumfile}"; then |
398 |
+ die "sed failed to remove all module go.mod entries from go.sum" |
399 |
+ fi |
400 |
+} |
401 |
+ |
402 |
# @FUNCTION: go-module_live_vendor |
403 |
# @DESCRIPTION: |
404 |
# This function is used in live ebuilds to vendor the dependencies when |
405 |
# upstream doesn't vendor them. |
406 |
go-module_live_vendor() { |
407 |
- debug-print-function ${FUNCNAME} "$@" |
408 |
+ debug-print-function "${FUNCNAME}" "$@" |
409 |
|
410 |
+ # shellcheck disable=SC2086 |
411 |
has live ${PROPERTIES} || |
412 |
die "${FUNCNAME} only allowed in live ebuilds" |
413 |
[[ "${EBUILD_PHASE}" == unpack ]] || |
414 |
@@ -168,7 +460,7 @@ go-module_live_vendor() { |
415 |
# @DESCRIPTION: |
416 |
# Display a warning about security updates for Go programs. |
417 |
go-module_pkg_postinst() { |
418 |
- debug-print-function ${FUNCNAME} "$@" |
419 |
+ debug-print-function "${FUNCNAME}" "$@" |
420 |
[[ -n ${REPLACING_VERSIONS} ]] && return 0 |
421 |
ewarn "${PN} is written in the Go programming language." |
422 |
ewarn "Since this language is statically linked, security" |
423 |
diff --git profiles/thirdpartymirrors profiles/thirdpartymirrors |
424 |
index ad4c4b972146..d60f166e07c9 100644 |
425 |
--- profiles/thirdpartymirrors |
426 |
+++ profiles/thirdpartymirrors |
427 |
@@ -25,3 +25,4 @@ sourceforge https://download.sourceforge.net |
428 |
sourceforge.jp http://iij.dl.sourceforge.jp https://osdn.dl.sourceforge.jp https://jaist.dl.sourceforge.jp |
429 |
ubuntu http://mirror.internode.on.net/pub/ubuntu/ubuntu/ https://mirror.tcc.wa.edu.au/ubuntu/ http://ubuntu.uni-klu.ac.at/ubuntu/ http://mirror.dhakacom.com/ubuntu-archive/ http://ubuntu.c3sl.ufpr.br/ubuntu/ http://ubuntu.uni-sofia.bg/ubuntu/ http://hr.archive.ubuntu.com/ubuntu/ http://cz.archive.ubuntu.com/ubuntu/ https://mirror.dkm.cz/ubuntu http://ftp.cvut.cz/ubuntu/ http://ftp.stw-bonn.de/ubuntu/ https://ftp-stud.hs-esslingen.de/ubuntu/ https://mirror.netcologne.de/ubuntu/ https://mirror.unej.ac.id/ubuntu/ http://kr.archive.ubuntu.com/ubuntu/ https://mirror.nforce.com/pub/linux/ubuntu/ http://mirror.amsiohosting.net/archive.ubuntu.com/ http://nl3.archive.ubuntu.com/ubuntu/ https://mirror.timeweb.ru/ubuntu/ http://ubuntu.mirror.su.se/ubuntu/ https://ftp.yzu.edu.tw/ubuntu/ https://mirror.aptus.co.tz/pub/ubuntuarchive/ https://ubuntu.volia.net/ubuntu-archive/ https://mirror.sax.uk.as61049.net/ubuntu/ https://mirror.pnl.gov/ubuntu/ http://mirror.cc.columbia.edu/pub/linux/ubuntu/archive/ https://mirrors.namecheap.com/ubuntu/ |
430 |
vdr-developerorg http://projects.vdr-developer.org/attachments/download |
431 |
+goproxy https://proxy.golang.org/ https://goproxy.io/ https://gocenter.io/ |
432 |
-- |
433 |
2.25.0 |