6
6
import platform
7
7
import sys
8
8
import urllib .request
9
+ from urllib .parse import urljoin
9
10
import json
10
11
import hashlib
12
+ import logging
11
13
12
14
INDEX_URL = os .getenv ("ASDF_ZIG_INDEX_URL" , "https://ziglang.org/download/index.json" )
13
15
HTTP_TIMEOUT = int (os .getenv ("ASDF_ZIG_HTTP_TIMEOUT" , "30" ))
@@ -46,17 +48,21 @@ def all_versions(index=fetch_index()):
46
48
return versions
47
49
48
50
49
- def download_and_check (url , out_file , expected_shasum ):
50
- print (f"Download tarball from { url } to { out_file } ..." )
51
- chunk_size = 8192 # 8KB chunks
51
+ def download_and_check (url , out_file , expected_shasum , total_size ):
52
+ logging . info (f"Begin download tarball( { total_size } ) from { url } to { out_file } ..." )
53
+ chunk_size = 1024 * 1024 # 1M chunks
52
54
sha256_hash = hashlib .sha256 ()
53
55
with urllib .request .urlopen (url , timeout = HTTP_TIMEOUT ) as response :
54
56
if response .getcode () != 200 :
55
57
raise Exception (f"Fetch index.json error: { response .getcode ()} " )
56
58
59
+ read_size = 0
57
60
with open (out_file , "wb" ) as f :
58
61
while True :
59
62
chunk = response .read (chunk_size )
63
+ read_size += len (chunk )
64
+ progress_percentage = (read_size / total_size ) * 100 if total_size > 0 else 0
65
+ logging .info (f'Downloaded: { read_size } /{ total_size } bytes ({ progress_percentage :.2f} %)' )
60
66
if not chunk :
61
67
break # eof
62
68
sha256_hash .update (chunk )
@@ -69,20 +75,21 @@ def download_and_check(url, out_file, expected_shasum):
69
75
)
70
76
71
77
72
- def download_tarball (url , out_file , expected_shasum ):
78
+ def download_tarball (url , out_file , expected_shasum , total_size ):
73
79
filename = url .split ("/" )[- 1 ]
74
80
random .shuffle (MIRRORS )
75
- urls = [f"{ mirror } /{ filename } " for mirror in MIRRORS ]
76
81
77
- for url in urls :
82
+ for mirror in MIRRORS :
78
83
try :
79
- download_and_check (url , out_file , expected_shasum )
84
+ # Ensure base_url has a trailing slash
85
+ mirror = mirror if mirror .endswith ('/' ) else mirror + '/'
86
+ download_and_check (urljoin (mirror , filename ), out_file , expected_shasum , total_size )
80
87
return
81
88
except Exception as e :
82
- print (f"Current mirror failed, try next. err:{ e } " )
89
+ logging . error (f"Current mirror failed, try next. err:{ e } " )
83
90
84
91
# All mirrors failed, fallback to original url
85
- download_and_check (url , out_file , expected_shasum )
92
+ download_and_check (url , out_file , expected_shasum , total_size )
86
93
87
94
88
95
def download (version , out_file ):
@@ -101,7 +108,8 @@ def download(version, out_file):
101
108
102
109
tarball_url = links [link_key ]["tarball" ]
103
110
tarball_shasum = links [link_key ]["shasum" ]
104
- download_tarball (tarball_url , out_file , tarball_shasum )
111
+ tarball_size = int (links [link_key ]["size" ])
112
+ download_tarball (tarball_url , out_file , tarball_shasum , tarball_size )
105
113
106
114
107
115
def main (args ):
@@ -115,9 +123,10 @@ def main(args):
115
123
elif command == "download" :
116
124
download (args [1 ], args [2 ])
117
125
else :
118
- print (f"Unknown command: { command } " )
126
+ logging . error (f"Unknown command: { command } " )
119
127
sys .exit (1 )
120
128
121
129
122
130
if __name__ == "__main__" :
131
+ logging .basicConfig (level = logging .INFO , format = '[%(asctime)s] %(message)s' )
123
132
main (sys .argv [1 :])
0 commit comments