From 24b6f47cf172885f05b0b08176da4806417c7d6a Mon Sep 17 00:00:00 2001 From: Joshua Zivkovic Date: Mon, 9 Feb 2026 09:43:29 +0000 Subject: [PATCH] Update cargo source to use source provenance --- src/buildstream_plugins/sources/cargo.py | 38 ++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/buildstream_plugins/sources/cargo.py b/src/buildstream_plugins/sources/cargo.py index c0e78d3..abdb7cd 100644 --- a/src/buildstream_plugins/sources/cargo.py +++ b/src/buildstream_plugins/sources/cargo.py @@ -74,6 +74,10 @@ *version_type*, for which it reports the checksum of the archive as the *version*. The versions extracted from the Cargo.lock at tracking time are used to report the *guess_version*. + +Additional source info can be specified using the `provenance` field for each referenced crate as per +`built-in source provenance documentation +`_. """ import json @@ -125,13 +129,14 @@ # sha (str|None): The sha256 checksum of the downloaded crate # class Crate(SourceFetcher): - def __init__(self, cargo, name, version, sha=None): + def __init__(self, cargo, name, version, sha=None, provenance=None): super().__init__() self.cargo = cargo self.name = name self.version = str(version) self.sha = sha + self.provenance = provenance self.mark_download_url(cargo.url) ######################################################## @@ -159,7 +164,12 @@ def fetch(self, alias_override=None, **kwargs): def get_source_info(self): url, _ = self._get_url() return self.cargo.create_source_info( - url, SourceInfoMedium.REMOTE_FILE, SourceVersionType.SHA256, self.sha, version_guess=self.version + url, + SourceInfoMedium.REMOTE_FILE, + SourceVersionType.SHA256, + self.sha, + version_guess=self.version, + provenance_node=self.provenance, ) ######################################################## @@ -368,16 +378,29 @@ class CargoSource(Source): # We need the Cargo.lock file to construct our ref at track time BST_REQUIRES_PREVIOUS_SOURCES_TRACK = True + BST_CUSTOM_SOURCE_PROVENANCE = True + ######################################################## # Plugin/Source API method implementations # ######################################################## def configure(self, node): - # The url before any aliasing # self.original_url = node.get_str("url", "https://static.crates.io/crates") self.cargo_lock = node.get_str("cargo-lock", "Cargo.lock") self.vendor_dir = node.get_str("vendor-dir", "crates") + self.provenance = {} + + # Because source provenance info lives in the ref it would be + # removed upon source track, create a backup here so it is + # available to be added back in when setting the ref + ref = node.get_sequence("ref", None) + if ref is not None: + for crate in ref: + if "provenance" in crate: + crate_name = crate.get_str("name") + provenance = crate.get_mapping("provenance") + self.provenance[crate_name] = provenance.strip_node_info() # If the specified URL is just an alias, require the alias to resolve # to a URL with a trailing slash. Otherwise, append a trailing slash if @@ -413,6 +436,14 @@ def get_ref(self): return self.ref def set_ref(self, ref, node): + def add_provenance(crate): + if crate["name"] in self.provenance: + crate["provenance"] = self.provenance[crate["name"]] + return crate + + # add provenance back in + ref = list(map(add_provenance, ref)) + node["ref"] = ref self._recompute_crates(node.get_sequence("ref")) @@ -513,6 +544,7 @@ def _parse_crates(self, refs): crate.get_str("name"), crate.get_str("version"), sha=crate.get_str("sha", None), + provenance=crate.get_mapping("provenance", None), ) for crate in refs ]