@@ -66,6 +66,14 @@ def self.default_cfgs_path
66
66
class Resolver
67
67
extend T ::Sig
68
68
69
+ # return type of #cfg_info
70
+ class ConfigInfo < T ::Struct
71
+ const :name , String
72
+ const :path , Pathname
73
+ const :unresolved_yaml , T ::Hash [ String , T . untyped ]
74
+ prop :resolved_yaml , T . nilable ( T ::Hash [ String , T . untyped ] )
75
+ end
76
+
69
77
# path to find database schema files
70
78
sig { returns ( Pathname ) }
71
79
attr_reader :schemas_path
@@ -86,6 +94,18 @@ class Resolver
86
94
sig { returns ( Pathname ) }
87
95
attr_reader :custom_path
88
96
97
+ # path to merged spec (merged with custom overley, but prior to resolution)
98
+ sig { params ( cfg_path_or_name : T . any ( String , Pathname ) ) . returns ( Pathname ) }
99
+ def merged_spec_path ( cfg_path_or_name )
100
+ @gen_path / "spec" / cfg_info ( cfg_path_or_name ) . name
101
+ end
102
+
103
+ # path to merged and resolved spec
104
+ sig { params ( cfg_path_or_name : T . any ( String , Pathname ) ) . returns ( Pathname ) }
105
+ def resolved_spec_path ( cfg_path_or_name )
106
+ @gen_path / "resolved_spec" / cfg_info ( cfg_path_or_name ) . name
107
+ end
108
+
89
109
# path to a python binary
90
110
sig { returns ( Pathname ) }
91
111
attr_reader :python_path
@@ -126,6 +146,9 @@ def initialize(
126
146
@custom_path = custom_path_override || ( @repo_root / "spec" / "custom" / "isa" )
127
147
@python_path = python_path_override || ( @repo_root / ".home" / ".venv" / "bin" / "python3" )
128
148
149
+ # cache of config names
150
+ @cfg_info = T . let ( { } , T ::Hash [ T . any ( String , Pathname ) , ConfigInfo ] )
151
+
129
152
FileUtils . mkdir_p @gen_path
130
153
end
131
154
@@ -151,23 +174,24 @@ def run(cmd)
151
174
# returns the config data
152
175
sig { params ( config_path : Pathname ) . returns ( T ::Hash [ String , T . untyped ] ) }
153
176
def resolve_config ( config_path )
154
- config_yaml = T . nilable ( T :: Hash [ String , T . untyped ] )
155
- config_name = config_path . basename ( ".yaml" )
177
+ config_info = cfg_info ( config_path )
178
+ return T . must ( config_info . resolved_yaml ) unless config_info . resolved_yaml . nil?
156
179
180
+ resolved_config_yaml = T . let ( { } , T . nilable ( T ::Hash [ String , T . untyped ] ) )
157
181
# write the config with arch_overlay expanded
158
- if any_newer? ( gen_path / "cfgs" / "#{ config_name } .yaml" , [ config_path ] )
159
- config_yaml = YAML . load_file ( config_path )
160
-
182
+ if any_newer? ( gen_path / "cfgs" / "#{ config_info . name } .yaml" , [ config_path ] )
161
183
# is there anything to do here? validate?
162
184
185
+ resolved_config_yaml = config_info . unresolved_yaml . dup
186
+ resolved_config_yaml [ "$source" ] = config_path . realpath . to_s
187
+
163
188
FileUtils . mkdir_p gen_path / "cfgs"
164
- File . write ( gen_path / "cfgs" / "#{ config_name } .yaml" , YAML . dump ( config_yaml ) )
189
+ File . write ( gen_path / "cfgs" / "#{ config_info . name } .yaml" , YAML . dump ( resolved_config_yaml ) )
165
190
else
166
- config_yaml = YAML . load_file ( gen_path / "cfgs" / "#{ config_name } .yaml" )
191
+ resolved_config_yaml = YAML . load_file ( gen_path / "cfgs" / "#{ config_info . name } .yaml" )
167
192
end
168
193
169
- config_yaml [ "$source" ] = config_path . realpath
170
- config_yaml
194
+ config_info . resolved_yaml = resolved_config_yaml
171
195
end
172
196
173
197
sig { params ( config_yaml : T ::Hash [ String , T . untyped ] ) . void }
@@ -189,16 +213,16 @@ def merge_arch(config_yaml)
189
213
end
190
214
raise "custom directory '#{ overlay_path } ' does not exist" if !overlay_path . nil? && !overlay_path . directory?
191
215
192
- if any_newer? ( gen_path / "spec" / config_name / ".stamp" , deps )
216
+ if any_newer? ( merged_spec_path ( config_name ) / ".stamp" , deps )
193
217
run [
194
218
python_path . to_s ,
195
219
"#{ Udb . gem_path } /python/yaml_resolver.py" ,
196
220
"merge" ,
197
221
std_path . to_s ,
198
222
overlay_path . nil? ? "/does/not/exist" : overlay_path . to_s ,
199
- " #{ gen_path } /spec/ #{ config_name } "
223
+ merged_spec_path ( config_name ) . to_s
200
224
]
201
- FileUtils . touch ( gen_path / "spec" / config_name / ".stamp" )
225
+ FileUtils . touch ( merged_spec_path ( config_name ) / ".stamp" )
202
226
end
203
227
end
204
228
@@ -207,46 +231,58 @@ def resolve_arch(config_yaml)
207
231
merge_arch ( config_yaml )
208
232
config_name = config_yaml [ "name" ]
209
233
210
- deps = Dir [ gen_path / "arch" / config_yaml [ "name" ] / "**" / "*.yaml" ] . map { |p | Pathname . new ( p ) }
211
- if any_newer? ( gen_path / "resolved_spec" / config_yaml [ "name" ] / ".stamp" , deps )
234
+ deps = Dir [ merged_spec_path ( config_name ) / "**" / "*.yaml" ] . map { |p | Pathname . new ( p ) }
235
+ if any_newer? ( resolved_spec_path ( config_name ) / ".stamp" , deps )
212
236
run [
213
237
python_path . to_s ,
214
238
"#{ Udb . gem_path } /python/yaml_resolver.py" ,
215
239
"resolve" ,
216
- " #{ gen_path } /spec/ #{ config_name } " ,
217
- " #{ gen_path } /resolved_spec/ #{ config_name } "
240
+ merged_spec_path ( config_name ) . to_s ,
241
+ resolved_spec_path ( config_name ) . to_s
218
242
]
219
- FileUtils . touch ( gen_path / "resolved_spec" / config_yaml [ "name" ] / ".stamp" )
243
+ FileUtils . touch ( resolved_spec_path ( config_name ) / ".stamp" )
220
244
end
221
245
end
222
246
223
- # resolve the specification for a config, and return a ConfiguredArchitecture
224
- sig { params ( config_path_or_name : T . any ( Pathname , String ) ) . returns ( Udb ::ConfiguredArchitecture ) }
225
- def cfg_arch_for ( config_path_or_name )
247
+ sig { params ( config_path_or_name : T . any ( Pathname , String ) ) . returns ( ConfigInfo ) }
248
+ def cfg_info ( config_path_or_name )
249
+ return @cfg_info . fetch ( config_path_or_name ) if config_path_or_name . is_a? ( String ) && @cfg_info . key? ( config_path_or_name )
250
+ return @cfg_info . fetch ( config_path_or_name . realpath ) if config_path_or_name . is_a? ( Pathname ) && @cfg_info . key? ( config_path_or_name . realpath )
251
+
226
252
config_path =
227
253
case config_path_or_name
228
254
when Pathname
229
255
raise "Path does not exist: #{ config_path_or_name } " unless config_path_or_name . file?
230
256
231
- config_path_or_name
257
+ config_path_or_name . realpath
232
258
when String
233
- @repo_root / "cfgs" / "#{ config_path_or_name } .yaml"
259
+ ( @repo_root / "cfgs" / "#{ config_path_or_name } .yaml" ) . realpath
234
260
else
235
261
T . absurd ( config_path_or_name )
236
262
end
237
263
238
- @cfg_archs ||= { }
239
- return @cfg_archs [ config_path ] if @cfg_archs . key? ( config_path )
264
+ config_yaml = YAML . safe_load_file ( config_path )
265
+ info = ConfigInfo . new ( name : config_yaml [ "name" ] , path : config_path , unresolved_yaml : config_yaml )
266
+ @cfg_info [ config_path ] = info
267
+ @cfg_info [ info . name ] = info
268
+ end
269
+ private :cfg_info
240
270
241
- config_yaml = resolve_config ( config_path )
242
- config_name = config_yaml [ "name" ]
271
+ # resolve the specification for a config, and return a ConfiguredArchitecture
272
+ sig { params ( config_path_or_name : T . any ( Pathname , String ) ) . returns ( Udb ::ConfiguredArchitecture ) }
273
+ def cfg_arch_for ( config_path_or_name )
274
+ config_info = cfg_info ( config_path_or_name )
275
+
276
+ @cfg_archs ||= { }
277
+ return @cfg_archs [ config_info . path ] if @cfg_archs . key? ( config_info . path )
243
278
244
- resolve_arch ( config_yaml )
279
+ resolve_config ( config_info . path )
280
+ resolve_arch ( config_info . unresolved_yaml )
245
281
246
- @cfg_archs [ config_path ] = Udb ::ConfiguredArchitecture . new (
247
- config_name ,
248
- Udb ::AbstractConfig . create ( gen_path / "cfgs" / "#{ config_name } .yaml" ) ,
249
- gen_path / "resolved_spec" / config_name
282
+ @cfg_archs [ config_info . path ] = Udb ::ConfiguredArchitecture . new (
283
+ config_info . name ,
284
+ Udb ::AbstractConfig . create ( gen_path / "cfgs" / "#{ config_info . name } .yaml" ) ,
285
+ resolved_spec_path ( config_info . name )
250
286
)
251
287
end
252
288
end
0 commit comments