From 1b821841d09aee4ed829efdb408fd195ae1949e3 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 26 Dec 2024 12:27:37 -0500 Subject: [PATCH] refactor(package): make a workspace-shared vcs info builder This is aimed to cache duplicate works like file system or VCS info lookups. --- src/cargo/ops/cargo_package/mod.rs | 6 ++++-- src/cargo/ops/cargo_package/vcs.rs | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/cargo/ops/cargo_package/mod.rs b/src/cargo/ops/cargo_package/mod.rs index 07ba919c98a..3821a6882f8 100644 --- a/src/cargo/ops/cargo_package/mod.rs +++ b/src/cargo/ops/cargo_package/mod.rs @@ -225,6 +225,7 @@ fn do_package<'a>( // Packages need to be created in dependency order, because dependencies must // be added to our local overlay before we can create lockfiles that depend on them. + let mut vcs_info_builder = vcs::VcsInfoBuilder::new(ws, opts); let sorted_pkgs = deps.sort(); let mut outputs: Vec<(Package, PackageOpts<'_>, FileLock)> = Vec::new(); for (pkg, cli_features) in sorted_pkgs { @@ -233,7 +234,7 @@ fn do_package<'a>( to_package: ops::Packages::Default, ..opts.clone() }; - let ar_files = prepare_archive(ws, &pkg, &opts)?; + let ar_files = prepare_archive(ws, &pkg, &opts, &mut vcs_info_builder)?; if opts.list { for ar_file in &ar_files { @@ -368,6 +369,7 @@ fn prepare_archive( ws: &Workspace<'_>, pkg: &Package, opts: &PackageOpts<'_>, + vcs_info_builder: &mut vcs::VcsInfoBuilder<'_, '_>, ) -> CargoResult> { let gctx = ws.gctx(); let mut src = PathSource::new(pkg.root(), pkg.package_id().source_id(), gctx); @@ -386,7 +388,7 @@ fn prepare_archive( let src_files = src.list_files(pkg)?; // Check (git) repository state, getting the current commit hash. - let vcs_info = vcs::check_repo_state(pkg, &src_files, gctx, &opts)?; + let vcs_info = vcs_info_builder.build(pkg, &src_files)?; build_ar_list(ws, pkg, src_files, vcs_info) } diff --git a/src/cargo/ops/cargo_package/vcs.rs b/src/cargo/ops/cargo_package/vcs.rs index 44adfd85a1a..068e7c892cf 100644 --- a/src/cargo/ops/cargo_package/vcs.rs +++ b/src/cargo/ops/cargo_package/vcs.rs @@ -9,6 +9,7 @@ use serde::Serialize; use tracing::debug; use crate::core::Package; +use crate::core::Workspace; use crate::CargoResult; use crate::GlobalContext; @@ -31,6 +32,28 @@ pub struct GitVcsInfo { dirty: bool, } +/// A shared builder for generating [`VcsInfo`] for packages inside the same workspace. +/// +/// This is aimed to cache duplicate works like file system or VCS info lookups. +pub struct VcsInfoBuilder<'a, 'gctx> { + ws: &'a Workspace<'gctx>, + opts: &'a PackageOpts<'gctx>, +} + +impl<'a, 'gctx> VcsInfoBuilder<'a, 'gctx> { + pub fn new( + ws: &'a Workspace<'gctx>, + opts: &'a PackageOpts<'gctx>, + ) -> VcsInfoBuilder<'a, 'gctx> { + VcsInfoBuilder { ws, opts } + } + + /// Builds an [`VcsInfo`] for the given `pkg` and its associated `src_files`. + pub fn build(&mut self, pkg: &Package, src_files: &[PathBuf]) -> CargoResult> { + check_repo_state(pkg, src_files, self.ws.gctx(), self.opts) + } +} + /// Checks if the package source is in a *git* DVCS repository. /// /// If *git*, and the source is *dirty* (e.g., has uncommitted changes),