OSDN Git Service

Update info
[rebornos/cnchi-gnome-osdn.git] / scripts / reflector-antergos
1 #!/bin/bash
2 #
3 # Generates to stdout a ranked Antergos mirror list that can be directly used as
4 # file /etc/pacman.d/antergos-mirrorlist.
5 #
6 # For optimizing performance
7 # - while searching the mirrors with this tool
8 # AND
9 # - while updating your system using the ranked mirrors
10 # you may exclude mirror countries (option --exclude-countries)
11 # or exclude groups of countries (--exclude-countrygroups), or individual mirrors (--exclude-mirrors).
12 #
13 # You can specify which protocols (https, http) are used (option --protocols).
14 #
15 # For more details, see below.
16 #
17 # Installation:
18 # - Copy this script into a file (e.g. /usr/bin/reflector-antergos or /usr/local/bin/reflector-antergos)
19 # and make it executable (e.g. chmod +x /usr/bin/reflector-antergos).
20 #
21 # NOTE1: for option --exclude-countries, in addition to country names you can
22 # give "reserved" word 'Automated'. The Automated excludes all
23 # automated mirrors (usually one or two).
24 # Single mirrors (URLs) can be excluded with option --exclude-mirrors.
25 #
26 # NOTE2: it is possible to manually edit and re-order mirrors
27 # in /etc/pacman.d/antergos-mirrorlist.
28 #
29 # Usage example:
30 # reflector-antergos --exclude-countrygroup=Asia2,Europe > ~/antergos-mirrorlist
31 # sudo mv -f /etc/pacman.d/antergos-mirrorlist /etc/pacman.d/antergos-mirrorlist.bak # optional: backup old file
32 # sudo mv -f ~/antergos-mirrorlist /etc/pacman.d/antergos-mirrorlist
33 #
34 # TODO:
35 # - Only http and https protocols are currently supported.
36 #
37 # Caveats:
38 # - This script assumes $INPUTFILE (antergos-mirrorlist, see function GetLatestInputFile below)
39 # is written using a certain format.
40 # If the format changes, this script must be modified accordingly
41 # (which may or may not be trivial).
42 #
43
44 OUTPUTFILE=/etc/pacman.d/antergos-mirrorlist
45 INPUTFILE="" # the latest available antergos-mirrorlist, downloaded!
46
47 EXCLUDEDCOUNTRYGROUPS=""
48 EXCLUDEDCOUNTRIES=""
49 EXCLUDEDMIRRORS=""
50 PROTOCOLS="http" # default protocol
51 INCLUDEDCOUNTRIES=""
52
53 REPO=antergos
54 ARCH=$(uname -m)
55
56 TMPDIR="$HOME/.rankingstuff.tmp.$$"
57 #TMPDIR="/tmp/.rankingstuff.tmp.$$"
58 RANKEDMIRRORS="$TMPDIR/rankedmirrors"
59 INSTALLER="$TMPDIR/installer.bash"
60
61 REFLECTOR_ANTERGOS_CONF=/etc/reflector-antergos.conf # may contain e.g. REFERENCEURL
62 if [ -f $REFLECTOR_ANTERGOS_CONF ] ; then
63 source $REFLECTOR_ANTERGOS_CONF
64 fi
65 if [ "$REFERENCEURL" = "" ] ; then
66 REFERENCEURL=http://mirrors.antergos.com/$REPO/$ARCH/main.files.tar.gz
67 fi
68
69 REFERENCEFILE="$TMPDIR/referencefile"
70 REFERENCESTAMP=0 # timestamp
71
72 FOUND_MIRRORS=0
73 SAVE_TO_FILE=false # false=output to standard output, true=to /etc/pacman.d/antergos-mirrorlist
74
75 HIDE_ORIGINAL_MIRRORS=yes # Controls how the original mirror list is appended after ranked mirrors.
76 # yes=hides original mirrors, no=don't hide original mirrors.
77
78 VERSION_STUB="$Id: reflector-antergos,v 1.34 2018/06/20 14:38:01 manuel Exp $"
79 VERSION=0.$(echo "$VERSION_STUB" | awk '{print $3}')
80
81 VERBOSE=1
82 DEBUG=0
83
84 TIME_CMD=/usr/bin/time
85 WGET_CMD=/usr/bin/wget
86
87 WGET_TIMEOUT=30 # seconds to wait for the mirror to respond
88
89 echo2() { echo "$@" >&2 ; }
90 verbose2() { test $VERBOSE -ne 0 && echo2 "$@" ; }
91 verbose2more() { test $VERBOSE -eq 2 && echo2 "$@" ; }
92 debug2() { test $DEBUG -eq 1 && echo2 "$@" ; }
93 printf2()
94 {
95 local fmt="$1"
96 shift
97 printf "$fmt" "$@" >&2
98 }
99
100 _runcheck()
101 {
102 "$@"
103 if [ $? -ne 0 ] ; then
104 echo2 "ERROR: command '$*' failed."
105 exit 1
106 fi
107 }
108
109 Usage()
110 {
111 case $VERBOSE in
112 1|2) cat <<EOF
113 Overview:
114
115 reflector-antergos generates (to stdout) a ranked Antergos mirror list
116 that can be directly used as file /etc/pacman.d/antergos-mirrorlist.
117
118 Version: $VERSION
119
120 Usage: $(basename $0) [options]
121 where 'options' are:
122 --exclude-countries=X,Y,Z,...
123 Exclude all mirrors from given countries.
124 Note1: If a country name includes spaces, e.g. Czech Republic,
125 convert spaces into underscores, e.g. Czech_Republic.
126 Note2: The word 'Automated' excludes all mirrors from section
127 'Automated Mirror Selection'.
128
129 --exclude-countrygroups=X,Y,Z,...
130 Exclude countries using group names: America, Asia, Asia2, Europe, Europe2
131 where Asia2 and Europe2 include Russia.
132
133 --exclude-mirrors=X,Y,Z,...
134 Exclude mirror urls that contain any of strings X, Y or Z as substring.
135
136 --include-countries=X,Y,Z,...
137 The opposite of --exclude-countries.
138 Note that this option cannot be used together with options to
139 exclude countries.
140
141 --save
142 Saves the ranked mirror list to file /etc/pacman.d/antergos-mirrorlist
143 and makes a backup of the previous file.
144 Note that usage of this option requires root permissions.
145 If this option is not used, the ranked mirror list is printed to standard output.
146
147 --hide-original-mirrors=X
148 As the original mirror list is appended to the ranking result,
149 this option controls whether original mirrors are hidden or not.
150 X=yes hides original mirrors (default).
151 X=no does not hide them.
152 Note that the original mirror list may contain some out-of-order mirrors.
153
154 --protocols=X,Y,...
155 Repo protocols in preference order (currently only https and http
156 are supported).
157
158 --timeout=seconds
159 Max time in seconds to wait for a mirror response. Default is $WGET_TIMEOUT.
160
161 --repo=X
162 X defaults to 'antergos'
163
164 --arch=X
165 X defaults to $(uname -m)
166
167 --quiet
168 Don't show progress info.
169
170 --verbose
171 Show more details about operation
172
173 --help
174 -h
175 This help.
176
177 Example:
178 $(basename $0) --exclude-countries=China,Russia,USA,Japan,Automated \\
179 --exclude-mirrors=sourceforge,mirrors.tuxns,antergos-mirror-a.alpix \\
180 --protocols=https,http
181
182 EOF
183 ;;
184 esac
185 }
186
187
188 wget_error()
189 {
190 # return as one word!
191 case "$1" in
192 0) echo "ok" ;;
193 1) echo "generic_error" ;;
194 2) echo "parse_error" ;;
195 3) echo "file_i/o_error" ;;
196 4) echo "network_failure" ;;
197 5) echo "ssl_verification_failure" ;;
198 6) echo "username/password_authentication_failure" ;;
199 7) echo "protocol_error" ;;
200 8) echo "server_issued_error" ;;
201 *) echo "(unknown_error)" ;;
202 esac
203 }
204
205 RankMirrorProtocol()
206 {
207 local mirrorarg="$1"
208 local country="$2"
209 local mirror=$(echo "$mirrorarg" | sed -e 's|\$repo|'$REPO'|' -e 's|\$arch|'$ARCH'|')
210 local mirrorurl="$mirror/$(basename $REFERENCEURL)"
211 local mirrorfile="$TMPDIR/mirrorfile"
212 local mirrordata="$TMPDIR/mirrordata"
213 local result
214 local downloadtime=-1
215 local status=ok
216 local timestamp
217 local xx
218 local hide
219
220 for xx in $EXCLUDEDMIRRORS
221 do
222 if [[ "$mirror" =~ "$xx" ]] ; then
223 return
224 fi
225 done
226
227 verbose2 " $mirrorarg"
228
229 rm -f "$mirrorfile"
230
231 $TIME_CMD -f %e $WGET_CMD --timeout=$WGET_TIMEOUT --tries=1 -q -O "$mirrorfile" "$mirrorurl" 2>"$mirrordata" 1>/dev/null
232 result=$?
233
234 if [ $result -eq 0 ] ; then
235 downloadtime=$(cat "$mirrordata" | tr '.' ',')
236 timestamp=$(stat -c %Y "$mirrorfile")
237
238 #verbose2 "vertailu: $timestamp $REFERENCESTAMP"
239 if [[ "$timestamp" < "$REFERENCESTAMP" ]] ; then
240 status="outdated"
241 result=1
242 elif [ "$(cmp "$mirrorfile" "$REFERENCEFILE")" != "" ] ; then
243 status="contents_differ"
244 result=1
245 fi
246 else
247 status=$(wget_error $result) # file download problem
248 fi
249
250 if [ "$status" != "ok" ] ; then
251 hide="#"
252
253 echo2 "status = $status"
254 case "$status" in
255 outdated) echo2 "timestamp = $timestamp refstamp = $REFERENCESTAMP" ;;
256 *) ;;
257 esac
258 else
259 ((FOUND_MIRRORS++))
260 fi
261 printf "%sServer = %s ############# downloadtime: %5s status: %s %s\n" \
262 "$hide" "$mirrorarg" "$downloadtime" "$status" "$country" >> "$RANKEDMIRRORS"
263
264 return $result
265 }
266
267 RankMirror()
268 {
269 local mirror="$1"
270 local country="$2"
271 local protocol
272 local m
273
274 for protocol in $PROTOCOLS
275 do
276 m=$(echo "$mirror" | sed 's|^[a-z]*://|'$protocol'://|')
277 RankMirrorProtocol "$m" "$country"
278 done
279 }
280
281 RankCountryMirrors()
282 {
283 local country="$1"
284 local mirror
285 local mirrors
286
287 if [ "$country" = "Automated" ] ; then
288 mirrors=$(grep -A 5 "^# [ ]*Automated Mirror" "$INPUTFILE" | grep "^Server = " | awk '{print $3}')
289 else
290 local country2=$(echo $country | sed 's|_.*$||') # remove first underscore (and tail) that may have been put there
291 country=$(echo $country | sed 's|_| |g') # restore the original country name!
292 mirrors=$(sed -n '/# '$country2'/,/^$/ p' $INPUTFILE | sed '1d;$d' | awk '{print $3}')
293 fi
294
295 verbose2 "$country:"
296 for mirror in $mirrors
297 do
298 RankMirror "$mirror" "$country"
299 done
300 }
301
302 SortMirrors()
303 {
304 local protocol
305
306 mv "$RANKEDMIRRORS" "$RANKEDMIRRORS".tmp
307
308 for protocol in $PROTOCOLS
309 do
310 grep "Server = $protocol://" "$RANKEDMIRRORS".tmp | sort -g -k 6 >> "$RANKEDMIRRORS"
311 done
312 rm -f "$RANKEDMIRRORS".tmp
313 }
314
315 RemoveCommentsOnServerLines()
316 {
317 mv "$RANKEDMIRRORS" "$RANKEDMIRRORS".tmp
318 cat "$RANKEDMIRRORS".tmp | sed 's|/\$arch[ ]*#|/\$arch\n#|' > "$RANKEDMIRRORS"
319 rm -f "$RANKEDMIRRORS".tmp
320 }
321
322 AddHeaderToFile()
323 {
324 local program=$(basename $0)
325
326 mv "$RANKEDMIRRORS" "$RANKEDMIRRORS".tmp
327 echo "## Generated by $program (version $VERSION) at $(date)." >> "$RANKEDMIRRORS"
328 echo "##" >> "$RANKEDMIRRORS"
329 echo "## Options used: $COMMAND_LINE" >> "$RANKEDMIRRORS"
330 echo "##" >> "$RANKEDMIRRORS"
331 cat "$RANKEDMIRRORS".tmp >> "$RANKEDMIRRORS"
332 if [ -f "$INPUTFILE" ] ; then
333 echo "" >> "$RANKEDMIRRORS"
334 echo "" >> "$RANKEDMIRRORS"
335 echo "#############################################################" >> "$RANKEDMIRRORS"
336 echo "############## Original antergos-mirrorlist: ################" >> "$RANKEDMIRRORS"
337 echo "#############################################################" >> "$RANKEDMIRRORS"
338 echo "" >> "$RANKEDMIRRORS"
339 case "$HIDE_ORIGINAL_MIRRORS" in
340 yes|y|Y|true|on|1)
341 cat "$INPUTFILE" | sed -e 's|^#Server = |##Server = |' -e 's|^Server = |#Server = |' >> "$RANKEDMIRRORS" # original mirrors commented out
342 ;;
343 *)
344 cat "$INPUTFILE" >> "$RANKEDMIRRORS"
345 ;;
346 esac
347 fi
348 rm -f "$RANKEDMIRRORS".tmp
349 }
350
351 ShowMirrorlist()
352 {
353 case "$SAVE_TO_FILE" in
354 true)
355 sudo mv -f "$OUTPUTFILE" "$OUTPUTFILE".bak
356 sudo cp -f "$RANKEDMIRRORS" "$OUTPUTFILE"
357 ;;
358 false)
359 cat "$RANKEDMIRRORS"
360 ;;
361 esac
362 }
363
364 RankAllMirrors() # this mainly controls the operation
365 {
366 # If a country name for allcountries includes spaces, they are turned to underscores.
367 # Note that this implementation handles max 3 words in a country name.
368 # If more words can exist on a country name, change the awk command on the next line.
369 local allcountries=$(grep "^# [A-Z]" "$INPUTFILE" | awk '{print $2"_"$3"_"$4}' | sed 's|[_]*$||')
370 local automatedmirrors=$(grep -A 5 "^# [ ]*Automated Mirror" "$INPUTFILE" | grep "^Server = " | awk '{print $3}')
371 local country mirror
372
373 rm -f "$RANKEDMIRRORS"
374
375 if [ -n "$INCLUDEDCOUNTRIES" ] ; then
376 # only the included countries are ranked
377 for country in $INCLUDEDCOUNTRIES
378 do
379 RankCountryMirrors "$country"
380 done
381 else
382 if [[ ! "$EXCLUDEDCOUNTRIES" =~ "Automated" ]] ; then
383 allcountries+=" Automated"
384 else
385 printf2 "Automated Mirrors:\n <excluded>\n"
386 fi
387
388 for country in $allcountries
389 do
390 if [[ ! "$EXCLUDEDCOUNTRIES" =~ "$country" ]] ; then
391 RankCountryMirrors "$country"
392 else
393 printf2 "$(echo $country | sed 's|_| |g'):\n <excluded>\n"
394 fi
395 done
396 fi
397
398 if [ $FOUND_MIRRORS -eq 0 ] ; then
399 echo2 ""
400 echo2 -n "Fail: no good mirrors currently found! "
401 if [ "$EXCLUDEDCOUNTRIES" = "" ] ; then
402 echo2 "Please try again later."
403 else
404 echo2 "Please try again later, or reduce your list of excluded countries."
405 fi
406 return 1
407 else
408 echo2 "$FOUND_MIRRORS mirrors found."
409 fi
410
411 SortMirrors
412 AddHeaderToFile
413 RemoveCommentsOnServerLines
414 ShowMirrorlist
415 }
416
417 GetLatestInputFile()
418 {
419 # Download the latest available antergos-mirrorlist as a reference input file.
420
421 echo2 -n "Downloading latest mirror info ... "
422 _runcheck pushd "$TMPDIR" >/dev/null
423
424 local filelist=fileinfo-$$.html
425 _runcheck wget -q -O "$filelist" https://repo.antergos.info/antergos/x86_64/
426
427 local inputfile=$(cat "$filelist" | sed 's|</a>|</a>\n|g' | grep "antergos-mirrorlist" | grep -v "xz\.sig" | sed 's|^.*>\(antergos\-mirrorlist\-[0-9\-]*\-any\.pkg\.tar\.xz\)<.*$|\1|')
428 rm -f "$filelist"
429
430 _runcheck wget -q https://repo.antergos.info/antergos/x86_64/"$inputfile"
431 _runcheck tar xf "$inputfile"
432
433 if [ -f etc/pacman.d/antergos-mirrorlist ] ; then
434 mv etc/pacman.d/antergos-mirrorlist .
435 rm -rf etc
436 rm -f "$inputfile" .BUILDINFO .MTREE .PKGINFO
437 else
438 echo2 "Error: file antergos-mirrorlist not found in downloaded package '$PWD/$inputfile'!"
439 exit 1
440 fi
441
442 _runcheck popd >/dev/null
443
444 echo2 "done."
445
446 INPUTFILE="$TMPDIR/antergos-mirrorlist"
447
448 if [ "$(cat "$INPUTFILE")" = "" ] ; then
449 echo2 "Error: your '$INPUTFILE' is empty??"
450 exit 1
451 fi
452 }
453
454 GetReferenceFiles()
455 {
456 # make sure we have a reference file to read!
457 GetLatestInputFile
458
459 $WGET_CMD -q -O "$REFERENCEFILE" $REFERENCEURL
460 REFERENCESTAMP=$(stat -c %Y "$REFERENCEFILE")
461 }
462
463 CleanAll()
464 {
465 rm -rf ${TMPDIR%.*}.*
466 }
467
468 AddToExcludedCountries()
469 {
470 local america="Canada USA"
471 local asia="China Japan"
472 local europe="Bulgaria Czech Denmark France England Germany Greece Netherlands Portugal Spain Sweden"
473
474 local xx
475 for xx in $EXCLUDEDCOUNTRYGROUPS
476 do
477 case "$xx" in
478 America) EXCLUDEDCOUNTRIES+=" $america" ;;
479 Asia) EXCLUDEDCOUNTRIES+=" $asia" ;;
480 Asia2) EXCLUDEDCOUNTRIES+=" $asia Russia" ;;
481 Europe) EXCLUDEDCOUNTRIES+=" $europe" ;;
482 Europe2) EXCLUDEDCOUNTRIES+=" $europe Russia" ;;
483 *)
484 echo2 "Warning: word '$xx' is not recognized as a country group."
485 ;;
486 esac
487 done
488 }
489
490 HandleOptions()
491 {
492 local arg
493 local doexit=0
494
495 for arg in "$@"
496 do
497 case "$arg" in
498 --help|-h)
499 CleanAll ; Usage ; doexit=1
500 ;;
501 --quiet)
502 VERBOSE=0
503 ;;
504 --verbose)
505 VERBOSE=2
506 ;;
507 --debug)
508 DEBUG=1
509 ;;
510 --protocols=*)
511 PROTOCOLS="$(echo ${arg:12} | tr ',' ' ')"
512 ;;
513 --exclude-countries=*)
514 EXCLUDEDCOUNTRIES+=" $(echo ${arg:20} | tr ',' ' ')"
515 ;;
516 --exclude-countrygroups=*)
517 EXCLUDEDCOUNTRYGROUPS="$(echo ${arg:24} | tr ',' ' ')"
518 AddToExcludedCountries
519 ;;
520 --include-countries=*)
521 INCLUDEDCOUNTRIES+=" $(echo ${arg:20} | tr ',' ' ')"
522 ;;
523 --save)
524 SAVE_TO_FILE=true
525 ;;
526 --exclude-mirrors=*)
527 EXCLUDEDMIRRORS="$(echo ${arg:18} | tr ',' ' ')"
528 ;;
529 --hide-original-mirrors=*)
530 HIDE_ORIGINAL_MIRRORS="${arg:24}"
531 ;;
532 --timeout=*)
533 WGET_TIMEOUT="${arg:10}"
534 ;;
535 --repo=*)
536 REPO=$(echo ${arg:7})
537 ;;
538 --arch=*)
539 ARCH=$(echo ${arg:7})
540 ;;
541 esac
542 done
543 if [ -n "$INCLUDEDCOUNTRIES" ] && [ -n "$EXCLUDEDCOUNTRIES" ] ; then
544 echo2 "Sorry, options to both include and exclude countries cannot be used together."
545 echo2 "Note however that it is allowed to include countries but exclude mirrors."
546 doexit=1
547 fi
548
549 debug2 "Command line: $0 $@"
550
551 verbose2more "EXCLUDEDCOUNTRYGROUPS = $EXCLUDEDCOUNTRYGROUPS"
552 verbose2more "EXCLUDEDCOUNTRIES = $EXCLUDEDCOUNTRIES"
553 verbose2more "EXCLUDEDMIRRORS = $EXCLUDEDMIRRORS"
554 verbose2more "INCLUDEDCOUNTRIES = $INCLUDEDCOUNTRIES"
555 verbose2more "PROTOCOLS = $PROTOCOLS"
556 verbose2more "WGET_TIMEOUT = $WGET_TIMEOUT"
557
558 test $doexit -eq 1 && exit 0
559 }
560
561 CheckRequirements()
562 {
563 # check required programs
564 if [ ! -x $TIME_CMD ] ; then
565 echo2 "Sorry, you need to install package 'time' first!"
566 echo2 "pacman -S --needed time"
567 exit 1
568 fi
569 if [ ! -x $WGET_CMD ] ; then
570 echo2 "Sorry, you need to install package 'wget' first!"
571 echo2 "pacman -S --needed wget"
572 exit 1
573 fi
574
575 mkdir -p "$TMPDIR"
576 }
577
578 StartHere()
579 {
580 COMMAND_LINE="$*"
581
582 CheckRequirements
583 HandleOptions "$@"
584 GetReferenceFiles
585 RankAllMirrors
586 CleanAll
587 }
588
589 StartHere "$@"