@@ -4,6 +4,7 @@ using UUIDs
4
4
using TOML
5
5
using SHA
6
6
using ResourceContexts
7
+ using Base: PkgId
7
8
8
9
export DataSet, dataset, @datafunc , @datarun
9
10
export Blob, BlobTree, newfile, newdir
@@ -215,6 +216,8 @@ identifier, `nothing` is returned.
215
216
"""
216
217
project_name (data_project:: AbstractDataProject ) = nothing
217
218
219
+ data_drivers (proj:: AbstractDataProject ) = []
220
+
218
221
# -------------------------------------------------------------------------------
219
222
"""
220
223
DataProject
@@ -224,11 +227,15 @@ Names are unique within the project.
224
227
"""
225
228
struct DataProject <: AbstractDataProject
226
229
datasets:: Dict{String,DataSet}
230
+ drivers:: Vector{Dict{String,Any}}
227
231
end
228
232
229
- DataProject () = DataProject (Dict {String,DataSet} ())
233
+ DataProject () = DataProject (Dict {String,DataSet} (), Vector {Dict{String,Any}} ())
234
+
235
+ DataProject (project:: AbstractDataProject ) = DataProject (Dict (pairs (project)),
236
+ Vector {Dict{String,Any}} ())
230
237
231
- DataProject (project:: AbstractDataProject ) = DataProject ( Dict ( pairs ( project)))
238
+ data_drivers (project:: DataProject ) = project. drivers
232
239
233
240
function _fill_template (toml_path, toml_str)
234
241
# Super hacky templating for paths relative to the toml file.
@@ -276,6 +283,14 @@ function load_project(config::AbstractDict; kws...)
276
283
dataset = DataSet (dataset_conf)
277
284
link_dataset (proj, dataset. name => dataset)
278
285
end
286
+ if haskey (config, " drivers" )
287
+ _check_keys (config, DataProject, [" drivers" => AbstractVector])
288
+ for driver_conf in config[" drivers" ]
289
+ _check_keys (driver_conf, DataProject, [" type" => String, " name" => String, " module" => Dict])
290
+ _check_keys (driver_conf[" module" ], DataProject, [" name" => String, " uuid" => String])
291
+ push! (proj. drivers, driver_conf)
292
+ end
293
+ end
279
294
proj
280
295
end
281
296
363
378
364
379
StackedDataProject () = StackedDataProject ([])
365
380
381
+ data_drivers (stack:: StackedDataProject ) = vcat (data_drivers .(stack. projects)... )
382
+
366
383
function Base. keys (stack:: StackedDataProject )
367
384
names = []
368
385
for project in stack. projects
@@ -479,8 +496,23 @@ PROJECT = StackedDataProject()
479
496
# deprecated. TODO : Remove dependency on this from JuliaHub
480
497
_current_project = DataProject ()
481
498
499
+ _isprecompiling () = ccall (:jl_generating_output , Cint, ()) == 1
500
+
482
501
function __init__ ()
483
- global PROJECT = create_project_stack (ENV )
502
+ # Triggering Base.require for storage drivers during precompilation should
503
+ # be unnecessary and can cause problems if those driver modules use
504
+ # Requires-like code loading.
505
+ if ! _isprecompiling ()
506
+ global PROJECT = create_project_stack (ENV )
507
+ for proj in PROJECT. projects
508
+ try
509
+ add_storage_driver (proj)
510
+ catch exc
511
+ @error " Could not load storage drivers from data project" #=
512
+ =# project= proj exception= (exc,catch_backtrace ())
513
+ end
514
+ end
515
+ end
484
516
end
485
517
486
518
dataset (name) = dataset (PROJECT, name)
@@ -494,6 +526,7 @@ May be renamed in a future version.
494
526
"""
495
527
function load_project! (path_or_config)
496
528
new_project = load_project (path_or_config, auto_update= true )
529
+ add_storage_driver (new_project)
497
530
pushfirst! (PROJECT, new_project)
498
531
# deprecated: _current_project reflects only the initial version of the
499
532
# project on *top* of the stack.
@@ -527,6 +560,33 @@ function add_storage_driver((name,opener)::Pair)
527
560
end
528
561
end
529
562
563
+ function add_storage_driver (project:: AbstractDataProject )
564
+ for conf in data_drivers (project)
565
+ if conf[" type" ] != " storage"
566
+ # Anticipate there might be layer drivers too
567
+ continue
568
+ end
569
+ pkgid = PkgId (UUID (conf[" module" ][" uuid" ]), conf[" module" ][" name" ])
570
+ if Base. haskey (Base. package_locks, pkgid)
571
+ # Hack: Avoid triggering another call to require() for packages
572
+ # which are already in the process of being loaded. (This would
573
+ # result in a deadlock!)
574
+ #
575
+ # Obviously this depends on Base internals...
576
+ continue
577
+ end
578
+ mod = Base. require (pkgid)
579
+ driver_name = conf[" name" ]
580
+ # Module itself does add_storage_driver() inside its __init__
581
+ # TODO : Is this a good workflow?
582
+ lock (_storage_drivers_lock) do
583
+ get (_storage_drivers, driver_name) do
584
+ error (" Package $pkgid did not provide storage driver $driver_name " )
585
+ end
586
+ end
587
+ end
588
+ end
589
+
530
590
function _find_driver (dataset)
531
591
storage_config = dataset. storage
532
592
driver_name = get (storage_config, " driver" ) do
0 commit comments