diff --git a/src/cargo/core/feature.rs b/src/cargo/core/feature.rs new file mode 100644 index 00000000000..dc12fd82fac --- /dev/null +++ b/src/cargo/core/feature.rs @@ -0,0 +1,34 @@ +#[derive(Debug, Clone)] +pub struct Feature { + dependencies: Vec, + features: Vec, +} + +impl Feature { + pub fn new() -> Feature { + Feature { + dependencies: vec![], + features: vec![], + } + } + + pub fn dependencies(&self) -> &[String] { + &self.dependencies + } + + pub fn features(&self) -> &[String] { + &self.features + } + + /// Sets the list of dependencies required by this feature + pub fn set_dependencies(mut self, dependencies: Vec) -> Feature { + self.dependencies = dependencies; + self + } + + /// Sets the list of features that this feature depends on + pub fn set_features(mut self, features: Vec) -> Feature { + self.features = features; + self + } +} diff --git a/src/cargo/core/mod.rs b/src/cargo/core/mod.rs index d345e3d67c5..b8576077311 100644 --- a/src/cargo/core/mod.rs +++ b/src/cargo/core/mod.rs @@ -8,6 +8,7 @@ pub use self::resolver::Resolve; pub use self::shell::{Shell, MultiShell, ShellConfig}; pub use self::source::{Source, SourceId, SourceMap, SourceSet, GitReference}; pub use self::summary::Summary; +pub use self::feature::Feature; pub mod source; pub mod package; @@ -18,4 +19,5 @@ pub mod resolver; pub mod summary; pub mod shell; pub mod registry; +pub mod feature; mod package_id_spec; diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index bba90c3ad8a..4c7511e83c7 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -6,7 +6,7 @@ use std::fmt; use std::rc::Rc; use semver; -use core::{PackageId, Registry, SourceId, Summary, Dependency}; +use core::{PackageId, Registry, SourceId, Summary, Dependency, Feature}; use core::PackageIdSpec; use util::{CargoResult, Graph, human, ChainError, CargoError}; use util::profile; @@ -33,10 +33,12 @@ pub struct Resolve { #[derive(Copy)] pub enum Method<'a> { Everything, - Required(/* dev_deps = */ bool, - /* features = */ &'a [String], - /* uses_default_features = */ bool, - /* target_platform = */ Option<&'a str>), + Required { + dev_deps: bool, + features: &'a [String], + uses_default_features: bool, + target_platform: Option<&'a str> + }, } impl Resolve { @@ -170,7 +172,7 @@ fn activate(mut cx: Box, // Extracting the platform request. let platform = match method { - Method::Required(_, _, _, platform) => platform, + Method::Required { target_platform, .. } => target_platform, Method::Everything => None, }; @@ -230,7 +232,7 @@ fn flag_activated(cx: &mut Context, } debug!("checking if {} is already activated", summary.package_id()); let features = match *method { - Method::Required(_, features, _, _) => features, + Method::Required { features, .. } => features, Method::Everything => return false, }; match cx.resolve.features(id) { @@ -247,8 +249,12 @@ fn activate_deps<'a>(cx: Box, cur: usize) -> CargoResult>> { if cur == deps.len() { return Ok(Ok(cx)) } let (dep, ref candidates, ref features) = deps[cur]; - let method = Method::Required(false, &features, - dep.uses_default_features(), platform); + let method = Method::Required { + dev_deps: false, + features: &features, + uses_default_features: dep.uses_default_features(), + target_platform: platform + }; let key = (dep.name().to_string(), dep.source_id().clone()); let prev_active = cx.activations.get(&key) @@ -424,7 +430,7 @@ fn resolve_features<'a>(cx: &mut Context, parent: &'a Summary, (&'a Dependency, Vec)>> { let dev_deps = match method { Method::Everything => true, - Method::Required(dev_deps, _, _, _) => dev_deps, + Method::Required { dev_deps, .. } => dev_deps, }; // First, filter by dev-dependencies @@ -434,7 +440,7 @@ fn resolve_features<'a>(cx: &mut Context, parent: &'a Summary, // Second, ignoring dependencies that should not be compiled for this platform let deps = deps.filter(|d| { match method { - Method::Required(_, _, _, Some(ref platform)) => { + Method::Required { target_platform: Some(ref platform), .. } => { d.is_active_for_platform(platform) }, _ => true @@ -452,7 +458,7 @@ fn resolve_features<'a>(cx: &mut Context, parent: &'a Summary, continue } let mut base = feature_deps.remove(dep.name()).unwrap_or(vec![]); - for feature in dep.features().iter() { + for feature in dep.features() { base.push(feature.clone()); if feature.contains("/") { return Err(human(format!("features in dependencies \ @@ -464,19 +470,7 @@ fn resolve_features<'a>(cx: &mut Context, parent: &'a Summary, ret.insert(dep.name(), (dep, base)); } - // All features can only point to optional dependencies, in which case they - // should have all been weeded out by the above iteration. Any remaining - // features are bugs in that the package does not actually have those - // features. - if feature_deps.len() > 0 { - let unknown = feature_deps.keys().map(|s| s.as_slice()) - .collect::>(); - if unknown.len() > 0 { - let features = unknown.connect(", "); - return Err(human(format!("Package `{}` does not have these features: \ - `{}`", parent.package_id(), features))) - } - } + assert!(feature_deps.is_empty(), "ended up with leftover features: {:?}", feature_deps); // Record what list of features is active for this package. if used_features.len() > 0 { @@ -506,78 +500,66 @@ fn build_features(s: &Summary, method: Method) let mut visited = HashSet::new(); match method { Method::Everything => { - for key in s.features().keys() { - try!(add_feature(s, key, &mut deps, &mut used, &mut visited)); - } for dep in s.dependencies().iter().filter(|d| d.is_optional()) { - try!(add_feature(s, dep.name(), &mut deps, &mut used, - &mut visited)); + deps.insert(dep.name().to_string(), vec![]); + } + for (name, feat) in s.features() { + try!(add_feature(s, name, feat, &mut deps, &mut used, &mut visited)); } } - Method::Required(_, requested_features, _, _) => { - for feat in requested_features.iter() { - try!(add_feature(s, feat, &mut deps, &mut used, &mut visited)); + Method::Required { features: requested_features, .. } => { + let (good, bad): (Vec<_>, Vec<_>) = requested_features.iter() + .filter(|f| !f.is_empty()) + .partition(|f| s.features().contains_key(*f)); + if !bad.is_empty() { + return Err(human(format!("Package `{}` does not have these features: \ + `{}`", s.package_id(), bad.connect(",")))) + } + for (name, feat) in good.iter().map(|feat| (feat, &s.features()[**feat])) { + try!(add_feature(s, name, feat, &mut deps, &mut used, &mut visited)); } } } match method { - Method::Everything | Method::Required(_, _, true, _) => { - if s.features().get("default").is_some() && - !visited.contains("default") { - try!(add_feature(s, "default", &mut deps, &mut used, - &mut visited)); + Method::Everything | Method::Required { uses_default_features: true, .. } => { + match s.features().get("default") { + Some(feat) if !visited.contains("default") => { + try!(add_feature(s, "default", feat, &mut deps, &mut used, &mut visited)); + } + _ => {} } } _ => {} } return Ok((deps, used)); - fn add_feature(s: &Summary, feat: &str, + fn add_feature(s: &Summary, name: &str, feat: &Feature, deps: &mut HashMap>, used: &mut HashSet, visited: &mut HashSet) -> CargoResult<()> { - if feat.is_empty() { return Ok(()) } - - // If this feature is of the form `foo/bar`, then we just lookup package - // `foo` and enable its feature `bar`. Otherwise this feature is of the - // form `foo` and we need to recurse to enable the feature `foo` for our - // own package, which may end up enabling more features or just enabling - // a dependency. - let mut parts = feat.splitn(1, '/'); - let feat_or_package = parts.next().unwrap(); - match parts.next() { - Some(feat) => { - let package = feat_or_package; - match deps.entry(package.to_string()) { - Occupied(e) => e.into_mut(), - Vacant(e) => e.insert(Vec::new()), - }.push(feat.to_string()); + used.insert(name.to_string()); + + for dep in feat.dependencies() { + let mut parts = dep.splitn(1, '/'); + let package = parts.next().unwrap(); + let feats = match deps.entry(package.to_string()) { + Occupied(e) => e.into_mut(), + Vacant(e) => e.insert(Vec::new()), + }; + if let Some(feat) = parts.next() { + feats.push(feat.to_string()); } - None => { - let feat = feat_or_package; - if !visited.insert(feat.to_string()) { - return Err(human(format!("Cyclic feature dependency: \ - feature `{}` depends on itself", - feat))) - } - used.insert(feat.to_string()); - match s.features().get(feat) { - Some(recursive) => { - for f in recursive.iter() { - try!(add_feature(s, f, deps, used, - visited)); - } - } - None => { - match deps.entry(feat.to_string()) { - Occupied(..) => {} // already activated - Vacant(e) => { e.insert(Vec::new()); } - } - } - } - visited.remove(&feat.to_string()); + } + + for subfeat in feat.features() { + if !visited.insert(subfeat.to_string()) { + return Err(human(format!("Cyclic feature dependency: feature \ + `{}` depends on itself", subfeat))); } + try!(add_feature(s, subfeat, &s.features()[*subfeat], deps, used, visited)); + visited.remove(subfeat); } + Ok(()) } } diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index 53513855270..fef9138221d 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::mem; use semver::Version; -use core::{Dependency, PackageId, SourceId}; +use core::{Dependency, PackageId, SourceId, Feature}; use util::{CargoResult, human}; @@ -14,30 +14,25 @@ use util::{CargoResult, human}; pub struct Summary { package_id: PackageId, dependencies: Vec, - features: HashMap>, + features: HashMap, } impl Summary { pub fn new(pkg_id: PackageId, dependencies: Vec, - features: HashMap>) -> CargoResult { - for dep in dependencies.iter() { - if features.get(dep.name()).is_some() { - return Err(human(format!("Features and dependencies cannot have \ - the same name: `{}`", dep.name()))) - } + features: HashMap) -> CargoResult { + for dep in &dependencies { if dep.is_optional() && !dep.is_transitive() { return Err(human(format!("Dev-dependencies are not allowed \ to be optional: `{}`", dep.name()))) } } - for (feature, list) in features.iter() { - for dep in list.iter() { + for (feature, desc) in &features { + for dep in desc.dependencies() { let mut parts = dep.splitn(1, '/'); let dep = parts.next().unwrap(); let is_reexport = parts.next().is_some(); - if !is_reexport && features.get(dep).is_some() { continue } match dependencies.iter().find(|d| d.name() == dep) { Some(d) => { if d.is_optional() || is_reexport { continue } @@ -47,19 +42,20 @@ impl Summary { `optional = true` to the \ dependency", feature, dep))) } - None if is_reexport => { - return Err(human(format!("Feature `{}` requires `{}` \ - which is not an optional \ - dependency", feature, dep))) - } None => { - return Err(human(format!("Feature `{}` includes `{}` \ - which is neither a dependency \ - nor another feature", + return Err(human(format!("Feature `{}` requires `{}` \ + which is not a dependency", feature, dep))) } } } + for subfeat in desc.features() { + if !features.contains_key(subfeat) { + return Err(human(format!("Feature `{}` requires `{}` which \ + is not a feature", feature, + subfeat))); + } + } } Ok(Summary { package_id: pkg_id, @@ -73,7 +69,7 @@ impl Summary { pub fn version(&self) -> &Version { self.package_id().version() } pub fn source_id(&self) -> &SourceId { self.package_id.source_id() } pub fn dependencies(&self) -> &[Dependency] { &self.dependencies } - pub fn features(&self) -> &HashMap> { &self.features } + pub fn features(&self) -> &HashMap { &self.features } pub fn override_id(mut self, id: PackageId) -> Summary { self.package_id = id; diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index b48c0d53f9a..46129c49ca6 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -109,8 +109,12 @@ pub fn compile_pkg(package: &Package, options: &CompileOptions) try!(registry.add_overrides(override_ids)); let platform = target.as_ref().map(|e| e.as_slice()).or(Some(rustc_host.as_slice())); - let method = Method::Required(dev_deps, &features, - !no_default_features, platform); + let method = Method::Required { + dev_deps: dev_deps, + features: &features, + uses_default_features: !no_default_features, + target_platform: platform + }; let resolved_with_overrides = try!(ops::resolve_with_previous(&mut registry, package, method, Some(&resolve), None)); diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 2461981b835..97026bb74b1 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -6,7 +6,7 @@ use std::old_io::fs::PathExtensions; use curl::http; use git2; -use registry::{Registry, NewCrate, NewCrateDependency}; +use registry::{Registry, NewCrate, NewCrateDependency, NewCrateFeature}; use term::color::BLACK; use core::source::Source; @@ -88,6 +88,12 @@ fn transmit(pkg: &Package, tarball: &Path, registry: &mut Registry) }.to_string(), } }).collect::>(); + let features = pkg.summary().features().iter().map(|(name, feature)| { + (name.clone(), NewCrateFeature { + dependencies: feature.dependencies().to_vec(), + features: feature.features().to_vec(), + }) + }).collect(); let manifest = pkg.manifest(); let ManifestMetadata { ref authors, ref description, ref homepage, ref documentation, @@ -115,7 +121,7 @@ fn transmit(pkg: &Package, tarball: &Path, registry: &mut Registry) name: pkg.name().to_string(), vers: pkg.version().to_string(), deps: deps, - features: pkg.summary().features().clone(), + features: features, authors: authors.clone(), description: description.clone(), homepage: homepage.clone(), diff --git a/src/cargo/sources/registry.rs b/src/cargo/sources/registry.rs index 2a26e1a6f57..c5f166e19c1 100644 --- a/src/cargo/sources/registry.rs +++ b/src/cargo/sources/registry.rs @@ -170,7 +170,7 @@ use rustc_serialize::json; use tar::Archive; use url::Url; -use core::{Source, SourceId, PackageId, Package, Summary, Registry}; +use core::{Source, SourceId, PackageId, Package, Summary, Registry, Feature}; use core::dependency::{Dependency, Kind}; use sources::{PathSource, git}; use util::{CargoResult, Config, internal, ChainError, ToUrl, human}; @@ -209,7 +209,7 @@ struct RegistryPackage { name: String, vers: String, deps: Vec, - features: HashMap>, + features: HashMap, cksum: String, yanked: Option, } @@ -225,6 +225,12 @@ struct RegistryDependency { kind: Option, } +#[derive(RustcDecodable)] +struct RegistryFeature { + features: Vec, + dependencies: Vec, +} + impl<'a, 'b> RegistrySource<'a, 'b> { pub fn new(source_id: &SourceId, config: &'a Config<'b>) -> RegistrySource<'a, 'b> { @@ -407,6 +413,9 @@ impl<'a, 'b> RegistrySource<'a, 'b> { self.parse_registry_dependency(dep) }).collect(); let deps = try!(deps); + let features = features.into_iter().map(|(name, feature)| { + (name, self.parse_feature(feature)) + }).collect(); self.hashes.insert((name, vers), cksum); Ok((try!(Summary::new(pkgid, deps, features)), yanked.unwrap_or(false))) } @@ -433,6 +442,12 @@ impl<'a, 'b> RegistrySource<'a, 'b> { .set_kind(kind)) } + /// Converts an encoded feature into a cargo feature + fn parse_feature(&self, feature: RegistryFeature) -> Feature { + let RegistryFeature { dependencies, features } = feature; + Feature::new().set_dependencies(dependencies).set_features(features) + } + /// Actually perform network operations to update the registry fn do_update(&mut self) -> CargoResult<()> { if self.updated { return Ok(()) } diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index a55b471fa9e..2ea3fee0eeb 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -10,7 +10,7 @@ use semver; use rustc_serialize::{Decodable, Decoder}; use core::SourceId; -use core::{Summary, Manifest, Target, Dependency, PackageId, GitReference}; +use core::{Summary, Manifest, Target, Dependency, PackageId, GitReference, Feature}; use core::dependency::Kind; use core::manifest::{LibKind, Profile, ManifestMetadata}; use core::package_id::Metadata; @@ -196,6 +196,18 @@ pub struct DetailedTomlDependency { default_features: Option, } +#[derive(RustcDecodable)] +pub enum TomlFeature { + Simple(Vec), + Detailed(DetailedTomlFeature), +} + +#[derive(RustcDecodable, Clone)] +pub struct DetailedTomlFeature { + dependencies: Vec, + features: Vec, +} + #[derive(RustcDecodable)] pub struct TomlManifest { package: Option>, @@ -209,7 +221,7 @@ pub struct TomlManifest { dependencies: Option>, dev_dependencies: Option>, build_dependencies: Option>, - features: Option>>, + features: Option>, target: Option>, } @@ -491,9 +503,7 @@ impl TomlManifest { let exclude = project.exclude.clone().unwrap_or(Vec::new()); let include = project.include.clone().unwrap_or(Vec::new()); - let summary = try!(Summary::new(pkgid, deps, - self.features.clone() - .unwrap_or(HashMap::new()))); + let summary = try!(Summary::new(pkgid, deps, translate_features(&self.features))); let metadata = ManifestMetadata { description: project.description.clone(), homepage: project.homepage.clone(), @@ -578,6 +588,24 @@ fn process_dependencies(cx: &mut Context, Ok(()) } +fn translate_features(raw: &Option>) -> HashMap { + if let &None = raw { + return HashMap::new(); + } + + raw.as_ref().unwrap().iter().map(|(name, desc)| { + let desc = match *desc { + TomlFeature::Simple(ref features) => Feature::new().set_dependencies(features.clone()), + TomlFeature::Detailed(ref detail) => { + Feature::new() + .set_features(detail.features.clone()) + .set_dependencies(detail.dependencies.clone()) + } + }; + (name.clone(), desc) + }).collect() +} + #[derive(RustcDecodable, Debug, Clone)] struct TomlTarget { name: String, diff --git a/src/registry/lib.rs b/src/registry/lib.rs index 887264fc535..0d70668cb6d 100644 --- a/src/registry/lib.rs +++ b/src/registry/lib.rs @@ -51,7 +51,7 @@ pub struct NewCrate { pub name: String, pub vers: String, pub deps: Vec, - pub features: HashMap>, + pub features: HashMap, pub authors: Vec, pub description: Option, pub documentation: Option, @@ -74,6 +74,12 @@ pub struct NewCrateDependency { pub kind: String, } +#[derive(RustcEncodable)] +pub struct NewCrateFeature { + pub dependencies: Vec, + pub features: Vec, +} + #[derive(RustcDecodable)] pub struct User { pub id: u32, @@ -146,7 +152,7 @@ impl Registry { let mut body = ChainedReader::new(vec![Box::new(header) as Box, Box::new(tarball) as Box].into_iter()); - let url = format!("{}/api/v1/crates/new", self.host); + let url = format!("{}/api/v2/crates/new", self.host); let token = try!(self.token.as_ref().ok_or(Error::TokenMissing)); let request = self.handle.put(url, &mut body) @@ -194,7 +200,7 @@ impl Registry { fn req(&mut self, path: String, body: Option<&[u8]>, method: Method, authorized: Auth) -> Result { let mut req = Request::new(&mut self.handle, method) - .uri(format!("{}/api/v1{}", self.host, path)) + .uri(format!("{}/api/v2{}", self.host, path)) .header("Accept", "application/json") .content_type("application/json"); diff --git a/tests/test_cargo_features.rs b/tests/test_cargo_features.rs index 9f39f22e6ca..289c4446a9d 100644 --- a/tests/test_cargo_features.rs +++ b/tests/test_cargo_features.rs @@ -26,32 +26,7 @@ test!(invalid1 { failed to parse manifest at `[..]` Caused by: - Feature `bar` includes `baz` which is neither a dependency nor another feature -").as_slice())); -}); - -test!(invalid2 { - let p = project("foo") - .file("Cargo.toml", r#" - [project] - name = "foo" - version = "0.0.1" - authors = [] - - [features] - bar = ["baz"] - - [dependencies.bar] - path = "foo" - "#) - .file("src/main.rs", ""); - - assert_that(p.cargo_process("build"), - execs().with_status(101).with_stderr(format!("\ -failed to parse manifest at `[..]` - -Caused by: - Features and dependencies cannot have the same name: `bar` + Feature `bar` requires `baz` which is not a dependency ").as_slice())); }); @@ -161,7 +136,7 @@ test!(invalid6 { failed to parse manifest at `[..]` Caused by: - Feature `foo` requires `bar` which is not an optional dependency + Feature `foo` requires `bar` which is not a dependency ").as_slice())); }); @@ -184,7 +159,7 @@ test!(invalid7 { failed to parse manifest at `[..]` Caused by: - Feature `foo` requires `bar` which is not an optional dependency + Feature `foo` requires `bar` which is not a dependency ").as_slice())); }); @@ -223,6 +198,9 @@ test!(no_feature_doesnt_build { version = "0.0.1" authors = [] + [features] + bar = ["bar"] + [dependencies.bar] path = "bar" optional = true @@ -268,7 +246,10 @@ test!(default_feature_pulled_in { authors = [] [features] - default = ["bar"] + bar = ["bar"] + + [features.default] + features = ["bar"] [dependencies.bar] path = "bar" @@ -314,8 +295,8 @@ test!(cyclic_feature { version = "0.0.1" authors = [] - [features] - default = ["default"] + [features.default] + features = ["default"] "#) .file("src/main.rs", ""); @@ -333,9 +314,11 @@ test!(cyclic_feature2 { version = "0.0.1" authors = [] - [features] - foo = ["bar"] - bar = ["foo"] + [features.foo] + features = ["bar"] + + [features.bar] + features = ["foo"] "#) .file("src/main.rs", ""); @@ -353,15 +336,31 @@ test!(groups_on_groups_on_groups { version = "0.0.1" authors = [] - [features] - default = ["f1"] - f1 = ["f2", "bar"] - f2 = ["f3", "f4"] - f3 = ["f5", "f6", "baz"] - f4 = ["f5", "f7"] - f5 = ["f6"] - f6 = ["f7"] - f7 = ["bar"] + [features.default] + features = ["f1"] + + [features.f1] + features = ["f2"] + dependencies = ["bar"] + + [features.f2] + features = ["f3", "f4"] + + [features.f3] + features = ["f5", "f6"] + dependencies = ["baz"] + + [features.f4] + features = ["f5", "f7"] + + [features.f5] + features = ["f6"] + + [features.f6] + features = ["f7"] + + [features.f7] + dependencies = ["bar"] [dependencies.bar] path = "bar" @@ -407,6 +406,10 @@ test!(many_cli_features { version = "0.0.1" authors = [] + [features] + bar = ["bar"] + baz = ["baz"] + [dependencies.bar] path = "bar" optional = true @@ -526,7 +529,9 @@ test!(many_features_no_rebuilds { [features] ftest = [] ftest2 = [] - fall = ["ftest", "ftest2"] + + [features.fall] + features = ["ftest", "ftest2"] "#) .file("a/src/lib.rs", ""); diff --git a/tests/test_cargo_publish.rs b/tests/test_cargo_publish.rs index 760aa1cd550..a399c0f2794 100644 --- a/tests/test_cargo_publish.rs +++ b/tests/test_cargo_publish.rs @@ -24,7 +24,7 @@ fn setup() { index = "{reg}" token = "api-token" "#, reg = registry()).as_slice()).unwrap(); - fs::mkdir_recursive(&upload_path().join("api/v1/crates"), old_io::USER_DIR).unwrap(); + fs::mkdir_recursive(&upload_path().join("api/v2/crates"), old_io::USER_DIR).unwrap(); repo(®istry_path()) .file("config.json", format!(r#"{{ @@ -58,7 +58,7 @@ test!(simple { dir = p.url(), reg = registry()).as_slice())); - let mut f = File::open(&upload_path().join("api/v1/crates/new")).unwrap(); + let mut f = File::open(&upload_path().join("api/v2/crates/new")).unwrap(); // Skip the metadata payload and the size of the tarball let sz = f.read_le_u32().unwrap(); f.seek(sz as i64 + 4, old_io::SeekCur).unwrap(); diff --git a/tests/test_cargo_search.rs b/tests/test_cargo_search.rs index e67eed073ff..740efff4412 100644 --- a/tests/test_cargo_search.rs +++ b/tests/test_cargo_search.rs @@ -22,7 +22,7 @@ fn setup() { [registry] index = "{reg}" "#, reg = registry()).as_slice()).unwrap(); - fs::mkdir_recursive(&api_path().join("api/v1"), old_io::USER_DIR).unwrap(); + fs::mkdir_recursive(&api_path().join("api/v2"), old_io::USER_DIR).unwrap(); repo(®istry_path()) .file("config.json", format!(r#"{{ @@ -50,10 +50,10 @@ test!(simple { "keywords": [], "license": null, "links": { - "owners": "/api/v1/crates/hoare/owners", - "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies", - "version_downloads": "/api/v1/crates/hoare/downloads", - "versions": "/api/v1/crates/hoare/versions" + "owners": "/api/v2/crates/hoare/owners", + "reverse_dependencies": "/api/v2/crates/hoare/reverse_dependencies", + "version_downloads": "/api/v2/crates/hoare/downloads", + "versions": "/api/v2/crates/hoare/versions" }, "max_version": "0.1.1", "name": "hoare", @@ -65,7 +65,7 @@ test!(simple { "total": 1 } }"#; - let base = api_path().join("api/v1/crates"); + let base = api_path().join("api/v2/crates"); // Older versions of curl don't peel off query parameters when looking for // filenames, so just make both files.