From 6cf047b9ed27e81dab8bf40430fac572e142ae0f Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Wed, 9 Aug 2023 16:38:31 +0100 Subject: [PATCH] Factor out functions to find package directory. Bug: 293289578 Test: atest cargo_embargo.test Change-Id: I53b1f37ed1a9cd171c373c7fb4effda94f887437 --- tools/cargo_embargo/src/cargo_out.rs | 54 +++++++++++++++++----------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/tools/cargo_embargo/src/cargo_out.rs b/tools/cargo_embargo/src/cargo_out.rs index a51a383fb..29b750c6b 100644 --- a/tools/cargo_embargo/src/cargo_out.rs +++ b/tools/cargo_embargo/src/cargo_out.rs @@ -356,27 +356,7 @@ impl Crate { } } _ if !arg.starts_with('-') => { - let src_path = Path::new(arg); - // Canonicalize the path because: - // - // 1. We don't consistently get relative or absolute paths elsewhere. If we - // canonicalize everything, it becomes easy to compare paths. - // - // 2. We don't want to consider symlinks to code outside the cwd as part of the - // project (e.g. AOSP's import of crosvm has symlinks from crosvm's own 3p - // directory to the android 3p directories). - let src_path = src_path - .canonicalize() - .unwrap_or_else(|e| panic!("failed to canonicalize {src_path:?}: {}", e)); - out.package_dir = src_path.parent().unwrap().to_path_buf(); - while !out.package_dir.join("Cargo.toml").try_exists()? { - if let Some(parent) = out.package_dir.parent() { - out.package_dir = parent.to_path_buf(); - } else { - bail!("No Cargo.toml found in parents of {:?}", src_path); - } - } - out.main_src = src_path.strip_prefix(&out.package_dir).unwrap().to_path_buf(); + (out.package_dir, out.main_src) = split_src_path(Path::new(arg))?; } // ignored flags @@ -443,3 +423,35 @@ impl Crate { Ok(out) } } + +/// Given a path to the main source file of some Rust crate, returns the canonical path to the +/// package directory, and the relative path to the source file within that directory. +fn split_src_path(src_path: &Path) -> Result<(PathBuf, PathBuf)> { + // Canonicalize the path because: + // + // 1. We don't consistently get relative or absolute paths elsewhere. If we + // canonicalize everything, it becomes easy to compare paths. + // + // 2. We don't want to consider symlinks to code outside the cwd as part of the + // project (e.g. AOSP's import of crosvm has symlinks from crosvm's own 3p + // directory to the android 3p directories). + let src_path = src_path + .canonicalize() + .unwrap_or_else(|e| panic!("failed to canonicalize {src_path:?}: {}", e)); + let package_dir = find_cargo_toml(&src_path)?; + let main_src = src_path.strip_prefix(&package_dir).unwrap().to_path_buf(); + + Ok((package_dir, main_src)) +} + +/// Given a path to a Rust source file, finds the closest ancestor directory containing a +/// `Cargo.toml` file. +fn find_cargo_toml(src_path: &Path) -> Result { + let mut package_dir = src_path.parent().unwrap(); + while !package_dir.join("Cargo.toml").try_exists()? { + package_dir = package_dir + .parent() + .ok_or_else(|| anyhow!("No Cargo.toml found in parents of {:?}", src_path))?; + } + Ok(package_dir.to_path_buf()) +}