7
7
import shutil
8
8
import subprocess
9
9
import tarfile
10
+ import tempfile
10
11
import time
11
12
import urllib .request
12
13
import warnings
@@ -52,7 +53,7 @@ def get_libc():
52
53
libc = platform .libc_ver ()[0 ].lower ()
53
54
return libc_aliases .get (libc , libc )
54
55
55
- def compatible_julia_versions (compat = None , stable = True , kind = None ):
56
+ def compatible_julia_versions (compat = None ):
56
57
os = get_os ()
57
58
arch = get_arch ()
58
59
libc = get_libc ()
@@ -62,12 +63,12 @@ def compatible_julia_versions(compat=None, stable=True, kind=None):
62
63
ans = {}
63
64
for (k , v ) in all_julia_versions ().items ():
64
65
v = v .copy ()
65
- if stable is not None and v ['stable' ] != stable :
66
+ if not v ['stable' ]:
66
67
continue
67
68
files = []
68
69
for f in v ['files' ]:
69
70
assert f ['version' ] == k
70
- if kind is not None and f ['kind' ] != kind :
71
+ if not any ( f ['url' ]. endswith ( ext ) for ext in julia_installers ) :
71
72
continue
72
73
if f ['os' ] != os :
73
74
continue
@@ -92,27 +93,34 @@ def compatible_julia_versions(compat=None, stable=True, kind=None):
92
93
raise Exception (f'multiple matching triplets { sorted (triplets )} - this is a bug, please report' )
93
94
return ans
94
95
95
- def install_julia (vers , prefix ):
96
+ def best_julia_version (compat = None ):
97
+ vers = compatible_julia_versions (compat )
96
98
if not vers :
97
99
raise Exception ('no compatible Julia version found' )
98
- for v in sorted (vers .keys (), key = Version , reverse = True ):
99
- for f in vers [v ]['files' ]:
100
- url = f ['url' ]
101
- if url .endswith ('.tar.gz' ):
102
- installer = install_julia_tar_gz
103
- elif url .endswith ('.zip' ):
104
- installer = install_julia_zip
105
- elif url .endswith ('.dmg' ):
106
- installer = install_julia_dmg
107
- else :
108
- continue
109
- buf = download_julia (f )
110
- prefix2 = prefix .format (version = v )
111
- print (f'Installing Julia to { prefix2 } ' )
112
- if os .path .exists (prefix2 ):
113
- shutil .rmtree (prefix2 )
114
- installer (f , buf , prefix2 )
115
- return
100
+ v = sorted (vers .keys (), key = Version , reverse = True )[0 ]
101
+ return v , vers [v ]
102
+
103
+ def install_julia (ver , prefix ):
104
+ for f in ver ['files' ]:
105
+ url = f ['url' ]
106
+ # find a suitable installer
107
+ installer = None
108
+ for ext in julia_installers :
109
+ if url .endswith (ext ):
110
+ installer = julia_installers [ext ]
111
+ break
112
+ if installer is None :
113
+ continue
114
+ # download julia
115
+ buf = download_julia (f )
116
+ # include the version in the prefix
117
+ print (f'Installing Julia to { prefix } ' )
118
+ if os .path .exists (prefix ):
119
+ shutil .rmtree (prefix )
120
+ if os .path .dirname (prefix ):
121
+ os .makedirs (os .path .dirname (prefix ))
122
+ installer (f , buf , prefix )
123
+ return
116
124
raise Exception ('no installable Julia version found' )
117
125
118
126
def download_julia (f ):
@@ -130,7 +138,7 @@ def download_julia(f):
130
138
break
131
139
buf .write (data )
132
140
if time .time () > t :
133
- print (f' downloaded { buf .tell ()/ (1 << 20 ):.3f } MB of { size / (1 << 20 ):.3f } MB' )
141
+ print (f' downloaded { buf .tell ()/ (1 << 20 ):.1f } MB of { size / (1 << 20 ):.1f } MB' )
134
142
t = time .time () + freq
135
143
print (' download complete' )
136
144
print (f'Verifying download' )
@@ -144,55 +152,50 @@ def download_julia(f):
144
152
return buf
145
153
146
154
def install_julia_zip (f , buf , prefix ):
147
- os .makedirs (prefix )
148
- with zipfile .ZipFile (buf ) as zf :
149
- zf .extractall (prefix )
150
- fns = os .listdir (prefix )
151
- if 'bin' not in fns :
152
- if len (fns ) != 1 :
153
- raise Exception ('expecting one subdirectory' )
154
- top = fns [0 ]
155
- fns = os .listdir (os .path .join (prefix , top ))
156
- if 'bin' not in fns :
157
- raise Exception ('expecting a bin directory' )
158
- for fn in fns :
159
- os .rename (os .path .join (prefix , top , fn ), os .path .join (prefix , fn ))
160
- os .rmdir (os .path .join (prefix , top ))
155
+ with tempfile .TemporaryDirectory () as tmpdir :
156
+ # extract all files
157
+ with zipfile .ZipFile (buf ) as zf :
158
+ zf .extractall (tmpdir )
159
+ # copy stuff out
160
+ srcdirs = [d for d in os .listdir (tmpdir ) if d .startswith ('julia' )]
161
+ if len (srcdirs ) != 1 :
162
+ raise Exception ('expecting one julia* directory' )
163
+ shutil .copytree (os .path .join (tmpdir , srcdirs [0 ]), prefix , symlinks = True )
161
164
162
165
def install_julia_tar_gz (f , buf , prefix ):
163
- os .makedirs (prefix )
164
- with gzip .GzipFile (fileobj = buf ) as gf :
165
- with tarfile .TarFile (fileobj = gf ) as tf :
166
- tf .extractall (prefix )
167
- fns = os .listdir (prefix )
168
- if 'bin' not in fns :
169
- if len (fns ) != 1 :
170
- raise Exception ('expecting one subdirectory' )
171
- top = fns [0 ]
172
- fns = os .listdir (os .path .join (prefix , top ))
173
- if 'bin' not in fns :
174
- raise Exception ('expecting a bin directory' )
175
- for fn in fns :
176
- os .rename (os .path .join (prefix , top , fn ), os .path .join (prefix , fn ))
177
- os .rmdir (os .path .join (prefix , top ))
166
+ with tempfile .TemporaryDirectory () as tmpdir :
167
+ # extract all files
168
+ with gzip .GzipFile (fileobj = buf ) as gf :
169
+ with tarfile .TarFile (fileobj = gf ) as tf :
170
+ tf .extractall (tmpdir )
171
+ # copy stuff out
172
+ srcdirs = [d for d in os .listdir (tmpdir ) if d .startswith ('julia' )]
173
+ if len (srcdirs ) != 1 :
174
+ raise Exception ('expecting one julia* directory' )
175
+ shutil .copytree (os .path .join (tmpdir , srcdirs [0 ]), prefix , symlinks = True )
178
176
179
177
def install_julia_dmg (f , buf , prefix ):
180
- tmpdir = prefix + '.tmp'
181
- os .makedirs (tmpdir )
182
- # write the dmg file out
183
- dmg = os .path .join (tmpdir , 'dmg' )
184
- with open (dmg , 'wb' ) as f :
185
- f .write (buf .read ())
186
- # mount it
187
- mount = os .path .join (tmpdir , 'mount' )
188
- subprocess .run (['hdiutil' , 'mount' , '-mount' , 'required' , '-mountpoint' , mount , dmg ], check = True , capture_output = True )
189
- # copy stuff out
190
- appdirs = [d for d in os .listdir (mount ) if d .startswith ('Julia' ) and d .endswith ('.app' )]
191
- if len (appdirs ) != 1 :
192
- raise Exception ('expecting one Julia*.app directory' )
193
- srcdir = os .path .join (mount , appdirs [0 ], 'Contents' , 'Resources' , 'julia' )
194
- shutil .copytree (srcdir , prefix , symlinks = True )
195
- # unmount
196
- subprocess .run (['umount' , mount ], check = True , capture_output = True )
197
- # delete tmpdir
198
- shutil .rmtree (tmpdir )
178
+ with tempfile .TemporaryDirectory () as tmpdir :
179
+ # write the dmg file out
180
+ dmg = os .path .join (tmpdir , 'dmg' )
181
+ with open (dmg , 'wb' ) as f :
182
+ f .write (buf .read ())
183
+ # mount it
184
+ mount = os .path .join (tmpdir , 'mount' )
185
+ subprocess .run (['hdiutil' , 'mount' , '-mount' , 'required' , '-mountpoint' , mount , dmg ], check = True , capture_output = True )
186
+ try :
187
+ # copy stuff out
188
+ appdirs = [d for d in os .listdir (mount ) if d .startswith ('Julia' ) and d .endswith ('.app' )]
189
+ if len (appdirs ) != 1 :
190
+ raise Exception ('expecting one Julia*.app directory' )
191
+ srcdir = os .path .join (mount , appdirs [0 ], 'Contents' , 'Resources' , 'julia' )
192
+ shutil .copytree (srcdir , prefix , symlinks = True )
193
+ finally :
194
+ # unmount
195
+ subprocess .run (['umount' , mount ], check = True , capture_output = True )
196
+
197
+ julia_installers = {
198
+ '.tar.gz' : install_julia_tar_gz ,
199
+ '.zip' : install_julia_zip ,
200
+ '.dmg' : install_julia_dmg ,
201
+ }
0 commit comments