From d64528f9e9218bb1152b93a9b5e88e735044762e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 23 Nov 2014 16:09:46 -0800 Subject: [PATCH] Allow features with '/' in the name These are just reexported features. Closes rust-lang/cargo#963 --- src/krate.rs | 14 ++++++++++++++ src/tests/krate.rs | 9 +++++++++ src/upload.rs | 27 ++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/krate.rs b/src/krate.rs index 4aeb732ad1..f15ab7e529 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -211,6 +211,20 @@ impl Crate { name.chars().all(|c| c.is_ascii()) } + pub fn valid_feature_name(name: &str) -> bool { + let mut parts = name.split('/'); + match parts.next() { + Some(part) if !Crate::valid_name(part) => return false, + None => return false, + _ => {} + } + match parts.next() { + Some(part) if !Crate::valid_name(part) => return false, + _ => {} + } + parts.next().is_none() + } + pub fn encodable(self, versions: Option>) -> EncodableCrate { let Crate { name, created_at, updated_at, downloads, max_version, description, diff --git a/src/tests/krate.rs b/src/tests/krate.rs index cf7015bb12..9651550892 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -326,6 +326,15 @@ fn new_crate_owner() { ::json::(&mut response); } +#[test] +fn valid_feature_names() { + assert!(Crate::valid_feature_name("foo")); + assert!(!Crate::valid_feature_name("")); + assert!(!Crate::valid_feature_name("/")); + assert!(!Crate::valid_feature_name("%/%")); + assert!(Crate::valid_feature_name("a/a")); +} + #[test] fn new_krate_too_big() { let (_b, app, middle) = ::app(); diff --git a/src/upload.rs b/src/upload.rs index 409a89dc08..815dcc9b84 100644 --- a/src/upload.rs +++ b/src/upload.rs @@ -29,13 +29,14 @@ pub struct CrateVersion(pub semver::Version); pub struct CrateVersionReq(pub semver::VersionReq); pub struct KeywordList(pub Vec); pub struct Keyword(pub String); +pub struct Feature(pub String); #[deriving(Decodable, Encodable)] pub struct CrateDependency { pub optional: bool, pub default_features: bool, pub name: CrateName, - pub features: Vec, + pub features: Vec, pub version_req: CrateVersionReq, pub target: Option, pub kind: Option, @@ -63,6 +64,17 @@ impl> Decodable for Keyword { } } +impl> Decodable for Feature { + fn decode(d: &mut D) -> Result { + let s = raw_try!(d.read_str()); + if !Crate::valid_feature_name(s.as_slice()) { + return Err(d.error(format!("invalid feature name specified: {}", + s).as_slice())) + } + Ok(Feature(s)) + } +} + impl> Decodable for CrateVersion { fn decode(d: &mut D) -> Result { let s = raw_try!(d.read_str()); @@ -126,6 +138,12 @@ impl> Encodable for Keyword { } } +impl> Encodable for Feature { + fn encode(&self, d: &mut D) -> Result<(), E> { + d.emit_str(self.as_slice()) + } +} + impl> Encodable for CrateVersion { fn encode(&self, d: &mut D) -> Result<(), E> { d.emit_str((**self).to_string().as_slice()) @@ -169,6 +187,13 @@ impl Deref for Keyword { } } +impl Deref for Feature { + fn deref<'a>(&'a self) -> &'a str { + let Feature(ref s) = *self; + s.as_slice() + } +} + impl Deref for CrateVersion { fn deref<'a>(&'a self) -> &'a semver::Version { let CrateVersion(ref s) = *self; s