@@ -5,10 +5,10 @@ load("@rs_rust_host_tools//:defs.bzl", "RS_HOST_CARGO_LABEL")
55load ("//rs/private:annotations.bzl" , "annotation_for" , "build_annotation_map" , "well_known_annotation_snippet_paths" )
66load ("//rs/private:cargo_credentials.bzl" , "load_cargo_credentials" )
77load ("//rs/private:cfg_parser.bzl" , "cfg_matches_expr_for_cfg_attrs" , "triple_to_cfg_attrs" )
8- load ("//rs/private:crate_git_repository.bzl" , "crate_git_repository" )
98load ("//rs/private:crate_repository.bzl" , "crate_repository" , "local_crate_repository" )
109load ("//rs/private:downloader.bzl" , "download_metadata_for_git_crates" , "new_downloader_state" , "parse_git_url" , "start_crate_registry_downloads" , "start_github_downloads" )
11- load ("//rs/private:git_repository.bzl" , "git_repository" )
10+ load ("//rs/private:git_cargo_workspace_repository.bzl" , "git_cargo_workspace_repository" )
11+ load ("//rs/private:git_crate_metadata_repository.bzl" , "git_crate_metadata_repository" )
1212load ("//rs/private:lint_flags.bzl" , "cargo_toml_lint_flags" )
1313load ("//rs/private:registry_config_repository.bzl" , "registry_config_repository" )
1414load ("//rs/private:registry_utils.bzl" , "CRATES_IO_REGISTRY" , "registry_config_repo_name" )
@@ -24,8 +24,11 @@ def _spoke_repo(hub_name, name, version):
2424 s = s .replace ("+" , "-" )
2525 return s
2626
27- def _external_repo_for_git_source (remote , commit ):
28- return remote .replace ("/" , "_" ).replace (":" , "_" ).replace ("@" , "_" ) + "_" + commit
27+ def _external_repo_for_git_source (hub_name , remote , commit ):
28+ return hub_name + "__" + remote .replace ("/" , "_" ).replace (":" , "_" ).replace ("@" , "_" ) + "_" + commit
29+
30+ def _git_crate_purl (name , version , remote , commit ):
31+ return "pkg:cargo/%s@%s?vcs_url=git+%s@%s" % (name , version , remote , commit )
2932
3033def _platform (triple , use_legacy_rules_rust_platforms ):
3134 if use_legacy_rules_rust_platforms :
@@ -149,6 +152,28 @@ def _manifest_package_dir(manifest_path, repo_root):
149152
150153 return package_dir .removesuffix ("/Cargo.toml" )
151154
155+ def _git_crate_package_path (annotation , strip_prefix ):
156+ workspace_dir = annotation .workspace_cargo_toml .removesuffix ("Cargo.toml" ).removesuffix ("/" )
157+ crate_dir = (strip_prefix or "" ).removeprefix ("./" ).removesuffix ("/" )
158+
159+ if workspace_dir and crate_dir :
160+ return _normalize_path (paths .normalize (paths .join (workspace_dir , crate_dir )))
161+ if workspace_dir :
162+ return _normalize_path (workspace_dir )
163+ return _normalize_path (crate_dir )
164+
165+ def _target_label (repo_name , package_path , target ):
166+ if package_path :
167+ return "@%s//%s:%s" % (repo_name , package_path , target )
168+ return "@%s//:%s" % (repo_name , target )
169+
170+ def _additive_build_file_content (mctx , annotation ):
171+ content = ""
172+ if annotation .additive_build_file :
173+ content += mctx .read (annotation .additive_build_file )
174+ content += annotation .additive_build_file_content
175+ return content
176+
152177def _spec_to_dep_dict_inner (dep , spec , is_build = False ):
153178 if type (spec ) == "string" :
154179 dep = {"name" : dep }
@@ -746,8 +771,6 @@ crate.annotation(
746771
747772 kwargs = dict (
748773 hub_name = hub_name ,
749- additive_build_file = annotation .additive_build_file ,
750- additive_build_file_content = annotation .additive_build_file_content ,
751774 gen_build_script = annotation .gen_build_script ,
752775 build_script_deps = [],
753776 build_script_deps_select = _select (feature_resolutions .build_deps ),
@@ -766,16 +789,14 @@ crate.annotation(
766789 crate_tags = annotation .tags ,
767790 deps_select = _select (feature_resolutions .deps ),
768791 aliases = feature_resolutions .aliases ,
769- gen_binaries = annotation .gen_binaries ,
770792 crate_features = annotation .crate_features ,
771793 crate_features_select = _select (feature_resolutions .features_enabled ),
772- patch_args = annotation .patch_args ,
773- patch_tool = annotation .patch_tool ,
774- patches = annotation .patches ,
775794 use_legacy_rules_rust_platforms = use_legacy_rules_rust_platforms ,
776795 )
777796
778797 repo_name = _spoke_repo (hub_name , crate_name , version )
798+ package ["target_repo_name" ] = repo_name
799+ package ["target_package_path" ] = ""
779800
780801 if source .startswith ("sparse+" ):
781802 checksum = package ["checksum" ]
@@ -789,11 +810,17 @@ crate.annotation(
789810
790811 crate_repository (
791812 name = repo_name ,
813+ additive_build_file = annotation .additive_build_file ,
814+ additive_build_file_content = annotation .additive_build_file_content ,
792815 crate_name = crate_name ,
793816 version = version ,
794817 registry_config = "@%s//:dl" % registry_config_repo_name (hub_name , source ),
795818 sbom_extra_qualifiers = qualifiers ,
796819 checksum = checksum ,
820+ gen_binaries = annotation .gen_binaries ,
821+ patch_args = annotation .patch_args ,
822+ patch_tool = annotation .patch_tool ,
823+ patches = annotation .patches ,
797824 # The repository will need to recompute these, but this lets us avoid serializing them.
798825 use_home_cargo_credentials = use_home_cargo_credentials ,
799826 cargo_config = cargo_config ,
@@ -807,26 +834,30 @@ crate.annotation(
807834 # TODO What PURL should that be ?
808835 local_crate_repository (
809836 name = repo_name ,
837+ additive_build_file = annotation .additive_build_file ,
838+ additive_build_file_content = annotation .additive_build_file_content ,
839+ gen_binaries = annotation .gen_binaries ,
840+ patch_args = annotation .patch_args ,
841+ patch_tool = annotation .patch_tool ,
842+ patches = annotation .patches ,
810843 path = package ["local_path" ],
811844 ** kwargs
812845 )
813846 elif source .startswith ("git+" ):
814847 remote , commit = parse_git_url (source )
815848
816- strip_prefix = package .get ("strip_prefix" )
817- workspace_cargo_toml = annotation .workspace_cargo_toml
818- if workspace_cargo_toml != "Cargo.toml" :
819- strip_prefix = workspace_cargo_toml .removesuffix ("Cargo.toml" ) + (strip_prefix or "" )
849+ package_path = _git_crate_package_path (annotation , package .get ("strip_prefix" ))
850+ package ["target_repo_name" ] = _external_repo_for_git_source (hub_name , remote , commit )
851+ package ["target_package_path" ] = package_path
820852
821853 if dry_run :
822854 continue
823855
824- crate_git_repository (
856+ git_crate_metadata_repository (
825857 name = repo_name ,
826- strip_prefix = strip_prefix ,
827- git_repo_label = "@" + _external_repo_for_git_source (remote , commit ),
828- remote = source ,
829- workspace_cargo_toml = annotation .workspace_cargo_toml ,
858+ package_name = crate_name ,
859+ package_version = version ,
860+ purl = _git_crate_purl (crate_name , version , remote , commit ),
830861 ** kwargs
831862 )
832863 else :
@@ -836,35 +867,41 @@ crate.annotation(
836867
837868 mctx .report_progress ("Initializing hub" )
838869
870+ package_by_fq = {
871+ _fq_crate (package ["name" ], package ["version" ]): package
872+ for package in packages
873+ }
874+
839875 hub_contents = []
840876 for name , versions in versions_by_name .items ():
841877 for version in versions :
842878 annotation = annotation_for (annotations , name , version )
843- spoke_repo = _spoke_repo (hub_name , name , version )
879+ package = package_by_fq [_fq_crate (name , version )]
880+ target_repo_name = package ["target_repo_name" ]
881+ target_package_path = package ["target_package_path" ]
844882
845883 hub_contents .append ("""
846884alias(
847885 name = "{name}-{version}",
848- actual = "@{spoke_repo}//:{name }",
849- )""" .format (name = name , version = version , spoke_repo = spoke_repo ))
886+ actual = "{actual }",
887+ )""" .format (name = name , version = version , actual = _target_label ( target_repo_name , target_package_path , name ) ))
850888
851889 for binary in annotation .gen_binaries :
852890 hub_contents .append ("""
853891alias(
854892 name = "{name}-{version}__{binary}",
855- actual = "@{spoke_repo}//:{binary}__bin ",
856- )""" .format (name = name , version = version , binary = binary , spoke_repo = spoke_repo ))
893+ actual = "{actual} ",
894+ )""" .format (name = name , version = version , binary = binary , actual = _target_label ( target_repo_name , target_package_path , binary + "__bin" ) ))
857895
858896 for alias_name , target in sorted (annotation .extra_aliased_targets .items ()):
859897 hub_contents .append ("""
860898alias(
861899 name = "{alias_name}-{version}",
862- actual = "@{spoke_repo}//:{target }",
900+ actual = "{actual }",
863901)""" .format (
864902 alias_name = alias_name ,
865903 version = version ,
866- target = target ,
867- spoke_repo = spoke_repo ,
904+ actual = _target_label (target_repo_name , target_package_path , target ),
868905 ))
869906
870907 workspace_versions = workspace_dep_versions_by_name .get (name )
@@ -1277,22 +1314,70 @@ def _crate_impl(mctx):
12771314
12781315 facts |= _generate_hub_and_spokes (mctx , cfg .name , annotations , suggested_annotation_snippet_paths , cargo_path , cfg .cargo_lock , cargo_toml_by_hub_name [cfg .name ], hub_packages , cfg .platform_triples , cargo_credentials , cfg .cargo_config , cfg .validate_lockfile , cfg .debug , cfg .use_legacy_rules_rust_platforms )
12791316
1280- # Lay down the git repos we will need; per-crate git_repository can clone from these .
1281- git_sources = set ()
1317+ # Lay down the git repos with generated per-crate BUILD overlays .
1318+ git_repos = {}
12821319 for mod in mctx .modules :
12831320 for cfg in mod .tags .from_cargo :
1321+ annotations = build_annotation_map (mod , cfg .name )
12841322 for package in packages_by_hub_name [cfg .name ]:
12851323 source = package .get ("source" , "" )
1286- if source .startswith ("git+" ):
1287- git_sources .add (source )
1288-
1289- for git_source in git_sources :
1290- remote , commit = parse_git_url (git_source )
1324+ if not source .startswith ("git+" ):
1325+ continue
12911326
1292- git_repository (
1293- name = _external_repo_for_git_source (remote , commit ),
1294- commit = commit ,
1295- remote = remote ,
1327+ remote , commit = parse_git_url (source )
1328+ annotation = annotation_for (annotations , package ["name" ], package ["version" ])
1329+ repo_name = _external_repo_for_git_source (cfg .name , remote , commit )
1330+ git_repo = git_repos .get (repo_name )
1331+ if not git_repo :
1332+ git_repo = {
1333+ "build_files" : {},
1334+ "gen_binaries" : {},
1335+ "commit" : commit ,
1336+ "hub_name" : cfg .name ,
1337+ "patch_args" : [],
1338+ "patch_tool" : "" ,
1339+ "patches" : {},
1340+ "remote" : remote ,
1341+ "workspace_cargo_toml" : annotation .workspace_cargo_toml ,
1342+ }
1343+ git_repos [repo_name ] = git_repo
1344+
1345+ strip_prefix = package .get ("strip_prefix" )
1346+ if strip_prefix == None :
1347+ strip_prefix = json .decode (facts [source + "_" + package ["name" ]])["strip_prefix" ]
1348+ package_path = _git_crate_package_path (annotation , strip_prefix )
1349+ build_file_path = paths .join (package_path , "BUILD.bazel" ) if package_path else "BUILD.bazel"
1350+ git_repo ["build_files" ][build_file_path ] = _additive_build_file_content (mctx , annotation )
1351+ if annotation .gen_binaries :
1352+ git_repo ["gen_binaries" ][build_file_path ] = annotation .gen_binaries
1353+
1354+ if annotation .patches :
1355+ patch_args = annotation .patch_args
1356+ patch_tool = annotation .patch_tool or ""
1357+ if git_repo ["patches" ] and (git_repo ["patch_args" ] != patch_args or git_repo ["patch_tool" ] != patch_tool ):
1358+ fail ("Git crates from %s use incompatible patch settings" % source )
1359+
1360+ git_repo ["patch_args" ] = patch_args
1361+ git_repo ["patch_tool" ] = patch_tool
1362+ for patch_file in annotation .patches :
1363+ git_repo ["patches" ][str (patch_file )] = patch_file
1364+
1365+ for repo_name , git_repo in git_repos .items ():
1366+ kwargs = {}
1367+ if git_repo ["gen_binaries" ]:
1368+ kwargs ["gen_binaries" ] = git_repo ["gen_binaries" ]
1369+
1370+ git_cargo_workspace_repository (
1371+ name = repo_name ,
1372+ build_files = git_repo ["build_files" ],
1373+ commit = git_repo ["commit" ],
1374+ hub_name = git_repo ["hub_name" ],
1375+ patch_args = git_repo ["patch_args" ],
1376+ patch_tool = git_repo ["patch_tool" ],
1377+ patches = git_repo ["patches" ].values (),
1378+ remote = git_repo ["remote" ],
1379+ workspace_cargo_toml = git_repo ["workspace_cargo_toml" ],
1380+ ** kwargs
12961381 )
12971382
12981383 kwargs = dict (
0 commit comments