这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@twaik
Copy link
Member

@twaik twaik commented May 18, 2025

See #4 (comment)

With this change mirrors are being automatically filtered out in the case if last sync was more than 12 hours ago which should be fine.

But I am not sure what will happen if the last change in termux-packages happens more than 12 hours ago, probably it will break mirror picking, needs some tests.

Also it implements nice indication for outdated mirrors, like (example):

[*] (1) https://ftp.agdsn.de/termux/termux-main: outdated
[*] (4) https://grimler.se/termux/termux-main: ok
[*] (1) https://ro.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://mirrors.cfe.re/termux/termux-main: bad
[*] (1) https://mirror.termux.dev/termux-main: bad
[*] (1) https://termux.3san.dev/termux/termux-main: outdated
[*] (1) https://mirror.bouwhuis.network/termux/termux-main: outdated
[*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: outdated
[*] (1) https://termux.mentality.rip/termux-main: outdated
[*] (1) https://is.mirror.flokinet.net/termux/termux-main: outdated
[*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirrors.medzik.dev/termux/termux-main: ok
[*] (1) https://packages.termux.dev/apt/termux-main: ok
[*] (1) https://mirror.sunred.org/termux/termux-main: ok
[*] (1) https://mirrors.de.sahilister.net/termux/termux-main: outdated
[*] (1) https://mirror.leitecastro.com/termux/termux-main: ok
[*] (1) https://termux.cdn.lumito.net/termux-main: ok
[*] (1) https://nl.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://ftp.fau.de/termux/termux-main: ok
[*] (1) https://termux.librehat.com/apt/termux-main: outdated
[*] (1) https://mirror.autkin.net/termux/termux-main: outdated
[*] (1) https://mirror.polido.pt/termux/termux-main: bad

Closes termux/termux-app#4517

@agnostic-apollo
Copy link
Member

agnostic-apollo commented May 19, 2025

  1. Yes, comparing against current time will start failing pkg command. Comparison must be done against default packages-cf mirror Last Modified time as per my comment in other issue, not current time. Its value must be got beforehand.
  2. If default packages-cf mirror is not accessible, then comparison must not be done.
  3. If user has selected a single mirror instead of mirror group or none, then comparison must not be done, including getting Last Modified value of default mirror.
  4. The threshold must be 6hrs, the same as rotation time and common sync time of mirrors.
  5. If user passes -u or --up-to-date-mirror, then threshold must be 0 to allow our users to get latest package update if needed, like in case we deploy a fix.
  6. Run curl command for Release url and set output to release_file_content variable, and do not pipe it to sed as curl failures should not be ignored and an early exit must be done without needlessly running a regex engine to get last modified value.
  7. Use bash regex and capture group to get last modified value instead of running external sed command.
  8. The last modified time of default mirror, and outdated mirrors should be logged so that users know it and we can also remove mirrors which are not being synced.

@twaik twaik force-pushed the dev/check-last-modified-date branch 7 times, most recently from df904db to 4d6a031 Compare May 19, 2025 07:16
@twaik
Copy link
Member Author

twaik commented May 19, 2025

  • Run curl command for Release url and set output to release_file_content variable, and do not pipe it to sed as curl failures should not be ignored and an early exit must be done without needlessly running a regex engine to get last modified value.

We do not fetch file content itself so I called the variable headers.

8. The last modified time of default mirror, and outdated mirrors should be logged

Logging of time difference between default mirror and current mirror last update time required changing logging logic a bit but I figured it out.

Now output looks like this:

Testing the available mirrors:
Default mirror last modified time is Mon May 19 09:19:38 IDT 2025
[*] (10) https://packages-cf.termux.dev/apt/termux-main: ok
[*] (1) https://mirror.textcord.xyz/termux/termux-main: bad
[*] (1) https://tmx.xvx.my.id/apt/termux-main: ok
[*] (1) https://mirror.freedif.org/termux/termux-main: ok
[*] (1) https://linux.domainesia.com/applications/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirror.twds.com.tw/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirror.nevacloud.com/applications/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirrors.nguyenhoang.cloud/termux/termux-main: outdated (by 12h 4m 27s)
[*] (1) https://mirrors.cbrx.io/apt/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirrors.in.sahilister.net/termux/termux-main: ok
[*] (1) https://termux.niranjan.co/termux-main: outdated (by 418h 52m 26s)
[*] (1) https://mirrors.krnk.org/apt/termux/termux-main: outdated (by 120h 1m 31s)
[*] (1) https://mirror.bardia.tech/termux/termux-main: bad
[*] (1) https://mirrors.ravidwivedi.in/termux/termux-main: ok
[*] (1) https://mirror.meowsmp.net/termux/termux-main: ok
[*] (1) https://mirrors.saswata.cc/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirrors.sdu.edu.cn/termux/termux-main: ok
[*] (1) https://mirror.jeonnam.school/termux/termux-main: ok
[*] (1) https://mirror.rinarin.dev/termux/termux-main: ok
[*] (1) https://mirror.albony.in/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirrors.aliyun.com/termux/termux-main: outdated (by 12h 4m 27s)
[*] (1) https://mirror.iscas.ac.cn/termux/apt/termux-main: outdated (by 8h 9m 36s)
[*] (1) https://mirrors.ustc.edu.cn/termux/termux-main: outdated (by 12h 4m 27s)
[*] (1) https://mirrors.pku.edu.cn/termux/termux-main: outdated (by 18h 4m 18s)
[*] (1) https://mirror.sjtu.edu.cn/termux/termux-main: ok
[*] (1) https://mirrors.sustech.edu.cn/termux/apt/termux-main: outdated (by 32h 15m 23s)
[*] (1) https://mirrors.nju.edu.cn/termux/apt/termux-main: outdated (by 1h 18m 8s)
[*] (1) https://mirrors.sau.edu.cn/termux/apt/termux-main: outdated (by 35h 57m 35s)
[*] (1) https://mirrors.cernet.edu.cn/termux/apt/termux-main: outdated (by 8h 9m 36s)
[*] (1) https://mirrors.cqupt.edu.cn/termux/termux-main: bad
[*] (1) https://mirrors.cfe.re/termux/termux-main: bad
[*] (1) https://ftp.agdsn.de/termux/termux-main: outdated (by 6h 6m 19s)
[*] (4) https://grimler.se/termux/termux-main: ok
[*] (1) https://ro.mirror.flokinet.net/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main: outdated (by 13h 41m 28s)
[*] (1) https://mirrors.hust.edu.cn/termux/apt/termux-main: wrong date
[*] (1) https://mirrors.bfsu.edu.cn/termux/apt/termux-main: outdated (by 13h 41m 28s)
[*] (1) https://mirrors.zju.edu.cn/termux/apt/termux-main: outdated (by 32h 15m 23s)
[*] (1) https://mirror.nyist.edu.cn/termux/apt/termux-main: outdated (by 6h 16m 13s)
[*] (1) https://mirror.termux.dev/termux-main: bad
[*] (1) https://mirror.bouwhuis.network/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirror.sunred.org/termux/termux-main: ok
[*] (1) https://packages.termux.dev/apt/termux-main: ok
[*] (1) https://mirror.mwt.me/termux/main: outdated (by 6h 6m 19s)
[*] (1) https://mirrors.medzik.dev/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://termux.3san.dev/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad
[*] (1) https://termux.mentality.rip/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://is.mirror.flokinet.net/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirror.polido.pt/termux/termux-main: bad
[*] (1) https://nl.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://mirrors.de.sahilister.net/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://termux.cdn.lumito.net/termux-main: ok
[*] (1) https://mirror.leitecastro.com/termux/termux-main: ok
[*] (1) https://termux.librehat.com/apt/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://dl.kcubeterm.com/termux-main: bad
[*] (1) https://ftp.fau.de/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirror.autkin.net/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://termux.danyael.xyz/termux/termux-main: ok
[*] (1) https://mirror.mwt.me/termux/main: outdated (by 6h 6m 19s)
[*] (1) https://repository.su/termux/termux-main: outdated (by 23h 59m 34s)
[*] (1) https://gnlug.org/pub/termux/termux-main: outdated (by 7m 8s)
[*] (1) https://mirror.quantum5.ca/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirrors.utermux.dev/termux/termux-main: outdated (by 12h 7m 7s)
[*] (1) https://mirror.fcix.net/termux/termux-main: ok
[*] (1) https://mirror.csclub.uwaterloo.ca/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://plug-mirror.rcac.purdue.edu/termux/termux-main: outdated (by 6h 6m 19s)
[*] (1) https://mirror.vern.cc/termux/termux-main: outdated (by 12h 4m 27s)
[*] (1) https://mirrors.middlendian.com/termux/termux-main: outdated (by 18h 4m 18s)
[*] (1) http://mirror.mephi.ru/termux/termux-main: outdated (by 23h 59m 34s)
Picking mirror: (https://packages-cf.termux.dev/apt/termux-main)

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
...

@twaik twaik force-pushed the dev/check-last-modified-date branch 4 times, most recently from 9cb1342 to 3ded0da Compare May 19, 2025 16:26
@twaik
Copy link
Member Author

twaik commented May 19, 2025

I have a sneaking suspicion as to why some users are running into a bit of trouble here...

Currently I am rewriting it with a bit more advanced logging and I found an interesting thing:

Testing the available mirrors:
Default mirror last modified time is Mon, 19 May 2025 19:51:16 GMT
[*] (1) https://mirror.polido.pt/termux/termux-main: bad (Could not resolve host: mirror.polido.pt)
[*] (1) https://mirrors.cfe.re/termux/termux-main: bad (Could not resolve host: mirrors.cfe.re)
[*] (1) https://mirrors.krnk.org/apt/termux/termux-main: outdated (by 5d 7h 33m 9s)
[*] (1) https://termux.niranjan.co/termux-main: outdated (by 17d 18h 24m 4s)
[*] (1) https://termux.librehat.com/apt/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.cbrx.io/apt/termux/termux-main: ok
[*] (10) https://packages-cf.termux.dev/apt/termux-main: ok
[*] (1) https://mirror.meowsmp.net/termux/termux-main: ok
[*] (1) https://mirror.rinarin.dev/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirrors.medzik.dev/termux/termux-main: ok
[*] (1) https://packages.termux.dev/apt/termux-main: ok
[*] (1) https://mirror.sunred.org/termux/termux-main: ok
[*] (1) https://mirrors.de.sahilister.net/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://termux.cdn.lumito.net/termux-main: ok
[*] (1) https://nl.mirror.flokinet.net/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://ftp.fau.de/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://ftp.agdsn.de/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://tmx.xvx.my.id/apt/termux-main: ok
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirror.bouwhuis.network/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://ro.mirror.flokinet.net/termux/termux-main: ok
[*] (4) https://grimler.se/termux/termux-main: ok
[*] (1) https://termux.3san.dev/termux/termux-main: ok
[*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: ok
[*] (1) https://mirror.freedif.org/termux/termux-main: ok
[*] (1) https://termux.mentality.rip/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirror.nevacloud.com/applications/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.ravidwivedi.in/termux/termux-main: ok
[*] (1) https://is.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://mirrors.nguyenhoang.cloud/termux/termux-main: ok
[*] (1) https://mirror.twds.com.tw/termux/termux-main: ok
[*] (1) https://dl.kcubeterm.com/termux-main: bad (HTTP error 521)
[*] (1) https://mirrors.sdu.edu.cn/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirror.bardia.tech/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirrors.pku.edu.cn/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.nju.edu.cn/termux/apt/termux-main: outdated (by 8h 49m 46s)
[*] (1) https://mirrors.aliyun.com/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirror.sjtu.edu.cn/termux/termux-main: ok
[*] (1) https://mirrors.ustc.edu.cn/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.sustech.edu.cn/termux/apt/termux-main: outdated (by 15h 41m 14s)
[*] (1) https://mirror.iscas.ac.cn/termux/apt/termux-main: outdated (by 15h 41m 14s)
[*] (1) https://mirrors.zju.edu.cn/termux/apt/termux-main: outdated (by 15h 41m 14s)
[*] (1) https://mirror.textcord.xyz/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirror.jeonnam.school/termux/termux-main: ok
[*] (1) https://mirrors.bfsu.edu.cn/termux/apt/termux-main: outdated (by 21h 13m 6s)
[*] (1) https://mirror.leitecastro.com/termux/termux-main: ok
[*] (1) https://mirror.autkin.net/termux/termux-main: outdated (by 13h 37m 57s)
[*] (1) https://mirrors.cqupt.edu.cn/termux/termux-main: outdated (by 19h 36m 5s)
[*] (1) http://mirror.mephi.ru/termux/termux-main: outdated (by 7h 31m 38s)
[*] (1) https://mirrors.saswata.cc/termux/termux-main: ok
[*] (1) https://linux.domainesia.com/applications/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirror.vern.cc/termux/termux-main: bad (Failed to connect to mirror.vern.cc port 443 after 383 ms: Could not connect to server)
[*] (1) https://mirror.nyist.edu.cn/termux/apt/termux-main: outdated (by 13h 47m 51s)
[*] (1) https://termux.danyael.xyz/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad (HTTP error 403)
[*] (1) https://gnlug.org/pub/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://plug-mirror.rcac.purdue.edu/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirror.csclub.uwaterloo.ca/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.in.sahilister.net/termux/termux-main: ok
[*] (1) https://mirror.quantum5.ca/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirror.fcix.net/termux/termux-main: ok
[*] (1) https://repository.su/termux/termux-main: outdated (by 7h 31m 38s)
[*] (1) https://mirror.albony.in/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main: ok
[*] (1) https://mirrors.cernet.edu.cn/termux/apt/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.sau.edu.cn/termux/apt/termux-main: outdated (by 7h 31m 38s)
[*] (1) https://mirrors.utermux.dev/termux/termux-main: outdated (by 19h 38m 45s)
[*] (1) https://mirrors.middlendian.com/termux/termux-main: outdated (by 1h 25m 24s)
[*] (1) https://mirrors.hust.edu.cn/termux/apt/termux-main: timeout
[*] (1) https://mirror.termux.dev/termux-main: timeout

@twaik
Copy link
Member Author

twaik commented May 19, 2025

Only some of mirrors are more or less up-to-date, others are outdated or unusable.
17 days!

@agnostic-apollo
Copy link
Member

agnostic-apollo commented May 19, 2025

You need to download the Release file like I have said multiple times, and not the header to fix termux/termux-app#4517 and ensure comparison is done based on modification time of repo, and possibly caching/sync policies of repo servers don't affect comparison. The whole file should not need to be downloaded, curl --range can probably be used. Additional validity checks should be done too for Release file. Other implementation issues exist too, will look into it sometime.

@agnostic-apollo
Copy link
Member

Only some of mirrors are more or less up-to-date, others are outdated or unusable.

Yeah, I suspected this too, that's why this was important to implement to filter them out and report to mirror owners, and permanently remove them if they remain too out of date.

@twaik
Copy link
Member Author

twaik commented May 19, 2025

You need to download the Release file like I have said multiple times, and not the header to fix

But why not? Seems like reading "last-modified" header of file is enough for finding out if file is up-to-date. Rsync explicitly syncs timestamps of files during sync.

@twaik
Copy link
Member Author

twaik commented May 19, 2025

I'll check it though.

@agnostic-apollo
Copy link
Member

agnostic-apollo commented May 19, 2025

If a mirror url is not hosting a Release file and instead is hosting a different file or redirecting to a different url like in case of domain expiry or new host, then you are comparing last modified time of the redirected page, not the release file which doesn't even exist on the server.

Look at following, no Release file exists at that url, but time is of right now. Basically header timestamp is not what should be compared, and it can be anything as per server policies.

$ curl --head https://deb.kcubeterm.com/termux-main
HTTP/2 521
date: Mon, 19 May 2025 21:37:32 GMT
content-length: 0
server: cloudflare
cache-control: private, no-store

@agnostic-apollo
Copy link
Member

Also not everyone may be using rsync and/or preserving timestamps of files.

@twaik
Copy link
Member Author

twaik commented May 19, 2025

  1. HTTP code 521 stands for "web server is down". So it is handled as http error.
  2. curl handles redirects fine and follows them.
  3. I am already on it.

@agnostic-apollo
Copy link
Member

You are assuming 521 will always be returned. Redirection could happen to a valid url too, like homepage.

@twaik
Copy link
Member Author

twaik commented May 19, 2025

With obtaining range 0-255 and parsing date from the release file the situation is not very much different.
The 17d-out-of-date mirror is still there.

Testing the available mirrors:
Default mirror last modified time is Mon, 19 May 2025 21:17:42 UTC
[*] (10) https://packages-cf.termux.dev/apt/termux-main: ok
[*] (1) https://mirrors.cfe.re/termux/termux-main: bad (Could not resolve host: mirrors.cfe.re)
[*] (1) https://mirror.polido.pt/termux/termux-main: bad (Could not resolve host: mirror.polido.pt)
[*] (1) https://mirror.textcord.xyz/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirrors.krnk.org/apt/termux/termux-main: outdated (by 5d 8h 59m 35s)
[*] (1) https://termux.niranjan.co/termux-main: outdated (by 17d 19h 50m 30s)
[*] (1) https://mirrors.ravidwivedi.in/termux/termux-main: ok
[*] (1) https://mirrors.bfsu.edu.cn/termux/apt/termux-main: outdated (by 22h 39m 32s)
[*] (1) https://mirrors.cbrx.io/apt/termux/termux-main: ok
[*] (4) https://grimler.se/termux/termux-main: ok
[*] (1) https://ro.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://linux.domainesia.com/applications/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.freedif.org/termux/termux-main: ok
[*] (1) https://mirrors.saswata.cc/termux/termux-main: ok
[*] (1) https://ftp.agdsn.de/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.nevacloud.com/applications/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.nguyenhoang.cloud/termux/termux-main: ok
[*] (1) https://termux.3san.dev/termux/termux-main: ok
[*] (1) https://mirror.bouwhuis.network/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: ok
[*] (1) https://termux.mentality.rip/termux-main: ok
[*] (1) https://is.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad (HTTP error 403)
[*] (1) https://mirror.meowsmp.net/termux/termux-main: ok
[*] (1) https://mirror.sunred.org/termux/termux-main: ok
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirrors.de.sahilister.net/termux/termux-main: ok
[*] (1) https://nl.mirror.flokinet.net/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.nju.edu.cn/termux/apt/termux-main: outdated (by 10h 16m 12s)
[*] (1) https://ftp.fau.de/termux/termux-main: ok
[*] (1) https://mirror.bardia.tech/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirrors.sustech.edu.cn/termux/apt/termux-main: outdated (by 17h 7m 40s)
[*] (1) https://mirror.iscas.ac.cn/termux/apt/termux-main: outdated (by 17h 7m 40s)
[*] (1) https://mirror.albony.in/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.ustc.edu.cn/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.aliyun.com/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.zju.edu.cn/termux/apt/termux-main: outdated (by 17h 7m 40s)
[*] (1) https://mirror.nyist.edu.cn/termux/apt/termux-main: outdated (by 15h 14m 17s)
[*] (1) https://mirrors.medzik.dev/termux/termux-main: ok
[*] (1) https://packages.termux.dev/apt/termux-main: ok
[*] (1) https://termux.librehat.com/apt/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirror.leitecastro.com/termux/termux-main: ok
[*] (1) https://tmx.xvx.my.id/apt/termux-main: ok
[*] (1) https://dl.kcubeterm.com/termux-main: bad (HTTP error 521)
[*] (1) https://termux.cdn.lumito.net/termux-main: ok
[*] (1) https://mirror.autkin.net/termux/termux-main: outdated (by 15h 4m 23s)
[*] (1) https://mirrors.cqupt.edu.cn/termux/termux-main: ok
[*] (1) http://mirror.mephi.ru/termux/termux-main: outdated (by 8h 58m 4s)
[*] (1) https://mirrors.sau.edu.cn/termux/apt/termux-main: outdated (by 8h 58m 4s)
[*] (1) https://mirror.jeonnam.school/termux/termux-main: ok
[*] (1) https://mirror.vern.cc/termux/termux-main: bad (Failed to connect to mirror.vern.cc port 443 after 399 ms: Could not connect to server)
[*] (1) https://mirror.twds.com.tw/termux/termux-main: ok
[*] (1) https://mirror.rinarin.dev/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.in.sahilister.net/termux/termux-main: ok
[*] (1) https://termux.danyael.xyz/termux/termux-main: ok
[*] (1) https://mirrors.sdu.edu.cn/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://gnlug.org/pub/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.csclub.uwaterloo.ca/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://plug-mirror.rcac.purdue.edu/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://repository.su/termux/termux-main: outdated (by 8h 58m 4s)
[*] (1) https://mirrors.utermux.dev/termux/termux-main: outdated (by 21h 5m 11s)
[*] (1) https://mirror.sjtu.edu.cn/termux/termux-main: ok
[*] (1) https://mirror.fcix.net/termux/termux-main: ok
[*] (1) https://mirror.quantum5.ca/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.cernet.edu.cn/termux/apt/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main: ok
[*] (1) https://mirrors.middlendian.com/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.pku.edu.cn/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.hust.edu.cn/termux/apt/termux-main: timeout
[*] (1) https://mirror.termux.dev/termux-main: timeout

@twaik
Copy link
Member Author

twaik commented May 19, 2025

I was wrong about still there. I forgot to remove obtaining timestamp in read and it reset my newly obtained variable.
There was other result. with --range some servers correctly respond with 206 code but do not send any content so I am getting only a blank line in the place where I should get lines.
As an option I can download the whole release file which will result in downloading ~1MB of data each time user invokes pkg.

And even in this case the situation is not better.

Testing the available mirrors:
Default mirror last modified time is Mon, 19 May 2025 21:17:42 UTC
[*] (10) https://packages-cf.termux.dev/apt/termux-main: ok
[*] (1) https://mirror.textcord.xyz/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirror.nevacloud.com/applications/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.nguyenhoang.cloud/termux/termux-main: ok
[*] (1) https://mirror.twds.com.tw/termux/termux-main: ok
[*] (1) https://linux.domainesia.com/applications/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://tmx.xvx.my.id/apt/termux-main: ok
[*] (1) https://mirror.freedif.org/termux/termux-main: ok
[*] (1) https://mirrors.cbrx.io/apt/termux/termux-main: ok
[*] (1) https://mirrors.in.sahilister.net/termux/termux-main: ok
[*] (1) https://mirror.albony.in/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.bardia.tech/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirrors.saswata.cc/termux/termux-main: ok
[*] (1) https://mirror.jeonnam.school/termux/termux-main: ok
[*] (1) https://mirror.meowsmp.net/termux/termux-main: ok
[*] (1) https://mirrors.krnk.org/apt/termux/termux-main: outdated (by 5d 8h 59m 35s)
[*] (1) https://termux.niranjan.co/termux-main: outdated (by 17d 19h 50m 30s)
[*] (1) https://mirror.rinarin.dev/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.ravidwivedi.in/termux/termux-main: ok
[*] (1) https://mirrors.sdu.edu.cn/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.sau.edu.cn/termux/apt/termux-main: outdated (by 8h 58m 4s)
[*] (1) https://mirrors.nju.edu.cn/termux/apt/termux-main: outdated (by 15h 4m 23s)
[*] (1) https://mirrors.sustech.edu.cn/termux/apt/termux-main: outdated (by 21h 2m 31s)
[*] (1) https://mirrors.pku.edu.cn/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.sjtu.edu.cn/termux/termux-main: ok
[*] (1) https://mirror.iscas.ac.cn/termux/apt/termux-main: outdated (by 21h 2m 31s)
[*] (1) https://mirrors.ustc.edu.cn/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.aliyun.com/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.cernet.edu.cn/termux/apt/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.cqupt.edu.cn/termux/termux-main: ok
[*] (1) https://mirrors.zju.edu.cn/termux/apt/termux-main: outdated (by 21h 2m 31s)
[*] (1) https://mirrors.hust.edu.cn/termux/apt/termux-main: timeout
[*] (1) https://mirrors.bfsu.edu.cn/termux/apt/termux-main: outdated (by 1d 3h 2m 22s)
[*] (1) https://mirror.nyist.edu.cn/termux/apt/termux-main: outdated (by 21h 2m 31s)
[*] (1) https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://ftp.agdsn.de/termux/termux-main: outdated (by 2h 51m 50s)
[*] (4) https://grimler.se/termux/termux-main: ok
[*] (1) https://ro.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://mirrors.cfe.re/termux/termux-main: bad (Could not resolve host: mirrors.cfe.re)
[*] (1) https://mirror.termux.dev/termux-main: timeout
[*] (1) https://termux.3san.dev/termux/termux-main: ok
[*] (1) https://mirror.bouwhuis.network/termux/termux-main: ok
[*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: ok
[*] (1) https://termux.mentality.rip/termux-main: ok
[*] (1) https://is.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad (HTTP error 403)
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirrors.medzik.dev/termux/termux-main: ok
[*] (1) https://packages.termux.dev/apt/termux-main: ok
[*] (1) https://mirror.sunred.org/termux/termux-main: ok
[*] (1) https://mirrors.de.sahilister.net/termux/termux-main: ok
[*] (1) https://mirror.leitecastro.com/termux/termux-main: ok
[*] (1) https://termux.cdn.lumito.net/termux-main: ok
[*] (1) https://nl.mirror.flokinet.net/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://ftp.fau.de/termux/termux-main: ok
[*] (1) https://termux.librehat.com/apt/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.autkin.net/termux/termux-main: outdated (by 15h 4m 23s)
[*] (1) https://mirror.polido.pt/termux/termux-main: bad (Could not resolve host: mirror.polido.pt)
[*] (1) https://dl.kcubeterm.com/termux-main: bad (HTTP error 521)
[*] (1) https://termux.danyael.xyz/termux/termux-main: ok
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirrors.utermux.dev/termux/termux-main: outdated (by 21h 5m 11s)
[*] (1) https://mirror.vern.cc/termux/termux-main: bad (Failed to connect to mirror.vern.cc port 443 after 370 ms: Could not connect to server)
[*] (1) https://plug-mirror.rcac.purdue.edu/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirror.quantum5.ca/termux/termux-main: ok
[*] (1) https://mirror.fcix.net/termux/termux-main: ok
[*] (1) https://mirror.csclub.uwaterloo.ca/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://gnlug.org/pub/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://mirrors.middlendian.com/termux/termux-main: outdated (by 2h 51m 50s)
[*] (1) https://repository.su/termux/termux-main: outdated (by 8h 58m 4s)
[*] (1) http://mirror.mephi.ru/termux/termux-main: outdated (by 8h 58m 4s)

@twaik
Copy link
Member Author

twaik commented May 19, 2025

Also AFAIK in the case if you not specify -t|--times to rsync it sets last modification time to download time so it is at least a distant approximation of what we need, so using last-modified header should be fine.

What do you think?

@twaik
Copy link
Member Author

twaik commented May 21, 2025

What do you think?

@agnostic-apollo ?

@agnostic-apollo
Copy link
Member

I was expecting some mirrors to have problems with --range, will have to test things myself to see what's going on and possibly implement a workaround and other fixes and also see performance impacts of downloading the partial Release file. Will take a while to do this as its at least a few hours of work and I am busy with other stuff.

@twaik
Copy link
Member Author

twaik commented May 21, 2025

Ok, so I am putting work in this direction on hold until I get your response on this.

But I still think checking Last-modified is fine because it will be or synchronized with termux's server or it will be a date of the last sync so it is still better than the current master branch solution.

@agnostic-apollo
Copy link
Member

Thanks, its not just about last modified time, we also need to ensure the url is for a valid Release file for the termux-main repo, as otherwise it will break apt for users.

@twaik
Copy link
Member Author

twaik commented May 21, 2025

If you think download ~1MB data is fine (~13KB * 70 files, somebody still uses limited connections) I can download the whole file content as well. But I just want to mention currently pkg has zero checks and my PR covers only this point.

@agnostic-apollo
Copy link
Member

That is definitely not fine, only following part needs to be downloaded for validation, that is 200 * 70 = 14KB, even fewer for mirror group. If --range does not work, then curl --silent --fail https://packages.termux.dev/apt/termux-main/dists/stable/Release | head -c 200 should work. If head may fails, then SIGPIPE may get triggered so exit codes etc will have to be checked properly.

Origin: termux-main stable
Label: termux-main stable
Suite: stable
Codename: stable
Date: Wed, 21 May 2025 13:07:54 UTC
Architectures: aarch64 arm i686 x86_64
Components: main
$ curl --silent --fail https://packages.termux.dev/apt/termux-main/dists/stable/Release1 | head -c 200
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
22 0

$ curl --silent --fail https://packages.termux.dev/apt/termux-main/dists/stable/Release | head -c 200
Origin: termux-main stable
Label: termux-main stable
Suite: stable
Codename: stable
Date: Wed, 21 May 2025 13:07:54 UTC
Architectures: aarch64 arm i686 x86_64
Components: main
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
0 0

@twaik
Copy link
Member Author

twaik commented May 21, 2025

So maybe in this case we should do grep instead of head? grep will both signal with error code and filter line in the case if the line with Date is not in output.

@agnostic-apollo
Copy link
Member

No, at least origin and architectures should be validated too. Regex engine should run internally in bash. Maybe read can work instead of head too. Will have to experiment all of this.

@twaik
Copy link
Member Author

twaik commented May 27, 2025

I just wanted to add something simple, but somehow it spiraled into a full script refactor, I'm not even sure how! And I wonder how I have more deletions than insertions.

So, there are some differences to original behaviour.

  1. Instead of creating lots of curl processes running in background and waiting for all of them to finish now the script runs a single curl process which sends all requests in parallel. It allowed me remove a huge amount of code related to parallelizing curl requests.
  2. Curl now downloads first 200 bytes of Release file instead of silently check only if URL responds with 200 code (as per @agnostic-apollo's request) and checks Release file's Date, Origin and Architectures fields to make sure the mirror is up-to-date and the Release file is valid.
  3. Now the script always tries to obtain last update timestamp of default mirror except for the case if single mirror is selected (as per @agnostic-apollo's request).
  4. Most of processing is running in serial instead of using background processes to avoid triggering phantom process killer, background processes are used only in the most critical places.
  5. I consider all termux-running devices as low-performance disregarding the real state of affairs, so I squashed get_mirror_url and get_mirror_weight into a single function to avoid re-sourcing mirror scripts. Same applies to last_modified invocations which invoked date utility twice (I replaced it with find invocation which compares timestamps of files). The reasons are pretty much simple: bionic's elf execution sequence is pretty much more heavy than glibc's and also termux can run on really slow and old devices.
  6. Instead of implementing weight-based random mirror picking the code which creates mirror list creates weighted mirror list and then random mirror is being selected by shuf command.

@twaik twaik force-pushed the dev/check-last-modified-date branch from 3ded0da to 266736f Compare May 27, 2025 07:24
@twaik
Copy link
Member Author

twaik commented May 27, 2025

So now the output is like this

Testing the available mirrors:
Default mirror date is Tue, 27 May 2025 06:14:41 UTC
[*] (10) https://packages-cf.termux.dev/apt/termux-main: up-to-date
[*] (1) https://mirrors.cfe.re/termux/termux-main: bad (Could not resolve host: mirrors.cfe.re)
[*] (1) https://mirror.polido.pt/termux/termux-main: bad (Could not resolve host: mirror.polido.pt)
[*] (1) https://mirror.bardia.tech/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirrors.krnk.org/apt/termux/termux-main: outdated (by 5d 5h 28m 43s)
[*] (1) https://termux.niranjan.co/termux-main: outdated (by 25d 4h 47m 29s)
[*] (1) https://mirrors.ravidwivedi.in/termux/termux-main: ok
[*] (1) https://ftp.agdsn.de/termux/termux-main: ok
[*] (4) https://grimler.se/termux/termux-main: up-to-date
[*] (1) https://ro.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://mirror.textcord.xyz/termux/termux-main: bad (HTTP error 404)
[*] (1) https://mirrors.nguyenhoang.cloud/termux/termux-main: outdated (by 5h 55m 31s)
[*] (1) https://mirror.twds.com.tw/termux/termux-main: ok
[*] (1) https://linux.domainesia.com/applications/termux/termux-main: ok
[*] (1) https://mirror.freedif.org/termux/termux-main: up-to-date
[*] (1) https://mirrors.cbrx.io/apt/termux/termux-main: ok
[*] (1) https://mirror.jeonnam.school/termux/termux-main: up-to-date
[*] (1) https://mirror.meowsmp.net/termux/termux-main: up-to-date
[*] (1) https://mirrors.sdu.edu.cn/termux/termux-main: ok
[*] (1) https://mirrors.sau.edu.cn/termux/apt/termux-main: outdated (by 5h 55m 31s)
[*] (1) https://mirrors.nju.edu.cn/termux/apt/termux-main: up-to-date
[*] (1) https://mirrors.sustech.edu.cn/termux/apt/termux-main: outdated (by 1d 5h 52m 58s)
[*] (1) https://mirrors.pku.edu.cn/termux/termux-main: outdated (by 11h 52m 53s)
[*] (1) https://mirror.sjtu.edu.cn/termux/termux-main: up-to-date
[*] (1) https://mirrors.ustc.edu.cn/termux/termux-main: outdated (by 5h 55m 31s)
[*] (1) https://termux.3san.dev/termux/termux-main: ok
[*] (1) https://mirror.bouwhuis.network/termux/termux-main: ok
[*] (1) https://termux.mentality.rip/termux-main: ok
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) https://mirror.mwt.me/termux/main: ok
[*] (1) http://mirror.mephi.ru/termux/termux-main: outdated (by 17h 38m 49s)
[*] (1) https://packages.termux.dev/apt/termux-main: up-to-date
[*] (1) https://is.mirror.flokinet.net/termux/termux-main: ok
[*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad (HTTP error 403)
[*] (1) https://mirrors.aliyun.com/termux/termux-main: outdated (by 5h 55m 31s)
[*] (1) https://mirror.sunred.org/termux/termux-main: up-to-date
[*] (1) https://mirrors.de.sahilister.net/termux/termux-main: ok
[*] (1) https://mirror.leitecastro.com/termux/termux-main: up-to-date
[*] (1) https://termux.cdn.lumito.net/termux-main: up-to-date
[*] (1) https://nl.mirror.flokinet.net/termux/termux-main: up-to-date
[*] (1) https://ftp.fau.de/termux/termux-main: ok
[*] (1) https://termux.librehat.com/apt/termux-main: ok
[*] (1) https://mirror.autkin.net/termux/termux-main: ok
[*] (1) https://mirror.rinarin.dev/termux/termux-main: up-to-date
[*] (1) https://mirrors.hust.edu.cn/termux/apt/termux-main: ok
[*] (1) https://tmx.xvx.my.id/apt/termux-main: up-to-date
[*] (1) https://mirror.vern.cc/termux/termux-main: outdated (by 5h 55m 31s)
[*] (1) https://mirror.nyist.edu.cn/termux/apt/termux-main: ok
[*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: ok
[*] (1) https://mirror.iscas.ac.cn/termux/apt/termux-main: outdated (by 5h 55m 31s)
[*] (1) https://mirrors.cqupt.edu.cn/termux/termux-main: ok
[*] (1) https://mirrors.bfsu.edu.cn/termux/apt/termux-main: outdated (by 11h 52m 53s)
[*] (1) https://dl.kcubeterm.com/termux-main: bad (HTTP error 521)
[*] (1) https://mirror.quantum5.ca/termux/termux-main: ok
[*] (1) https://mirrors.zju.edu.cn/termux/apt/termux-main: outdated (by 1d 5h 52m 58s)
[*] (1) https://mirror.albony.in/termux/termux-main: ok
[*] (1) https://mirrors.medzik.dev/termux/termux-main: ok
[*] (1) https://plug-mirror.rcac.purdue.edu/termux/termux-main: ok
[*] (1) https://mirror.fcix.net/termux/termux-main: ok
[*] (1) https://mirror.csclub.uwaterloo.ca/termux/termux-main: outdated (by 5h 55m 31s)
[*] (1) https://gnlug.org/pub/termux/termux-main: up-to-date
[*] (1) https://repository.su/termux/termux-main: outdated (by 17h 38m 49s)
[*] (1) https://termux.danyael.xyz/termux/termux-main: up-to-date
[*] (1) https://mirrors.utermux.dev/termux/termux-main: outdated (by 6h 4m 1s)
[*] (1) https://mirrors.in.sahilister.net/termux/termux-main: outdated (by 11h 52m 53s)
[*] (1) https://mirrors.middlendian.com/termux/termux-main: outdated (by 11h 52m 53s)
[*] (1) https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main: outdated (by 11h 52m 53s)
[*] (1) https://mirrors.cernet.edu.cn/termux/apt/termux-main: up-to-date
[*] (1) https://mirror.nevacloud.com/applications/termux/termux-main: ok
[*] (1) https://mirrors.saswata.cc/termux/termux-main: ok
[*] (1) https://mirror.termux.dev/termux-main: timeout
Picking mirror: https://packages-cf.termux.dev/apt/termux-main

...

@twaik
Copy link
Member Author

twaik commented May 27, 2025

Probably I can make it print only hostnames instead of full mirror urls, or even hostname + location to make output a bit more useful. Should I do so?

@twaik twaik force-pushed the dev/check-last-modified-date branch from 266736f to 61af27f Compare May 27, 2025 12:17
@twaik
Copy link
Member Author

twaik commented May 27, 2025

Seems like dpkg --print-architecture prints compile time variable which matches our compile target names, so we can inline this value at compile time as well.

@twaik twaik force-pushed the dev/check-last-modified-date branch from 61af27f to 8de8a81 Compare May 27, 2025 14:55
@twaik twaik mentioned this pull request May 27, 2025
@robertkirkman
Copy link
Member

Probably I can make it print only hostnames instead of full mirror urls, or even hostname + location to make output a bit more useful. Should I do so?

That sounds fine because, even if the full URL of the selected mirror is desired for convenience (like clicking it in a terminal emulator that supports opening URLs in order to browse it in a web browser), apt update will print the full URL of the mirror while it is running immediately afterward, so I don't think anything particularly important would be lost.

Copy link
Member

@robertkirkman robertkirkman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this and I tried to find anything wrong with it, but I have not found anything wrong in my opinion and this overall runs much faster than the current version.

@twaik
Copy link
Member Author

twaik commented May 28, 2025

Seems like performing apt update by checking pkgcache.bin is older than 2 hours is wrong.
Apt updates this file after any apt install or apt update invocation, even if nothing changes.

twaik@twaik:~$ sudo touch -d@0 /var/cache/apt/pkgcache.bin
twaik@twaik:~$ ls -la /var/cache/apt/pkgcache.bin
-rw-r--r-- 1 root root 54581391 Jan  1  1970 /var/cache/apt/pkgcache.bin
twaik@twaik:~$ sudo apt install
Summary:                        
  Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 12
twaik@twaik:~$ ls -la /var/cache/apt/pkgcache.bin
-rw-r--r-- 1 root root 54581391 May 28 23:16 /var/cache/apt/pkgcache.bin
twaik@twaik:~$ sudo touch -d@0 /var/cache/apt/pkgcache.bin
twaik@twaik:~$ ls -la /var/cache/apt/pkgcache.bin
-rw-r--r-- 1 root root 54581391 Jan  1  1970 /var/cache/apt/pkgcache.bin
twaik@twaik:~$ sudo apt list > /dev/null 2>&1
twaik@twaik:~$ ls -la /var/cache/apt/pkgcache.bin
-rw-r--r-- 1 root root 54581391 May 28 23:17 /var/cache/apt/pkgcache.bin

However, apt does not update the *_Release file of mirror if it was not changed, so probably the best solution will be creating a timestamp file for tracking last update date and check if it is more than 2 hours old instead of checking the pkgcache.bin file.

CC @agnostic-apollo because you merged this change.

@agnostic-apollo
Copy link
Member

agnostic-apollo commented May 28, 2025

CC @agnostic-apollo because you merged this change.

Lies!!! Trying to ruin my good name!

@agnostic-apollo
Copy link
Member

Will have to think more on the problem. Thanks for notification.

@twaik
Copy link
Member Author

twaik commented May 29, 2025

Lies!!! Trying to ruin my good name!

402908d

@agnostic-apollo
Copy link
Member

That didn't add pkgcache.bin check, only changed using date instead of find to check last modification time.

@twaik
Copy link
Member Author

twaik commented May 29, 2025

Any specific reason to avoid using find for that?

@agnostic-apollo
Copy link
Member

There shouldn't be a functional difference as far I see. But there should have been an existence check added in update_apt_cache for the pkgcache.bin file.

@twaik twaik force-pushed the dev/check-last-modified-date branch from 8de8a81 to cc1dea6 Compare June 8, 2025 04:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bad mirrors are still detected as available

3 participants