/
state.jl
108 lines (90 loc) · 3.56 KB
/
state.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import Base: show
abstract type AbstractWizardDependency; end
struct InlineBuildDependency <: AbstractWizardDependency
script::String
end
struct RemoteBuildDependency <: AbstractWizardDependency
url::String
script::Union{String, Nothing}
end
struct TarballDependency <: AbstractWizardDependency
url::String
hash::String
end
"""
WizardState
Building large dependencies can take a lot of time. This state object captures
all relevant state of this function. It can be passed back to the function to
resume where we left off. This can aid debugging when code changes are
necessary. It also holds all necessary metadata such as input/output streams.
"""
@Base.kwdef mutable struct WizardState
step::Symbol = :step1
ins::IO = stdin
outs::IO = stdout
# Filled in by step 1
platforms::Union{Nothing, Vector{Platform}} = nothing
# Filled in by step 2
workspace::Union{Nothing, String} = nothing
source_urls::Union{Nothing, Vector{String}} = nothing
source_files::Union{Nothing, Vector{SetupSource}} = nothing
dependencies::Union{Nothing, Vector{Dependency}} = nothing
compilers::Union{Nothing, Vector{Symbol}} = nothing
preferred_gcc_version::Union{Nothing, VersionNumber} = nothing
preferred_llvm_version::Union{Nothing, VersionNumber} = nothing
# Filled in by step 3
history::Union{Nothing, String} = nothing
files::Union{Nothing, Vector{String}} = nothing
file_kinds::Union{Nothing, Vector{Symbol}} = nothing
file_varnames::Union{Nothing, Vector{Symbol}} = nothing
patches::Vector{PatchSource} = PatchSource[]
# Filled in by step 5c
failed_platforms::Set{Platform} = Set{Platform}()
# Used to keep track of which platforms we already visited
visited_platforms::Set{Platform} = Set{Platform}()
# Used to keep track of which platforms we have shown to work
# with the current script. This gets reset if the script is edited.
validated_platforms::Set{Platform} = Set{Platform}()
# Filled in by step 7
name::Union{Nothing, String} = nothing
version::Union{Nothing, VersionNumber} = nothing
github_api::GitHub.GitHubAPI = GitHub.DEFAULT_API
travis_endpoint::String = "https://api.travis-ci.org/"
end
function serializeable_fields(::WizardState)
# We can't serialize TTY's, in general.
bad_fields = [:ins, :outs, :github_api]
return [f for f in fieldnames(WizardState) if !(f in bad_fields)]
end
# Serialize a WizardState out into a JLD2 dictionary-like object
function serialize(io, x::WizardState)
for field in serializeable_fields(x)
io[string(field)] = getproperty(x, field)
end
# For unnecessarily complicated fields (such as `x.github_api`) store the internal data raw:
io["github_api"] = string(x.github_api.endpoint)
# For non-serializable fields (such as `x.ins` and `x.outs`) we just recreate them in unserialize().
end
function unserialize(io)
x = WizardState()
for field in serializeable_fields(x)
setproperty!(x, field, io[string(field)])
end
# Manually recreate `ins` and `outs`. Note that this just sets them to their default values
x.ins = stdin
x.outs = stdout
x.github_api = GitHub.GitHubWebAPI(HTTP.URI(io["github_api"]))
return x
end
# Compare only serializeable fields when checking ==
function Base.:(==)(x::WizardState, y::WizardState)
for field in serializeable_fields(x)
if getproperty(x, field) != getproperty(y, field)
return false
end
end
return true
end
function show(io::IO, x::WizardState)
print(io, "WizardState [$(x.step)]")
end