[packages/cargo-vendor-filterer] fix missing required packages in some cases; rel 2
atler
atler at pld-linux.org
Thu Feb 12 16:12:33 CET 2026
commit 428bcb0903a1de19aa0bf53793d20eaf4e5256f3
Author: Jan Palus <atler at pld-linux.org>
Date: Thu Feb 12 16:07:38 2026 +0100
fix missing required packages in some cases; rel 2
from: https://github.com/coreos/cargo-vendor-filterer/pull/128
upstream report: https://github.com/coreos/cargo-vendor-filterer/issues/120
cargo-vendor-filterer.spec | 4 +-
missing-packages.patch | 153 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 156 insertions(+), 1 deletion(-)
---
diff --git a/cargo-vendor-filterer.spec b/cargo-vendor-filterer.spec
index e957763..cf4a1b0 100644
--- a/cargo-vendor-filterer.spec
+++ b/cargo-vendor-filterer.spec
@@ -4,7 +4,7 @@ Summary: Tool to "cargo vendor" with filtering
Summary(pl.UTF-8): Narzędzie do "cargo vendor" z filtrowaniem
Name: cargo-vendor-filterer
Version: 0.5.18
-Release: 1
+Release: 2
License: Apache v2.0
Group: Applications
Source0: https://github.com/coreos/cargo-vendor-filterer/archive/v%{version}/%{name}-%{version}.tar.gz
@@ -12,6 +12,7 @@ Source0: https://github.com/coreos/cargo-vendor-filterer/archive/v%{version}/%{n
Source1: %{name}-crates-%{crates_ver}.tar.xz
# Source1-md5: 3a187bef2982d868e3afefe3ac895af1
Patch0: tier2-platforms-without-host-tools.patch
+Patch1: missing-packages.patch
URL: https://github.com/coreos/cargo-vendor-filterer
BuildRequires: cargo
BuildRequires: openssl-devel
@@ -39,6 +40,7 @@ wymagają np. tylko linuksowych.
%prep
%setup -q -a1
%patch -P0 -p1
+%patch -P1 -p1
%{__mv} %{name}-%{crates_ver}/* .
sed -i -e 's/@@VERSION@@/%{version}/' Cargo.lock
diff --git a/missing-packages.patch b/missing-packages.patch
new file mode 100644
index 0000000..12cb8b4
--- /dev/null
+++ b/missing-packages.patch
@@ -0,0 +1,153 @@
+From 5d252f75eab29c38218a34d786f249c6e16558dc Mon Sep 17 00:00:00 2001
+From: Jan Palus <jpalus at fastmail.com>
+Date: Thu, 12 Feb 2026 15:18:57 +0100
+Subject: [PATCH] Fix required packages being replaced with stub in some cases
+
+So far packages directory locations were determined based on already
+limited set of features (ie default feature set) which might not reflect
+what `cargo vendor` does with all features enabled. Paired with cargo's
+naming convention for multiple versions of same package -- highest
+version uses "name" while lower versions use "name-version" -- it caused
+required package to be replaced with stub if highest version turned to
+be optional and excluded with filtered feature set.
+
+Instead first create map for all packages and their directories with all
+features enabled and use it as reference.
+
+Fixes #120
+---
+ src/main.rs | 105 +++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 61 insertions(+), 44 deletions(-)
+
+diff --git a/src/main.rs b/src/main.rs
+index 66825fb..d16725f 100644
+--- a/src/main.rs
++++ b/src/main.rs
+@@ -665,7 +665,60 @@ fn new_metadata_cmd(path: Option<&Utf8Path>, offline: bool) -> MetadataCommand {
+ command
+ }
+
+-fn get_unfiltered_packages(
++/// Get filesystem locations of packages vendored by `cargo vendor` (all features enabled)
++fn get_vendored_package_dirs(
++ args: &Args,
++) -> Result<HashMap<cargo_metadata::PackageId, String>> {
++ let root = args.get_root_package()?;
++ let all_manifest_paths = args.get_all_manifest_paths();
++ let mut pkgs_by_name: HashMap<_, Vec<_>> = HashMap::new();
++ for manifest_path in all_manifest_paths {
++ let mut command = new_metadata_cmd(manifest_path, args.offline);
++ command.features(AllFeatures);
++ let meta = command.exec().context("Executing cargo metadata")?;
++ meta.packages
++ .into_iter()
++ // Skip ourself
++ .filter(|pkg| root.as_ref().is_none_or(|root| pkg.id != root.id))
++ // Also skip anything local
++ .filter(|pkg| {
++ let local = pkg.source.is_none();
++ if local {
++ eprintln!("Skipping {0}", pkg.name);
++ }
++
++ !local
++ })
++ .for_each(|pkg| {
++ if let Some(pkgs) = pkgs_by_name.get_mut(&pkg.name) {
++ pkgs.push(pkg);
++ } else {
++ pkgs_by_name.insert(pkg.name.clone(), vec![pkg]);
++ }
++ });
++ }
++ let mut pkg_dirs = HashMap::new();
++ for (_name, mut pkgs) in pkgs_by_name {
++ // If we use versioned-dirs, we insert all packages with a versioned filename
++ // If not, we split off the first package and insert it without a version-suffix
++ if !args.versioned_dirs {
++ // Reverse sort - greater version is lower index
++ pkgs.sort_by(|a, b| b.version.cmp(&a.version));
++ let first = pkgs.remove(0);
++ pkg_dirs.insert(first.id, first.name);
++ }
++
++ for pkg in pkgs {
++ let dir = package_versioned_filename(&pkg);
++ pkg_dirs.insert(pkg.id, dir);
++ }
++ }
++
++ Ok(pkg_dirs)
++}
++
++/// Retrieve packages needed for selected feature set
++fn get_packages_for_features(
+ args: &Args,
+ config: &VendorFilter,
+ ) -> Result<HashMap<cargo_metadata::PackageId, cargo_metadata::Package>> {
+@@ -893,31 +946,12 @@ pub fn run(args: Args) -> Result<()> {
+ anyhow::bail!("Refusing to operate on extant directory: {}", output_dir);
+ }
+
+- eprintln!("Gathering metadata");
+ // We need to gather the full, unfiltered metadata to canonically know what
+ // `cargo vendor` will do.
+- let all_packages = get_unfiltered_packages(&args, &config)?;
+- let root = args.get_root_package()?;
+-
+- // Create a mapping of name -> [package versions]
+- let mut pkgs_by_name = BTreeMap::<_, Vec<_>>::new();
+- for pkg in all_packages.values() {
+- let name = pkg.name.as_str();
+- // Skip ourself
+- if let Some(root) = root.as_ref() {
+- if pkg.id == root.id {
+- continue;
+- }
+- }
+- // Also skip anything local
+- if pkg.source.as_ref().is_none() {
+- eprintln!("Skipping {name}");
+- continue;
+- }
+-
+- let v = pkgs_by_name.entry(name).or_default();
+- v.push(pkg);
+- }
++ eprintln!("Gathering metadata for vendored packages");
++ let vendored_dirs = get_vendored_package_dirs(&args)?;
++ eprintln!("Gathering metadata for selected feature set");
++ let all_packages = get_packages_for_features(&args, &config)?;
+
+ // And now do the filtered set
+ let mut packages = HashMap::new();
+@@ -982,26 +1016,9 @@ pub fn run(args: Args) -> Result<()> {
+ // the all_packages map with the filtered one, returning an index by the
+ // directory name that will have been generated by `cargo vendor`.
+ let mut package_filenames = BTreeMap::new();
+- for (_name, mut pkgs) in pkgs_by_name {
+- // Reverse sort - greater version is lower index
+- pkgs.sort_by(|a, b| b.version.cmp(&a.version));
+- // If we use versioned-dirs, we insert all packages with a versioned filename
+- // If not, we split off the first package and insert it without a version-suffix
+- let versioned_pkgs = if !args.versioned_dirs {
+- // SAFETY: The package set must be non-empty
+- let (first, rest) = pkgs.split_first().unwrap();
+- if packages.contains_key(&first.id) {
+- package_filenames.insert(Cow::Borrowed(first.name.as_str()), *first);
+- }
+- rest
+- } else {
+- &pkgs
+- };
+-
+- for pkg in versioned_pkgs {
+- if packages.contains_key(&pkg.id) {
+- package_filenames.insert(Cow::Owned(package_versioned_filename(pkg)), pkg);
+- }
++ for (id, pkg) in packages {
++ if let Some(dir) = vendored_dirs.get(&id) {
++ package_filenames.insert(Cow::Borrowed(dir.as_str()), pkg);
+ }
+ }
+
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/cargo-vendor-filterer.git/commitdiff/428bcb0903a1de19aa0bf53793d20eaf4e5256f3
More information about the pld-cvs-commit
mailing list