From 7d9dcd3adcbd994dd7948af923cf75d4d136719c Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sun, 19 Dec 2021 14:51:31 -0500 Subject: [PATCH] All infrastructure to allow Pkg to download all Artifacts --- base/binaryplatforms.jl | 11 ++++++-- stdlib/Artifacts/src/Artifacts.jl | 46 +++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index cfd7412faf656..7201d0a0702e7 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -1039,6 +1039,10 @@ platforms_match(a::AbstractPlatform, b::AbstractString) = platforms_match(a, str platforms_match(a::AbstractString, b::AbstractString) = platforms_match(string(a)::String, string(b)::String) +function filter_by_platform(download_info::Dict, platform::AbstractPlatform) + return collect(filter(p -> platforms_match(p, platform), keys(download_info))) +end + """ select_platform(download_info::Dict, platform::AbstractPlatform = HostPlatform()) @@ -1051,8 +1055,7 @@ match exactly, however attributes such as compiler ABI can have wildcards within them such as `nothing` which matches any version of GCC. """ function select_platform(download_info::Dict, platform::AbstractPlatform = HostPlatform()) - ps = collect(filter(p -> platforms_match(p, platform), keys(download_info))) - + ps = filter_by_platform(download_info, platform) if isempty(ps) return nothing end @@ -1063,6 +1066,10 @@ function select_platform(download_info::Dict, platform::AbstractPlatform = HostP # down, we just sort by triplet, then pick the last one. This has the effect # of generally choosing the latest release (e.g. a `libgfortran5` tarball # rather than a `libgfortran3` tarball) + # XXX: The reasoning above seems wrong. We actually need to download all of them + # since some of them could be custom platform tags. Future users should use + # the `filter_by_platform` function instead. + p = last(sort(ps, by = p -> triplet(p))) return download_info[p] end diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index 645e77944208b..c9feba3ab54ae 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -375,6 +375,15 @@ function artifact_meta(name::String, artifacts_toml::String; return artifact_meta(name, artifact_dict, artifacts_toml; platform=platform) end +function to_dl_dict(meta, name, artifacts_toml) + dl_dict = Dict{AbstractPlatform,Dict{String,Any}}() + for x in meta + x::Dict{String} + dl_dict[unpack_platform(x, name, artifacts_toml)] = x + end + return dl_dict +end + function artifact_meta(name::String, artifact_dict::Dict, artifacts_toml::String; platform::AbstractPlatform = HostPlatform()) if !haskey(artifact_dict, name) @@ -384,11 +393,7 @@ function artifact_meta(name::String, artifact_dict::Dict, artifacts_toml::String # If it's an array, find the entry that best matches our current platform if isa(meta, Vector) - dl_dict = Dict{AbstractPlatform,Dict{String,Any}}() - for x in meta - x::Dict{String} - dl_dict[unpack_platform(x, name, artifacts_toml)] = x - end + dl_dict = to_dl_dict(meta, name, artifacts_toml) meta = select_platform(dl_dict, platform) # If it's NOT a dict, complain elseif !isa(meta, Dict) @@ -406,6 +411,37 @@ function artifact_meta(name::String, artifact_dict::Dict, artifacts_toml::String return meta end +function all_artifact_meta(name::String, artifact_dict::Dict, artifacts_toml::String; + platform::AbstractPlatform = HostPlatform()) + if !haskey(artifact_dict, name) + return nothing + end + meta = artifact_dict[name] + + # If it's an array, find the entry that best matches our current platform + if isa(meta, Vector) + dl_dict = to_dl_dict(meta, name, artifacts_toml) + metas = filter_by_platform(dl_dict, platform) + # If it's NOT a dict, complain + elseif !isa(meta, Dict) + @error("Invalid artifacts file at $(artifacts_toml): artifact '$name' malformed, must be array or dict!") + return nothing + else + metas = [meta] + end + + # This is such a no-no, we are going to call it out right here, right now. + for meta in metas + if meta !== nothing && !haskey(meta, "git-tree-sha1") + @error("Invalid artifacts file at $(artifacts_toml): artifact '$name' contains no `git-tree-sha1`!") + return nothing + end + end + + # Return the full meta-dict. + return metas +end + """ artifact_hash(name::String, artifacts_toml::String; platform::AbstractPlatform = HostPlatform())