summary: Summary,
targets: Vec<Target>,
links: Option<String>,
- warnings: Vec<String>,
+ warnings: Vec<DelayedWarning>,
exclude: Vec<String>,
include: Vec<String>,
metadata: ManifestMetadata,
original: Rc<TomlManifest>,
}
+/// When parsing `Cargo.toml`, some warnings should silenced
+/// if the manifest comes from a dependency. `ManifestWarning`
+/// allows this delayed emission of warnings.
+#[derive(Clone, Debug)]
+pub struct DelayedWarning {
+ pub message: String,
+ pub is_critical: bool
+}
+
#[derive(Clone, Debug)]
pub struct VirtualManifest {
replace: Vec<(PackageIdSpec, Dependency)>,
pub fn summary(&self) -> &Summary { &self.summary }
pub fn targets(&self) -> &[Target] { &self.targets }
pub fn version(&self) -> &Version { self.package_id().version() }
- pub fn warnings(&self) -> &[String] { &self.warnings }
+ pub fn warnings(&self) -> &[DelayedWarning] { &self.warnings }
pub fn profiles(&self) -> &Profiles { &self.profiles }
pub fn publish(&self) -> bool { self.publish }
pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] { &self.replace }
}
pub fn add_warning(&mut self, s: String) {
- self.warnings.push(s)
+ self.warnings.push(DelayedWarning { message: s, is_critical: false })
+ }
+
+ pub fn add_critical_warning(&mut self, s: String) {
+ self.warnings.push(DelayedWarning { message: s, is_critical: true })
}
pub fn set_summary(&mut self, summary: Summary) {
-> CargoResult<(Manifest, Vec<PathBuf>)> {
let mut nested_paths = vec![];
let mut warnings = vec![];
+ let mut errors = vec![];
let project = me.project.as_ref().or_else(|| me.package.as_ref());
let project = project.ok_or_else(|| {
// If we have no lib at all, use the inferred lib if available
// If we have a lib with a path, we're done
// If we have a lib with no path, use the inferred lib or_else package name
- let targets = targets(me, package_name, package_root, &project.build, &mut warnings)?;
+ let targets = targets(me, package_name, package_root, &project.build,
+ &mut warnings, &mut errors)?;
if targets.is_empty() {
debug!("manifest has no build targets");
`license-file` is necessary".to_string());
}
for warning in warnings {
- manifest.add_warning(warning.clone());
+ manifest.add_warning(warning);
+ }
+ for error in errors {
+ manifest.add_critical_warning(error);
}
Ok((manifest, nested_paths))
package_name: &str,
package_root: &Path,
custom_build: &Option<StringOrBool>,
- warnings: &mut Vec<String>)
+ warnings: &mut Vec<String>,
+ errors: &mut Vec<String>)
-> CargoResult<Vec<Target>> {
let mut targets = Vec::new();
);
targets.extend(
- clean_examples(manifest.example.as_ref(), package_root)?
+ clean_examples(manifest.example.as_ref(), package_root, errors)?
);
targets.extend(
- clean_tests(manifest.test.as_ref(), package_root)?
+ clean_tests(manifest.test.as_ref(), package_root, errors)?
);
targets.extend(
- clean_benches(manifest.bench.as_ref(), package_root, warnings)?
+ clean_benches(manifest.bench.as_ref(), package_root, warnings, errors)?
);
// processing the custom build script
} else {
None
}
- })?;
+ });
+ let path = match path {
+ Ok(path) => path,
+ Err(e) => bail!("{}", e),
+ };
let mut target = Target::bin_target(&bin.name(), path,
bin.required_features.clone());
}
fn clean_examples(toml_examples: Option<&Vec<TomlExampleTarget>>,
- package_root: &Path)
+ package_root: &Path,
+ errors: &mut Vec<String>)
-> CargoResult<Vec<Target>> {
let targets = clean_targets("example", "example",
toml_examples, inferred_examples(package_root),
- package_root)?;
+ package_root, errors)?;
let mut result = Vec::new();
for (path, toml) in targets {
}
fn clean_tests(toml_tests: Option<&Vec<TomlTestTarget>>,
- package_root: &Path) -> CargoResult<Vec<Target>> {
+ package_root: &Path,
+ errors: &mut Vec<String>) -> CargoResult<Vec<Target>> {
let targets = clean_targets("test", "test",
toml_tests, inferred_tests(package_root),
- package_root)?;
+ package_root, errors)?;
let mut result = Vec::new();
for (path, toml) in targets {
fn clean_benches(toml_benches: Option<&Vec<TomlBenchTarget>>,
package_root: &Path,
- warnings: &mut Vec<String>) -> CargoResult<Vec<Target>> {
+ warnings: &mut Vec<String>,
+ errors: &mut Vec<String>) -> CargoResult<Vec<Target>> {
let mut legacy_bench_path = |bench: &TomlTarget| {
let legacy_path = package_root.join("src").join("bench.rs");
if !(bench.name() == "bench" && legacy_path.exists()) {
let targets = clean_targets_with_legacy_path("benchmark", "bench",
toml_benches, inferred_benches(package_root),
package_root,
+ errors,
&mut legacy_bench_path)?;
let mut result = Vec::new();
fn clean_targets(target_kind_human: &str, target_kind: &str,
toml_targets: Option<&Vec<TomlTarget>>,
inferred: Vec<(String, PathBuf)>,
- package_root: &Path)
+ package_root: &Path,
+ errors: &mut Vec<String>)
-> CargoResult<Vec<(PathBuf, TomlTarget)>> {
clean_targets_with_legacy_path(target_kind_human, target_kind,
toml_targets,
inferred,
package_root,
+ errors,
&mut |_| None)
}
toml_targets: Option<&Vec<TomlTarget>>,
inferred: Vec<(String, PathBuf)>,
package_root: &Path,
+ errors: &mut Vec<String>,
legacy_path: &mut FnMut(&TomlTarget) -> Option<PathBuf>)
-> CargoResult<Vec<(PathBuf, TomlTarget)>> {
let toml_targets = match toml_targets {
validate_unique_names(&toml_targets, target_kind)?;
let mut result = Vec::new();
for target in toml_targets {
- let path = target_path(&target, &inferred, target_kind, package_root, legacy_path)?;
+ let path = target_path(&target, &inferred, target_kind, package_root, legacy_path);
+ let path = match path {
+ Ok(path) => path,
+ Err(e) => {
+ errors.push(e);
+ continue
+ },
+ };
result.push((path, target));
}
Ok(result)
inferred: &[(String, PathBuf)],
target_kind: &str,
package_root: &Path,
- legacy_path: &mut FnMut(&TomlTarget) -> Option<PathBuf>) -> CargoResult<PathBuf> {
+ legacy_path: &mut FnMut(&TomlTarget) -> Option<PathBuf>) -> Result<PathBuf, String> {
if let Some(ref path) = target.path {
// Should we verify that this path exists here?
return Ok(package_root.join(&path.0));
if let Some(path) = legacy_path(target) {
return Ok(path);
}
-
- bail!("can't find `{name}` {target_kind}, specify {target_kind}.path",
- name = name, target_kind = target_kind)
+ Err(format!("can't find `{name}` {target_kind}, specify {target_kind}.path",
+ name = name, target_kind = target_kind))
}
(None, Some(_)) => unreachable!()
}
assert_that(p.cargo_process("test").arg("--all"),
execs().with_status(0));
}
+
+#[test]
+fn publish_a_crate_without_tests() {
+ Package::new("testless", "0.1.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "testless"
+ version = "0.1.0"
+ exclude = ["tests/*"]
+
+ [[test]]
+ name = "a_test"
+ "#)
+ .file("src/lib.rs", "")
+
+ // In real life, the package will have a test,
+ // which would be excluded from .crate file by the
+ // `exclude` field. Our test harness does not honor
+ // exclude though, so let's just not add the file!
+ // .file("tests/a_test.rs", "")
+
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ testless = "0.1.0"
+ "#)
+ .file("src/lib.rs", "");
+ p.build();
+
+ assert_that(p.cargo("test"), execs().with_status(0));
+ assert_that(p.cargo("test").arg("--package").arg("testless"),
+ execs().with_status(0));
+}