Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unstringlytypify #59

Merged
merged 6 commits into from
Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 43 additions & 41 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,41 +121,71 @@ use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::from_utf8;
use std::fmt;

use semver::Version;

pub use errors::{Error, ErrorKind, Result};
pub use dependency::{Dependency, DependencyKind};

mod errors;
mod dependency;

/// An "opaque" identifier for a package.
/// It is possible to inspect the `repr` field, if the need arises, but its
/// precise format is an implementation detail and is subject to change.
///
/// `Metadata` can be indexed by `PackageId`.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(transparent)]
pub struct PackageId {
/// The underlying string representation of id.
pub repr: String
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This move lost the convenience methods that existed on WorkspaceMember

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nevermind. I should have read the issue first

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, they are now basically metadata[package_id].url etc


impl std::fmt::Display for PackageId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.repr, f) }
}

#[derive(Clone, Serialize, Deserialize, Debug)]
/// Starting point for metadata returned by `cargo metadata`
pub struct Metadata {
/// A list of all crates referenced by this crate (and the crate itself)
pub packages: Vec<Package>,
/// A list of all workspace members
pub workspace_members: Vec<WorkspaceMember>,
pub workspace_members: Vec<PackageId>,
/// Dependencies graph
pub resolve: Option<Resolve>,
/// Workspace root
#[serde(default)]
pub workspace_root: String,
pub workspace_root: PathBuf,
/// Build directory
pub target_directory: String,
pub target_directory: PathBuf,
version: usize,
#[doc(hidden)]
#[serde(skip)]
__do_not_match_exhaustively: (),
}

impl std::ops::Index<&PackageId> for Metadata {
type Output = Package;

fn index(&self, idx: &PackageId) -> &Package {
self.packages.iter().find(|p| p.id == *idx)
.unwrap_or_else(|| {
panic!("no package with this id: {:?}", idx)
})
}
}

#[derive(Clone, Serialize, Deserialize, Debug)]
/// A dependency graph
pub struct Resolve {
/// Nodes in a dependencies graph
pub nodes: Vec<Node>,

/// The crate for which the metadata was read
pub root: Option<String>,
/// The crate for which the metadata was read.
pub root: Option<PackageId>,
#[doc(hidden)]
#[serde(skip)]
__do_not_match_exhaustively: (),
Expand All @@ -165,7 +195,7 @@ pub struct Resolve {
/// A node in a dependencies graph
pub struct Node {
/// An opaque identifier for a package
pub id: String,
pub id: PackageId,
/// Dependencies in a structured format.
///
/// `deps` handles renamed dependencies whereas `dependencies` does not.
Expand All @@ -174,7 +204,7 @@ pub struct Node {

/// List of opaque identifiers for this node's dependencies.
/// It doesn't support renamed dependencies. See `deps`.
pub dependencies: Vec<String>,
pub dependencies: Vec<PackageId>,

/// Features enabled on the crate
#[serde(default)]
Expand All @@ -190,7 +220,7 @@ pub struct NodeDep {
/// Crate name. If the crate was renamed, it's the new name.
pub name: String,
/// Package ID (opaque unique identifier)
pub pkg: String,
pub pkg: PackageId,
#[doc(hidden)]
#[serde(skip)]
__do_not_match_exhaustively: (),
Expand All @@ -202,12 +232,12 @@ pub struct Package {
/// Name as given in the `Cargo.toml`
pub name: String,
/// Version given in the `Cargo.toml`
pub version: String,
pub version: Version,
/// Authors given in the `Cargo.toml`
#[serde(default)]
pub authors: Vec<String>,
/// An opaque identifier for a package
pub id: String,
pub id: PackageId,
source: Option<String>,
/// Description as given in the `Cargo.toml`
pub description: Option<String>,
Expand All @@ -223,7 +253,7 @@ pub struct Package {
/// Features provided by the crate, mapped to the features required by that feature.
pub features: HashMap<String, Vec<String>>,
/// Path containing the `Cargo.toml`
pub manifest_path: String,
pub manifest_path: PathBuf,
/// Categories as given in the `Cargo.toml`
#[serde(default)]
pub categories: Vec<String>,
Expand Down Expand Up @@ -290,7 +320,7 @@ pub struct Target {
/// It doesn't apply to `lib` targets.
pub required_features: Vec<String>,
/// Path to the main source file of the target
pub src_path: String,
pub src_path: PathBuf,
/// Rust edition for this target
#[serde(default = "edition_default")]
pub edition: String,
Expand All @@ -299,34 +329,6 @@ pub struct Target {
__do_not_match_exhaustively: (),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
/// A workspace member. This is basically identical to `cargo::core::package_id::PackageId`, except
/// that this does not use `Arc` internally.
#[serde(transparent)]
pub struct WorkspaceMember {
/// The raw package id as given by cargo
pub raw: String,
}

impl WorkspaceMember {
fn part(&self, n: usize) -> &str {
self.raw.splitn(3, ' ').nth(n).unwrap()
}
/// The name of the crate
pub fn name(&self) -> &str {
self.part(0)
}
/// The version of the crate
pub fn version(&self) -> semver::Version {
semver::Version::parse(self.part(1)).expect("bad version in cargo metadata")
}
/// The path to the crate in url format
pub fn url(&self) -> &str {
let url = self.part(2);
&url[1..url.len() - 1]
}
}

fn edition_default() -> String {
"2015".to_string()
}
Expand Down
50 changes: 14 additions & 36 deletions tests/selftest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ extern crate serde_derive;

use std::env::current_dir;
use std::path::{Path, PathBuf};
use std::env;

use semver::Version;

Expand Down Expand Up @@ -39,21 +38,17 @@ fn metadata() {
assert_eq!(metadata.packages[0].targets[1].kind[0], "test");
assert_eq!(metadata.packages[0].targets[1].crate_types[0], "bin");

// Hack until the package metadata field reaches the stable channel (in version 1.27).
if env::var("TRAVIS_RUST_VERSION") != Ok("stable".into()) {
let package_metadata = &metadata.packages[0].metadata.as_object()
.expect("package.metadata must be a table. \
NOTE: This test currently only works on the beta and nightly channel.");
assert_eq!(package_metadata.len(), 1);

let value = package_metadata.get("cargo_metadata_test").unwrap();
let test_package_metadata: TestPackageMetadata = serde_json::from_value(value.clone())
.unwrap();
assert_eq!(test_package_metadata, TestPackageMetadata {
some_field: true,
other_field: "foo".into(),
});
}
let package_metadata = &metadata.packages[0].metadata.as_object()
.expect("package.metadata must be a table.");
assert_eq!(package_metadata.len(), 1);

let value = package_metadata.get("cargo_metadata_test").unwrap();
let test_package_metadata: TestPackageMetadata = serde_json::from_value(value.clone())
.unwrap();
assert_eq!(test_package_metadata, TestPackageMetadata {
some_field: true,
other_field: "foo".into(),
});
}

#[test]
Expand Down Expand Up @@ -96,11 +91,10 @@ fn error2() {
#[test]
fn metadata_deps() {
let metadata = cargo_metadata::metadata_deps(Some(Path::new("Cargo.toml")), true).unwrap();
let this = metadata
.packages
.iter()
.find(|package| package.name == "cargo_metadata")
let this_id = metadata.workspace_members
.first()
.expect("Did not find ourselves");
let this = &metadata[this_id];

assert_eq!(this.name, "cargo_metadata");
assert_eq!(this.targets.len(), 2);
Expand All @@ -125,19 +119,3 @@ fn metadata_deps() {
assert!(serde.req.matches(&Version::parse("1.99.99").unwrap()));
assert!(!serde.req.matches(&Version::parse("2.0.0").unwrap()));
}

#[test]
fn workspace_member_serialization_deserialization() {
let original =
"\"security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)\"";
let member: cargo_metadata::WorkspaceMember = serde_json::from_str(original).unwrap();
assert_eq!(member.name(), "security-framework");
assert_eq!(member.version(), Version::new(0, 1, 16));
assert_eq!(
member.url(),
"registry+https://github.com/rust-lang/crates.io-index"
);

let serialized = serde_json::to_string(&member).unwrap();
assert_eq!(serialized, original);
}