From dc12f7cd72e045bed19109b19d374e5361c85fc5 Mon Sep 17 00:00:00 2001 From: Preston Tunnell Wilson Date: Tue, 22 Mar 2022 18:46:56 -0400 Subject: [PATCH] Ptw/issue 74 Do not skelefy vendored directory (#120) * Reorder skeleton so that we can pass config file contents into when we discover the manifests * Ignore vendored sources Derive the directory for the vendored sources using the `source.crates-io` field from `.cargo/config.toml` * Add failing test * Refactor `vendored_directory` and make test pass! * Remove debug println * Incorporate PR feedback Uses `format` instead of string addition Co-authored-by: Preston TW --- src/skeleton/mod.rs | 4 +-- src/skeleton/read.rs | 21 ++++++++++- tests/skeletons.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/src/skeleton/mod.rs b/src/skeleton/mod.rs index 625b3c5..d98f275 100644 --- a/src/skeleton/mod.rs +++ b/src/skeleton/mod.rs @@ -31,9 +31,9 @@ impl Skeleton { /// Find all Cargo.toml files in `base_path` by traversing sub-directories recursively. pub fn derive>(base_path: P) -> Result { // Read relevant files from the filesystem - let mut manifests = read::manifests(&base_path)?; - let mut lock_file = read::lockfile(&base_path)?; let config_file = read::config(&base_path)?; + let mut manifests = read::manifests(&base_path, config_file.as_deref())?; + let mut lock_file = read::lockfile(&base_path)?; version_masking::mask_local_crate_versions(&mut manifests, &mut lock_file); diff --git a/src/skeleton/read.rs b/src/skeleton/read.rs index a27a49d..dea268a 100644 --- a/src/skeleton/read.rs +++ b/src/skeleton/read.rs @@ -21,10 +21,29 @@ pub(super) fn config>(base_path: &P) -> Result, an } } +fn vendored_directory(config_contents: Option<&str>) -> Option { + let contents = config_contents.and_then(|contents| contents.parse::().ok())?; + let source = contents.get("source")?; + let crates_io = source.get("crates-io")?; + let vendored_field_suffix = crates_io + .get("replace-with") + .and_then(|value| value.as_str())?; + let vendored_sources = source.get(vendored_field_suffix)?; + Some(vendored_sources.get("directory")?.as_str()?.to_owned()) +} + pub(super) fn manifests>( base_path: &P, + config_contents: Option<&str>, ) -> Result, anyhow::Error> { - let walker = GlobWalkerBuilder::new(&base_path, "/**/Cargo.toml") + let vendored_path = vendored_directory(config_contents); + let builder = if let Some(path) = vendored_path { + let exclude_vendored_sources = format!("!{}", path); + GlobWalkerBuilder::from_patterns(&base_path, &["/**/Cargo.toml", &exclude_vendored_sources]) + } else { + GlobWalkerBuilder::new(&base_path, "/**/Cargo.toml") + }; + let walker = builder .build() .context("Failed to scan the files in the current directory.")?; diff --git a/tests/skeletons.rs b/tests/skeletons.rs index 6898ce7..2f59505 100644 --- a/tests/skeletons.rs +++ b/tests/skeletons.rs @@ -807,6 +807,91 @@ version = "0.8.0" ); } +#[test] +pub fn ignore_vendored_directory() { + // Arrange + let content = r#" +[package] +name = "test-dummy" +version = "1.2.3" +edition = "2018" + +[dependencies] +rocket = "0.5.0-rc.1" + "#; + let cargo_config = r#" +[source.crates-io] +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "vendor" + "#; + + let rocket_cargo_toml = r#"[package] +edition = "2018" +name = "rocket" +version = "0.5.0-rc.1" +authors = ["Sergio Benitez "] +build = "build.rs" +description = "Web framework with a focus on usability, security, extensibility, and speed.\n" +homepage = "https://rocket.rs" +documentation = "https://api.rocket.rs/v0.5-rc/rocket/" +readme = "../../README.md" +keywords = ["rocket", "web", "framework", "server"] +categories = ["web-programming::http-server"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/SergioBenitez/Rocket" +[package.metadata.docs.rs] +all-features = true +[dependencies.rocket_dep] +version = "0.3.2""#; + + let rocket_dep_cargo_toml = r#"[package] +edition = "2018" +name = "rocket_dep" +version = "0.3.2" +authors = ["Test author"] +description = "sample package representing all of rocket's dependencies""#; + + let recipe_directory = TempDir::new().unwrap(); + let manifest = recipe_directory.child("Cargo.toml"); + manifest.write_str(content).unwrap(); + recipe_directory.child(".cargo").create_dir_all().unwrap(); + recipe_directory + .child(".cargo") + .child("config.toml") + .write_str(cargo_config) + .unwrap(); + recipe_directory.child("src").create_dir_all().unwrap(); + recipe_directory + .child("src") + .child("main.rs") + .touch() + .unwrap(); + + let vendored = recipe_directory.child("vendor"); + let rocket = vendored.child("rocket"); + let sample_rocket_dep = vendored.child("rocket_dep"); + rocket.create_dir_all().unwrap(); + sample_rocket_dep.create_dir_all().unwrap(); + + rocket + .child("Cargo.toml") + .write_str(rocket_cargo_toml) + .unwrap(); + + sample_rocket_dep + .child("Cargo.toml") + .write_str(rocket_dep_cargo_toml) + .unwrap(); + + // Act + let skeleton = Skeleton::derive(recipe_directory.path()).unwrap(); + + // Assert + assert_eq!(1, skeleton.manifests.len()); +} + fn check(actual: &str, expect: Expect) { let actual = actual.to_string(); expect.assert_eq(&actual);