diff --git a/Cargo.lock b/Cargo.lock index 30e5d8b22f7..60c86177028 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,10 +255,11 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f" +checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8" dependencies = [ + "camino", "cargo-platform 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.11.0", "semver-parser 0.10.2", diff --git a/fixtures/src/details.rs b/fixtures/src/details.rs index 7cee2e1ea0b..aef77534c74 100644 --- a/fixtures/src/details.rs +++ b/fixtures/src/details.rs @@ -18,10 +18,7 @@ use guppy::{ DependencyKind, PackageId, Platform, Version, }; use pretty_assertions::assert_eq; -use std::{ - collections::{BTreeMap, HashMap}, - path::PathBuf, -}; +use std::collections::{BTreeMap, HashMap}; /// This captures metadata fields that are relevant for tests. They are meant to be written out /// lazily as tests are filled out -- feel free to add more details as necessary! @@ -306,7 +303,13 @@ pub struct PackageDetails { license: Option<&'static str>, source: Option>, - build_targets: Option, BuildTargetKind<'static>, PathBuf)>>, + build_targets: Option< + Vec<( + BuildTargetId<'static>, + BuildTargetKind<'static>, + Utf8PathBuf, + )>, + >, // The vector items are (name, package id). // XXX add more details about dependency edges here? deps: Option>, diff --git a/guppy/CHANGELOG.md b/guppy/CHANGELOG.md index a1e3c358b8f..ace74fe8224 100644 --- a/guppy/CHANGELOG.md +++ b/guppy/CHANGELOG.md @@ -7,6 +7,11 @@ - `DependencyKind::VALUES` lists out all the values of `DependencyKind`. - `DependencyReq::no_default_features()` returns the enabled status for a dependency when `default-features = false`. +### Changed + +- `PackageMetadata::readme` now returns `&Utf8Path` rather than `&Path`. +- `BuildTarget::path` now returns `&Utf8Path` rather than `&Path`. + ## [0.8.0] - 2021-02-23 ### Changed diff --git a/guppy/Cargo.toml b/guppy/Cargo.toml index 2b388da68f3..11c507ed8f5 100644 --- a/guppy/Cargo.toml +++ b/guppy/Cargo.toml @@ -33,7 +33,7 @@ maintenance = { status = "actively-developed" } [dependencies] camino = "1.0.2" -cargo_metadata = "0.12.3" +cargo_metadata = "0.13.1" guppy-summaries = { version = "0.4.0", path = "../guppy-summaries", optional = true } fixedbitset = { version = "0.2.0", default-features = false } nested = "0.1.1" diff --git a/guppy/src/graph/build.rs b/guppy/src/graph/build.rs index cf8c29a901d..ff0fd6beacb 100644 --- a/guppy/src/graph/build.rs +++ b/guppy/src/graph/build.rs @@ -15,10 +15,7 @@ use cargo_metadata::{Dependency, DependencyKind, Metadata, NodeDep, Package, Res use once_cell::sync::OnceCell; use petgraph::prelude::*; use semver::Version; -use std::{ - collections::{BTreeMap, HashMap, HashSet}, - path::Path, -}; +use std::collections::{BTreeMap, HashMap, HashSet}; use target_spec::TargetSpec; impl PackageGraph { @@ -36,13 +33,7 @@ impl PackageGraph { .map(PackageId::from_metadata) .collect(); - let workspace_root = - Utf8PathBuf::from_path_buf(metadata.workspace_root).map_err(|path_buf| { - Error::PackageGraphConstructError(format!( - "workspace root is invalid UTF-8: {}", - path_buf.display() - )) - })?; + let workspace_root = metadata.workspace_root; let mut build_state = GraphBuildState::new( &metadata.packages, @@ -204,20 +195,14 @@ impl<'a> GraphBuildState<'a> { None => { return Err(Error::PackageGraphConstructError(format!( "package '{}': manifest path '{}' does not have parent", - package_id, - package.manifest_path.display(), + package_id, package.manifest_path, ))); } }; let rel_path = pathdiff::diff_paths(dirname, self.workspace_root) .expect("workspace root is absolute"); - let rel_path = Utf8PathBuf::from_path_buf(rel_path).map_err(|path_buf| { - Error::PackageGraphConstructError(format!( - "package '{}': location '{}' is invalid UTF-8", - package_id, - path_buf.display() - )) - })?; + let rel_path = Utf8PathBuf::from_path_buf(rel_path) + .expect("diff between two UTF-8 paths should produce a UTF-8 path"); PackageSourceImpl::Path(rel_path.into_boxed_path()) }; @@ -290,31 +275,6 @@ impl<'a> GraphBuildState<'a> { .chain(optional_deps) .collect(); - let license_file = match package.license_file { - Some(license_file) => Some( - Utf8PathBuf::from_path_buf(license_file) - .map_err(|path_buf| { - Error::PackageGraphConstructError(format!( - "for package '{}', license file is invalid UTF-8: {}", - package_id, - path_buf.display() - )) - })? - .into(), - ), - None => None, - }; - - let manifest_path = Utf8PathBuf::from_path_buf(package.manifest_path) - .map_err(|path_buf| { - Error::PackageGraphConstructError(format!( - "for package '{}', manifest path is invalid UTF-8: {}", - package_id, - path_buf.display() - )) - })? - .into(); - Ok(( package_id, PackageMetadataImpl { @@ -323,8 +283,8 @@ impl<'a> GraphBuildState<'a> { authors: package.authors, description: package.description.map(|s| s.into()), license: package.license.map(|s| s.into()), - license_file, - manifest_path, + license_file: package.license_file.map(|f| f.into()), + manifest_path: package.manifest_path.into(), categories: package.categories, keywords: package.keywords, readme: package.readme.map(|s| s.into()), @@ -357,7 +317,11 @@ impl<'a> GraphBuildState<'a> { /// Computes the workspace path for this package. Errors if this package is not in the /// workspace. - fn workspace_path(&self, id: &PackageId, manifest_path: &Path) -> Result, Error> { + fn workspace_path( + &self, + id: &PackageId, + manifest_path: &Utf8Path, + ) -> Result, Error> { // Strip off the workspace path from the manifest path. let workspace_path = manifest_path .strip_prefix(self.workspace_root) @@ -373,12 +337,6 @@ impl<'a> GraphBuildState<'a> { id, manifest_path )) })?; - let workspace_path = Utf8Path::from_path(workspace_path).ok_or_else(|| { - Error::PackageGraphConstructError(format!( - "workspace member '{}' has invalid UTF-8 manifest path {:?}", - id, manifest_path - )) - })?; Ok(workspace_path.to_path_buf().into_boxed_path()) } diff --git a/guppy/src/graph/build_targets.rs b/guppy/src/graph/build_targets.rs index 0b2fbc58316..05c33a198ff 100644 --- a/guppy/src/graph/build_targets.rs +++ b/guppy/src/graph/build_targets.rs @@ -2,7 +2,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use crate::sorted_set::SortedSet; -use std::{borrow::Borrow, cmp::Ordering, path::Path}; +use camino::Utf8Path; +use std::{borrow::Borrow, cmp::Ordering}; /// A build target in a package. /// @@ -59,7 +60,7 @@ impl<'g> BuildTarget<'g> { } /// Returns the absolute path of the location where the source for this build target is located. - pub fn path(&self) -> &'g Path { + pub fn path(&self) -> &'g Utf8Path { &self.inner.path } @@ -191,7 +192,7 @@ pub(super) struct BuildTargetImpl { // This is only set if the id is BuildTargetId::Library. pub(super) lib_name: Option>, pub(super) required_features: Vec, - pub(super) path: Box, + pub(super) path: Box, pub(super) edition: Box, pub(super) doc_tests: bool, } @@ -229,8 +230,7 @@ pub(super) enum BuildTargetKindImpl { Binary, } -// Allow Borrow usage for complex keys. Adapted from -// http://idubrov.name/rust/2018/06/01/tricking-the-hashmap.html. +// Borrow for complex keys. See https://github.com/sunshowers/borrow-complex-key-example. pub(super) trait BuildTargetKey { fn key(&self) -> BuildTargetId; } diff --git a/guppy/src/graph/graph_impl.rs b/guppy/src/graph/graph_impl.rs index 532531052c7..2988ec18f77 100644 --- a/guppy/src/graph/graph_impl.rs +++ b/guppy/src/graph/graph_impl.rs @@ -27,7 +27,6 @@ use std::{ collections::{BTreeMap, HashMap, HashSet}, fmt, iter, iter::FromIterator, - path::Path, }; use target_spec::TargetSpec; @@ -813,7 +812,7 @@ impl<'g> PackageMetadata<'g> { /// /// This is the same as the `readme` field of `Cargo.toml`. The path returned is relative to the /// directory the `Cargo.toml` is in (i.e. relative to the parent of `self.manifest_path()`). - pub fn readme(&self) -> Option<&'g Path> { + pub fn readme(&self) -> Option<&'g Utf8Path> { self.inner.readme.as_ref().map(|path| path.as_ref()) } @@ -1016,7 +1015,7 @@ pub(crate) struct PackageMetadataImpl { pub(super) manifest_path: Box, pub(super) categories: Vec, pub(super) keywords: Vec, - pub(super) readme: Option>, + pub(super) readme: Option>, pub(super) repository: Option>, pub(super) edition: Box, pub(super) metadata_table: JsonValue,