@@ -4,39 +4,90 @@ import Conda, JSON, TOML, Pkg, Dates, ..PythonCall
44
55# ## META
66
7- const _meta_file = Ref (" " )
8-
9- meta_file () = _meta_file[]
10-
11- function load_meta ()
12- fn = meta_file ()
13- isfile (fn) ? open (JSON. parse, fn) : Dict {String,Any} ()
7+ # increment whenever the format changes
8+ const META_VERSION = 1
9+
10+ Base. @kwdef struct Meta
11+ timestamp:: Float64
12+ load_path:: Vector{String}
13+ version:: VersionNumber
14+ files:: Vector{String}
15+ conda_packages:: Vector{String}
16+ conda_channels:: Vector{String}
17+ pip_packages:: Vector{String}
18+ pip_indexes:: Vector{String}
19+ scripts:: Vector{String}
1420end
1521
16- save_meta (meta) = open (io -> JSON. print (io, meta), meta_file (), " w" )
22+ function write_meta (io:: IO , meta:: Meta )
23+ write (io, Int (META_VERSION))
24+ write_meta (io, meta. timestamp)
25+ write_meta (io, meta. load_path)
26+ write_meta (io, meta. version)
27+ write_meta (io, meta. files)
28+ write_meta (io, meta. conda_packages)
29+ write_meta (io, meta. conda_channels)
30+ write_meta (io, meta. pip_packages)
31+ write_meta (io, meta. pip_indexes)
32+ write_meta (io, meta. scripts)
33+ end
1734
18- function get_meta (keys... )
19- meta = load_meta ()
20- for key in keys
21- if haskey (meta, key)
22- meta = meta[key]
23- else
24- return
25- end
35+ write_meta (io:: IO , x:: Float64 ) = write (io, x)
36+ write_meta (io:: IO , x:: VersionNumber ) = write_meta (io, string (x))
37+ function write_meta (io:: IO , x:: String )
38+ write (io, Int (sizeof (x)))
39+ write (io, x)
40+ end
41+ function write_meta (io:: IO , x:: Vector )
42+ write (io, Int (length (x)))
43+ for y in x
44+ write_meta (io, y)
2645 end
27- meta
2846end
2947
30- function set_meta (args... )
31- length (args) < 2 && error (" setmeta() takes at least 2 arguments" )
32- here = meta = load_meta ()
33- for key in args[1 : end - 2 ]
34- here = get! (Dict{String,Any}, here, key)
48+ function read_meta (io:: IO )
49+ if read (io, Int) == META_VERSION
50+ Meta (
51+ timestamp = read_meta (io, Float64),
52+ load_path = read_meta (io, Vector{String}),
53+ version = read_meta (io, VersionNumber),
54+ files = read_meta (io, Vector{String}),
55+ conda_packages = read_meta (io, Vector{String}),
56+ conda_channels = read_meta (io, Vector{String}),
57+ pip_packages = read_meta (io, Vector{String}),
58+ pip_indexes = read_meta (io, Vector{String}),
59+ scripts = read_meta (io, Vector{String}),
60+ )
61+ end
62+ end
63+ read_meta (io:: IO , :: Type{Float64} ) = read (io, Float64)
64+ read_meta (io:: IO , :: Type{VersionNumber} ) = VersionNumber (read_meta (io, String))
65+ function read_meta (io:: IO , :: Type{String} )
66+ n = read (io, Int)
67+ bytes = read (io, n)
68+ length (bytes) == n || error ()
69+ return String (bytes)
70+ end
71+ function read_meta (io:: IO , :: Type{Vector{T}} ) where {T}
72+ n = read (io, Int)
73+ x = Vector {T} ()
74+ for i in 1 : n
75+ push! (x, read_meta (io, T))
3576 end
36- here[args[end - 1 ]] = args[end ]
37- save_meta (meta)
77+ return x
78+ end
79+
80+ const _meta_file = Ref (" " )
81+
82+ meta_file () = _meta_file[]
83+
84+ function load_meta ()
85+ fn = meta_file ()
86+ isfile (fn) ? open (read_meta, fn) : nothing
3887end
3988
89+ save_meta (meta:: Meta ) = open (io -> write_meta (io, meta), meta_file (), " w" )
90+
4091# ## CONDA
4192
4293const _conda_env = Ref (" " )
@@ -150,19 +201,13 @@ function can_skip_resolve()
150201 # resolve if the conda environment doesn't exist yet
151202 isdir (conda_env ()) || return false
152203 # resolve if we haven't resolved before
153- deps = get_meta ( " jldeps " )
204+ deps = load_meta ( )
154205 deps === nothing && return false
155206 # resolve whenever the PythonCall version changes
156- version = get (deps, " version" , nothing )
157- version === nothing && return false
158- version != string (PythonCall. VERSION ) && return false
207+ deps. version == PythonCall. VERSION || return false
159208 # resolve whenever any of the environments in the load_path changes
160- timestamp = get (deps, " timestamp" , nothing )
161- timestamp === nothing && return false
162- timestamp = max (timestamp, stat (meta_file ()). mtime)
163- load_path = get (deps, " load_path" , nothing )
164- load_path === nothing && return false
165- load_path != Base. load_path () && return false
209+ timestamp = max (deps. timestamp, stat (meta_file ()). mtime)
210+ deps. load_path == Base. load_path () || return false
166211 for env in Base. load_path ()
167212 proj = Base. env_project_file (env)
168213 dir = nothing
@@ -286,14 +331,14 @@ function resolve(; create=true, force=false)
286331 env = conda_env ()
287332 skip = ! force && isdir (env)
288333 if skip
289- depinfo = get_meta ( " jldeps " )
290- skip & = (
334+ depinfo = load_meta ( )
335+ skip = (
291336 depinfo != = nothing &&
292- conda_channels == get ( depinfo, " conda_channels" , nothing ) &&
293- conda_packages == get ( depinfo, " conda_packages" , nothing ) &&
294- pip_indexes == get ( depinfo, " pip_indexes" , nothing ) &&
295- pip_packages == get ( depinfo, " pip_packages" , nothing ) &&
296- scripts == get ( depinfo, " scripts" , nothing )
337+ conda_channels == depinfo. conda_channels &&
338+ conda_packages == depinfo. conda_packages &&
339+ pip_indexes == depinfo. pip_indexes &&
340+ pip_packages == depinfo. pip_packages &&
341+ scripts == depinfo. scripts
297342 )
298343 end
299344
@@ -311,6 +356,7 @@ function resolve(; create=true, force=false)
311356 append! (conda_args, conda_packages)
312357 if create || ! isdir (env)
313358 ispath (env) && conda_run_root (` env remove --yes --prefix $env ` )
359+ ispath (env) && Base. rm (env, force= true , recursive= true )
314360 conda_run_root (` create --yes --no-default-packages --no-channel-priority --prefix $env $conda_args ` )
315361 conda_activate ()
316362 else
@@ -336,18 +382,17 @@ function resolve(; create=true, force=false)
336382 end
337383
338384 # record what we did
339- depinfo = Dict (
340- " timestamp" => time (),
341- " load_path" => Base. load_path (),
342- " version" => string (PythonCall. VERSION ),
343- " files" => all_deps_files,
344- " conda_packages" => conda_packages,
345- " conda_channels" => conda_channels,
346- " pip_packages" => pip_packages,
347- " pip_indexes" => pip_indexes,
348- " scripts" => scripts,
349- )
350- set_meta (" jldeps" , depinfo)
385+ save_meta (Meta (
386+ timestamp = time (),
387+ load_path = Base. load_path (),
388+ version = PythonCall. VERSION ,
389+ files = all_deps_files,
390+ conda_packages = conda_packages,
391+ conda_channels = conda_channels,
392+ pip_packages = pip_packages,
393+ pip_indexes = pip_indexes,
394+ scripts = scripts,
395+ ))
351396 end
352397
353398 return
0 commit comments