@@ -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 }
@@ -776,6 +801,8 @@ crate.annotation(
776801 )
777802
778803 repo_name = _spoke_repo (hub_name , crate_name , version )
804+ package ["target_repo_name" ] = repo_name
805+ package ["target_package_path" ] = ""
779806
780807 if source .startswith ("sparse+" ):
781808 checksum = package ["checksum" ]
@@ -813,20 +840,18 @@ crate.annotation(
813840 elif source .startswith ("git+" ):
814841 remote , commit = parse_git_url (source )
815842
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 "" )
843+ package_path = _git_crate_package_path (annotation , package .get ("strip_prefix" ))
844+ package ["target_repo_name" ] = _external_repo_for_git_source (hub_name , remote , commit )
845+ package ["target_package_path" ] = package_path
820846
821847 if dry_run :
822848 continue
823849
824- crate_git_repository (
850+ git_crate_metadata_repository (
825851 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 ,
852+ package_name = crate_name ,
853+ package_version = version ,
854+ purl = _git_crate_purl (crate_name , version , remote , commit ),
830855 ** kwargs
831856 )
832857 else :
@@ -836,35 +861,41 @@ crate.annotation(
836861
837862 mctx .report_progress ("Initializing hub" )
838863
864+ package_by_fq = {
865+ _fq_crate (package ["name" ], package ["version" ]): package
866+ for package in packages
867+ }
868+
839869 hub_contents = []
840870 for name , versions in versions_by_name .items ():
841871 for version in versions :
842872 annotation = annotation_for (annotations , name , version )
843- spoke_repo = _spoke_repo (hub_name , name , version )
873+ package = package_by_fq [_fq_crate (name , version )]
874+ target_repo_name = package ["target_repo_name" ]
875+ target_package_path = package ["target_package_path" ]
844876
845877 hub_contents .append ("""
846878alias(
847879 name = "{name}-{version}",
848- actual = "@{spoke_repo}//:{name }",
849- )""" .format (name = name , version = version , spoke_repo = spoke_repo ))
880+ actual = "{actual }",
881+ )""" .format (name = name , version = version , actual = _target_label ( target_repo_name , target_package_path , name ) ))
850882
851883 for binary in annotation .gen_binaries :
852884 hub_contents .append ("""
853885alias(
854886 name = "{name}-{version}__{binary}",
855- actual = "@{spoke_repo}//:{binary}__bin ",
856- )""" .format (name = name , version = version , binary = binary , spoke_repo = spoke_repo ))
887+ actual = "{actual} ",
888+ )""" .format (name = name , version = version , binary = binary , actual = _target_label ( target_repo_name , target_package_path , binary + "__bin" ) ))
857889
858890 for alias_name , target in sorted (annotation .extra_aliased_targets .items ()):
859891 hub_contents .append ("""
860892alias(
861893 name = "{alias_name}-{version}",
862- actual = "@{spoke_repo}//:{target }",
894+ actual = "{actual }",
863895)""" .format (
864896 alias_name = alias_name ,
865897 version = version ,
866- target = target ,
867- spoke_repo = spoke_repo ,
898+ actual = _target_label (target_repo_name , target_package_path , target ),
868899 ))
869900
870901 workspace_versions = workspace_dep_versions_by_name .get (name )
@@ -1277,22 +1308,62 @@ def _crate_impl(mctx):
12771308
12781309 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 )
12791310
1280- # Lay down the git repos we will need; per-crate git_repository can clone from these .
1281- git_sources = set ()
1311+ # Lay down the git repos with generated per-crate BUILD overlays .
1312+ git_repos = {}
12821313 for mod in mctx .modules :
12831314 for cfg in mod .tags .from_cargo :
1315+ annotations = build_annotation_map (mod , cfg .name )
12841316 for package in packages_by_hub_name [cfg .name ]:
12851317 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 )
1318+ if not source .startswith ("git+" ):
1319+ continue
12911320
1292- git_repository (
1293- name = _external_repo_for_git_source (remote , commit ),
1294- commit = commit ,
1295- remote = remote ,
1321+ remote , commit = parse_git_url (source )
1322+ annotation = annotation_for (annotations , package ["name" ], package ["version" ])
1323+ repo_name = _external_repo_for_git_source (cfg .name , remote , commit )
1324+ git_repo = git_repos .get (repo_name )
1325+ if not git_repo :
1326+ git_repo = {
1327+ "build_files" : {},
1328+ "commit" : commit ,
1329+ "hub_name" : cfg .name ,
1330+ "patch_args" : [],
1331+ "patch_tool" : "" ,
1332+ "patches" : {},
1333+ "remote" : remote ,
1334+ "workspace_cargo_toml" : annotation .workspace_cargo_toml ,
1335+ }
1336+ git_repos [repo_name ] = git_repo
1337+
1338+ strip_prefix = package .get ("strip_prefix" )
1339+ if strip_prefix == None :
1340+ strip_prefix = json .decode (facts [source + "_" + package ["name" ]])["strip_prefix" ]
1341+ package_path = _git_crate_package_path (annotation , strip_prefix )
1342+ build_file_path = paths .join (package_path , "BUILD.bazel" ) if package_path else "BUILD.bazel"
1343+ git_repo ["build_files" ][build_file_path ] = _additive_build_file_content (mctx , annotation )
1344+
1345+ if annotation .patches :
1346+ patch_args = annotation .patch_args
1347+ patch_tool = annotation .patch_tool or ""
1348+ if git_repo ["patches" ] and (git_repo ["patch_args" ] != patch_args or git_repo ["patch_tool" ] != patch_tool ):
1349+ fail ("Git crates from %s use incompatible patch settings" % source )
1350+
1351+ git_repo ["patch_args" ] = patch_args
1352+ git_repo ["patch_tool" ] = patch_tool
1353+ for patch_file in annotation .patches :
1354+ git_repo ["patches" ][str (patch_file )] = patch_file
1355+
1356+ for repo_name , git_repo in git_repos .items ():
1357+ git_cargo_workspace_repository (
1358+ name = repo_name ,
1359+ build_files = git_repo ["build_files" ],
1360+ commit = git_repo ["commit" ],
1361+ hub_name = git_repo ["hub_name" ],
1362+ patch_args = git_repo ["patch_args" ],
1363+ patch_tool = git_repo ["patch_tool" ],
1364+ patches = git_repo ["patches" ].values (),
1365+ remote = git_repo ["remote" ],
1366+ workspace_cargo_toml = git_repo ["workspace_cargo_toml" ],
12961367 )
12971368
12981369 kwargs = dict (
0 commit comments