@@ -6,16 +6,16 @@ load("//rs/private:annotations.bzl", "annotation_for", "build_annotation_map", "
66load ("//rs/private:cargo_credentials.bzl" , "load_cargo_credentials" )
77load (
88 "//rs/private:cargo_workspace_graph.bzl" ,
9+ "cargo_toml_fact" ,
910 "platform_label" ,
1011 "render_dep_data" ,
1112 "render_string_list" ,
1213 "resolve_cargo_workspace_members" ,
14+ "resolve_package_facts" ,
15+ "split_lockfile_packages" ,
1316 "workspace_dep_data" ,
14- _add_to_dict = "add_to_dict" ,
1517 _fq_crate = "fq_crate" ,
16- _new_feature_resolutions = "new_feature_resolutions" ,
1718 _normalize_path = "normalize_path" ,
18- _prepare_possible_deps = "prepare_possible_deps" ,
1919 _select = "select_items" ,
2020)
2121load ("//rs/private:crate_repository.bzl" , "crate_repository" , "local_crate_repository" )
@@ -56,26 +56,6 @@ def _date(ctx, label):
5656 result = ctx .execute (["gdate" , '+"%Y-%m-%d %H:%M:%S.%3N"' ])
5757 print (label , result .stdout )
5858
59- def _relative_to_workspace (path , workspace_root ):
60- normalized_root = _normalize_path (workspace_root )
61- normalized_path = _normalize_path (path )
62-
63- if not paths .is_absolute (normalized_path ):
64- normalized_path = _normalize_path (paths .normalize (paths .join (normalized_root , normalized_path )))
65-
66- root_parts = [p for p in normalized_root .split ("/" ) if p ]
67- path_parts = [p for p in normalized_path .split ("/" ) if p ]
68-
69- common = 0
70- max_common = min (len (root_parts ), len (path_parts ))
71- for idx in range (max_common ):
72- if root_parts [idx ] != path_parts [idx ]:
73- break
74- common = idx + 1
75-
76- rel_parts = [".." ] * (len (root_parts ) - common ) + path_parts [common :]
77- return "/" .join (rel_parts ) if rel_parts else "."
78-
7959def _label_directory (label ):
8060 idx = label .name .rfind ("/" )
8161 if idx == - 1 :
@@ -105,54 +85,6 @@ def _additive_build_file_content(mctx, annotation):
10585 content += annotation .additive_build_file_content
10686 return content
10787
108- def _spec_to_dep_dict_inner (dep , spec , is_build = False ):
109- if type (spec ) == "string" :
110- dep = {"name" : dep }
111- else :
112- dep = {
113- "name" : dep ,
114- "optional" : spec .get ("optional" , False ),
115- "default_features" : spec .get ("default_features" , spec .get ("default-features" , True )),
116- "features" : spec .get ("features" , []),
117- }
118- if "package" in spec :
119- dep ["package" ] = spec ["package" ]
120-
121- if is_build :
122- dep ["kind" ] = "build"
123-
124- return dep
125-
126- def _spec_to_dep_dict (dep , spec , annotation , workspace_cargo_toml_json , is_build = False ):
127- if type (spec ) == "dict" and spec .get ("workspace" ) == True :
128- workspace = workspace_cargo_toml_json .get ("workspace" )
129- if not workspace and annotation .workspace_cargo_toml != "Cargo.toml" :
130- fail ("""
131-
132- ERROR: `crate.annotation` for `{name}` has a `workspace_cargo_toml` pointing to a Cargo.toml without a `workspace` section. Please correct it in your MODULE.bazel!
133- Make sure you point to the `Cargo.toml` of the workspace, not of `{name}`!”
134-
135- """ .format (name = annotation .crate ))
136-
137- inherited = _spec_to_dep_dict_inner (
138- dep ,
139- workspace ["dependencies" ][dep ],
140- is_build ,
141- )
142-
143- extra_features = spec .get ("features" )
144- if extra_features :
145- inherited ["features" ] = sorted (set (extra_features + inherited .get ("features" , [])))
146-
147- if spec .get ("optional" ):
148- inherited ["optional" ] = True
149-
150- if spec .get ("package" ):
151- inherited ["package" ] = spec ["package" ]
152-
153- return inherited
154- return _spec_to_dep_dict_inner (dep , spec , is_build )
155-
15688def _generate_hub_and_spokes (
15789 mctx ,
15890 hub_name ,
@@ -203,79 +135,23 @@ def _generate_hub_and_spokes(
203135 existing_facts = getattr (mctx , "facts" , {}) or {}
204136 facts = {}
205137
206- workspace_root = _normalize_path (cargo_metadata ["workspace_root" ])
207- workspace_root_prefix = workspace_root + "/"
208- workspace_member_keys = {}
209- for package in cargo_metadata ["packages" ]:
210- workspace_member_keys [(package ["name" ], package ["version" ])] = True
211-
212- dep_paths_by_name = {}
213- for package in cargo_metadata ["packages" ]:
214- for dep in package .get ("dependencies" , []):
215- dep_path = dep .get ("path" )
216- if dep_path :
217- dep_paths_by_name [dep ["name" ]] = _relative_to_workspace (dep_path , workspace_root )
218-
219- patch_paths_by_name = {}
220- for registry_patches in workspace_cargo_toml_json .get ("patch" , {}).values ():
221- for name , spec in registry_patches .items ():
222- if type (spec ) != "dict" :
223- continue
224-
225- patch_path = spec .get ("path" )
226- if not patch_path :
227- continue
228-
229- if patch_path .startswith ("/" ):
230- normalized = _normalize_path (patch_path )
231- if not normalized .startswith (workspace_root_prefix ):
232- fail ("Patch path for %s points outside the workspace: %s" % (name , patch_path ))
233- rel_patch_path = normalized .removeprefix (workspace_root_prefix )
234- else :
235- rel_patch_path = _normalize_path (paths .normalize (patch_path ))
236-
237- patch_paths_by_name [name ] = rel_patch_path
238-
239- workspace_members = []
240- packages = []
241-
242- for package in all_packages :
243- pkg = dict (package )
244-
245- if pkg .get ("source" ):
246- packages .append (pkg )
247- continue
248-
249- key = (pkg ["name" ], pkg ["version" ])
250- if key in workspace_member_keys :
251- workspace_members .append (pkg )
252- continue
253-
254- rel_path = patch_paths_by_name .get (pkg ["name" ]) or dep_paths_by_name .get (pkg ["name" ])
255- local_path = rel_path
256- if rel_path and not rel_path .startswith ("/" ):
257- local_path = paths .join (workspace_root , rel_path )
258-
259- if not local_path :
260- fail ("Found a path dependency on %s %s but could not determine its path from Cargo.toml. Please declare it in [patch] or as a path dependency." % (pkg ["name" ], pkg ["version" ]))
261-
262- pkg ["source" ] = "path+" + hub_name + "/" + rel_path
263- pkg ["local_path" ] = local_path
264- packages .append (pkg )
138+ split_packages = split_lockfile_packages (
139+ hub_name ,
140+ cargo_metadata ,
141+ workspace_cargo_toml_json ,
142+ all_packages ,
143+ )
144+ packages = split_packages .packages
145+ workspace_members = split_packages .workspace_members
265146
266147 mctx .report_progress ("Computing dependencies and features" )
267148
268- feature_resolutions_by_fq_crate = dict ()
269-
270- versions_by_name = dict ()
271- for package_index in range (len (packages )):
272- package = packages [package_index ]
149+ facts_by_fq_crate = {}
150+ for package in packages :
273151 name = package ["name" ]
274152 version = package ["version" ]
275153 source = package ["source" ]
276154
277- _add_to_dict (versions_by_name , name , version )
278-
279155 if source .startswith ("sparse+" ):
280156 key = name + "_" + version
281157 fact = existing_facts .get (key )
@@ -332,26 +208,7 @@ def _generate_hub_and_spokes(
332208 mctx .watch (mctx .path (cargo_toml_path ))
333209 annotation = annotation_for (annotations , name , package ["version" ])
334210 cargo_toml_json = run_toml2json (mctx , cargo_toml_path )
335-
336- dependencies = [
337- _spec_to_dep_dict (dep , spec , annotation , {})
338- for dep , spec in cargo_toml_json .get ("dependencies" , {}).items ()
339- ] + [
340- _spec_to_dep_dict (dep , spec , annotation , {}, is_build = True )
341- for dep , spec in cargo_toml_json .get ("build-dependencies" , {}).items ()
342- ]
343-
344- for target , value in cargo_toml_json .get ("target" , {}).items ():
345- for dep , spec in value .get ("dependencies" , {}).items ():
346- converted = _spec_to_dep_dict (dep , spec , annotation , {})
347- converted ["target" ] = target
348- dependencies .append (converted )
349-
350- fact = dict (
351- features = cargo_toml_json .get ("features" , {}),
352- dependencies = dependencies ,
353- strip_prefix = "" ,
354- )
211+ fact = cargo_toml_fact (cargo_toml_json , {})
355212
356213 facts [key ] = json .encode (fact )
357214 package ["strip_prefix" ] = fact .get ("strip_prefix" , "" )
@@ -375,28 +232,10 @@ def _generate_hub_and_spokes(
375232 package_workspace_cargo_toml_json = package .get ("workspace_cargo_toml_json" )
376233 strip_prefix = package .get ("strip_prefix" , "" )
377234
378- dependencies = [
379- _spec_to_dep_dict (dep , spec , annotation , package_workspace_cargo_toml_json )
380- for dep , spec in cargo_toml_json .get ("dependencies" , {}).items ()
381- ] + [
382- _spec_to_dep_dict (dep , spec , annotation , package_workspace_cargo_toml_json , is_build = True )
383- for dep , spec in cargo_toml_json .get ("build-dependencies" , {}).items ()
384- ]
385-
386- for target , value in cargo_toml_json .get ("target" , {}).items ():
387- for dep , spec in value .get ("dependencies" , {}).items ():
388- converted = _spec_to_dep_dict (dep , spec , annotation , package_workspace_cargo_toml_json )
389- converted ["target" ] = target
390- dependencies .append (converted )
391-
392- if not dependencies and debug :
393- print (name , version , package ["source" ])
235+ fact = cargo_toml_fact (cargo_toml_json , package_workspace_cargo_toml_json , strip_prefix = strip_prefix )
394236
395- fact = dict (
396- features = cargo_toml_json .get ("features" , {}),
397- dependencies = dependencies ,
398- strip_prefix = strip_prefix ,
399- )
237+ if not fact ["dependencies" ] and debug :
238+ print (name , version , package ["source" ])
400239
401240 # Nest a serialized JSON since max path depth is 5.
402241 facts [key ] = json .encode (fact )
@@ -405,11 +244,11 @@ def _generate_hub_and_spokes(
405244 else :
406245 fail ("Unknown source %s for crate %s" % (source , name ))
407246
408- possible_features = fact [ "features" ]
409- possible_deps = _prepare_possible_deps ( fact [ "dependencies" ])
410- feature_resolutions = _new_feature_resolutions ( package_index , possible_deps , possible_features , platform_triples )
411- package [ "feature_resolutions" ] = feature_resolutions
412- feature_resolutions_by_fq_crate [ _fq_crate ( name , version )] = feature_resolutions
247+ facts_by_fq_crate [ _fq_crate ( name , version )] = fact
248+
249+ resolved_facts = resolve_package_facts ( packages , facts_by_fq_crate , platform_triples )
250+ feature_resolutions_by_fq_crate = resolved_facts . feature_resolutions_by_fq_crate
251+ versions_by_name = resolved_facts . versions_by_name
413252
414253 # Only files in the current Bazel workspace can/should be watched, so check where our manifests are located.
415254 watch_manifests = cargo_lock_path .repo_name == ""
0 commit comments