mirror of
https://github.com/rust-lang/cargo
synced 2024-10-13 03:02:45 +00:00
Add support for a license-file manifest key
This key will support projects with nonstandard licenses and the registry will display the license as "nonstandard". Closes #940
This commit is contained in:
parent
b9ff1a3af5
commit
5acb5f567b
|
@ -45,6 +45,7 @@ pub struct ManifestMetadata {
|
||||||
pub authors: Vec<String>,
|
pub authors: Vec<String>,
|
||||||
pub keywords: Vec<String>,
|
pub keywords: Vec<String>,
|
||||||
pub license: Option<String>,
|
pub license: Option<String>,
|
||||||
|
pub license_file: Option<String>,
|
||||||
pub description: Option<String>, // not markdown
|
pub description: Option<String>, // not markdown
|
||||||
pub readme: Option<String>, // file, not contents
|
pub readme: Option<String>, // file, not contents
|
||||||
pub homepage: Option<String>, // url
|
pub homepage: Option<String>, // url
|
||||||
|
|
|
@ -75,15 +75,15 @@ fn check_metadata(pkg: &Package, shell: &mut MultiShell) -> CargoResult<()> {
|
||||||
let mut missing = vec![];
|
let mut missing = vec![];
|
||||||
|
|
||||||
macro_rules! lacking {
|
macro_rules! lacking {
|
||||||
($($field: ident),*) => {{
|
($( $($field: ident)||* ),*) => {{
|
||||||
$(
|
$(
|
||||||
if md.$field.as_ref().map_or(true, |s| s.is_empty()) {
|
if $(md.$field.as_ref().map_or(true, |s| s.is_empty()))&&* {
|
||||||
missing.push(stringify!($field))
|
$(missing.push(stringify!($field).replace("_", "-"));)*
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
lacking!(description, license)
|
lacking!(description, license || license_file)
|
||||||
|
|
||||||
if !missing.is_empty() {
|
if !missing.is_empty() {
|
||||||
let mut things = missing.slice_to(missing.len() - 1).connect(", ");
|
let mut things = missing.slice_to(missing.len() - 1).connect(", ");
|
||||||
|
@ -91,10 +91,10 @@ fn check_metadata(pkg: &Package, shell: &mut MultiShell) -> CargoResult<()> {
|
||||||
if !things.is_empty() {
|
if !things.is_empty() {
|
||||||
things.push_str(" or ");
|
things.push_str(" or ");
|
||||||
}
|
}
|
||||||
things.push_str(*missing.last().unwrap());
|
things.push_str(missing.last().unwrap().as_slice());
|
||||||
|
|
||||||
try!(shell.warn(
|
try!(shell.warn(
|
||||||
format!("Warning: manifest has no {things}. \
|
format!("warning: manifest has no {things}. \
|
||||||
See http://doc.crates.io/manifest.html#package-metadata for more info.",
|
See http://doc.crates.io/manifest.html#package-metadata for more info.",
|
||||||
things = things).as_slice()))
|
things = things).as_slice()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::File;
|
use std::io::File;
|
||||||
|
use std::io::fs::PathExtensions;
|
||||||
use std::os;
|
use std::os;
|
||||||
use term::color::BLACK;
|
use term::color::BLACK;
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ fn transmit(pkg: &Package, tarball: &Path, registry: &mut Registry)
|
||||||
let manifest = pkg.get_manifest();
|
let manifest = pkg.get_manifest();
|
||||||
let ManifestMetadata {
|
let ManifestMetadata {
|
||||||
ref authors, ref description, ref homepage, ref documentation,
|
ref authors, ref description, ref homepage, ref documentation,
|
||||||
ref keywords, ref readme, ref repository, ref license,
|
ref keywords, ref readme, ref repository, ref license, ref license_file,
|
||||||
} = *manifest.get_metadata();
|
} = *manifest.get_metadata();
|
||||||
let readme = match *readme {
|
let readme = match *readme {
|
||||||
Some(ref readme) => {
|
Some(ref readme) => {
|
||||||
|
@ -98,6 +99,15 @@ fn transmit(pkg: &Package, tarball: &Path, registry: &mut Registry)
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
match *license_file {
|
||||||
|
Some(ref file) => {
|
||||||
|
if !pkg.get_root().join(file).exists() {
|
||||||
|
return Err(human(format!("the license file `{}` does not exist",
|
||||||
|
file)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
registry.publish(&NewCrate {
|
registry.publish(&NewCrate {
|
||||||
name: pkg.get_name().to_string(),
|
name: pkg.get_name().to_string(),
|
||||||
vers: pkg.get_version().to_string(),
|
vers: pkg.get_version().to_string(),
|
||||||
|
@ -111,6 +121,7 @@ fn transmit(pkg: &Package, tarball: &Path, registry: &mut Registry)
|
||||||
readme: readme,
|
readme: readme,
|
||||||
repository: repository.clone(),
|
repository: repository.clone(),
|
||||||
license: license.clone(),
|
license: license.clone(),
|
||||||
|
license_file: license_file.clone(),
|
||||||
}, tarball).map_err(|e| {
|
}, tarball).map_err(|e| {
|
||||||
human(e.to_string())
|
human(e.to_string())
|
||||||
})
|
})
|
||||||
|
|
|
@ -267,6 +267,7 @@ pub struct TomlProject {
|
||||||
readme: Option<String>,
|
readme: Option<String>,
|
||||||
keywords: Option<Vec<String>>,
|
keywords: Option<Vec<String>>,
|
||||||
license: Option<String>,
|
license: Option<String>,
|
||||||
|
license_file: Option<String>,
|
||||||
repository: Option<String>,
|
repository: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,6 +519,7 @@ impl TomlManifest {
|
||||||
readme: project.readme.clone(),
|
readme: project.readme.clone(),
|
||||||
authors: project.authors.clone(),
|
authors: project.authors.clone(),
|
||||||
license: project.license.clone(),
|
license: project.license.clone(),
|
||||||
|
license_file: project.license_file.clone(),
|
||||||
repository: project.repository.clone(),
|
repository: project.repository.clone(),
|
||||||
keywords: project.keywords.clone().unwrap_or(Vec::new()),
|
keywords: project.keywords.clone().unwrap_or(Vec::new()),
|
||||||
};
|
};
|
||||||
|
@ -541,6 +543,11 @@ impl TomlManifest {
|
||||||
manifest.add_warning(format!(" For more information, see \
|
manifest.add_warning(format!(" For more information, see \
|
||||||
http://doc.crates.io/build-script.html"));
|
http://doc.crates.io/build-script.html"));
|
||||||
}
|
}
|
||||||
|
if project.license_file.is_some() && project.license.is_some() {
|
||||||
|
manifest.add_warning(format!("warning: only one of `license` or \
|
||||||
|
`license-file` is necessary"));
|
||||||
|
}
|
||||||
|
|
||||||
Ok((manifest, nested_paths))
|
Ok((manifest, nested_paths))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,11 @@ keywords = ["...", "..."]
|
||||||
# license identifiers from http://spdx.org/licenses/. Multiple licenses can
|
# license identifiers from http://spdx.org/licenses/. Multiple licenses can
|
||||||
# be separated with a `/`
|
# be separated with a `/`
|
||||||
license = "..."
|
license = "..."
|
||||||
|
|
||||||
|
# If a project is using a nonstandard license, then this key may be specified in
|
||||||
|
# lieu of the above key and must point to a file relative to this manifest
|
||||||
|
# (similar to the readme key)
|
||||||
|
license-file = "..."
|
||||||
```
|
```
|
||||||
|
|
||||||
The [crates.io](https://crates.io) registry will render the description, display
|
The [crates.io](https://crates.io) registry will render the description, display
|
||||||
|
|
|
@ -55,6 +55,7 @@ pub struct NewCrate {
|
||||||
pub readme: Option<String>,
|
pub readme: Option<String>,
|
||||||
pub keywords: Vec<String>,
|
pub keywords: Vec<String>,
|
||||||
pub license: Option<String>,
|
pub license: Option<String>,
|
||||||
|
pub license_file: Option<String>,
|
||||||
pub repository: Option<String>,
|
pub repository: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,8 @@ test!(metadata_warning {
|
||||||
verifying = VERIFYING,
|
verifying = VERIFYING,
|
||||||
compiling = COMPILING,
|
compiling = COMPILING,
|
||||||
dir = p.url()).as_slice())
|
dir = p.url()).as_slice())
|
||||||
.with_stderr("Warning: manifest has no description or license. See \
|
.with_stderr("\
|
||||||
|
warning: manifest has no description, license or license-file. See \
|
||||||
http://doc.crates.io/manifest.html#package-metadata for more info."));
|
http://doc.crates.io/manifest.html#package-metadata for more info."));
|
||||||
|
|
||||||
let p = project("one")
|
let p = project("one")
|
||||||
|
@ -104,7 +105,8 @@ test!(metadata_warning {
|
||||||
verifying = VERIFYING,
|
verifying = VERIFYING,
|
||||||
compiling = COMPILING,
|
compiling = COMPILING,
|
||||||
dir = p.url()).as_slice())
|
dir = p.url()).as_slice())
|
||||||
.with_stderr("Warning: manifest has no description. See \
|
.with_stderr("\
|
||||||
|
warning: manifest has no description. See \
|
||||||
http://doc.crates.io/manifest.html#package-metadata for more info."));
|
http://doc.crates.io/manifest.html#package-metadata for more info."));
|
||||||
|
|
||||||
let p = project("both")
|
let p = project("both")
|
||||||
|
|
|
@ -480,3 +480,22 @@ test!(login_with_no_cargo_dir {
|
||||||
.env("HOME", Some(home)),
|
.env("HOME", Some(home)),
|
||||||
execs().with_status(0));
|
execs().with_status(0));
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test!(bad_license_file {
|
||||||
|
let p = project("all")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = []
|
||||||
|
license-file = "foo"
|
||||||
|
description = "bar"
|
||||||
|
"#)
|
||||||
|
.file("src/main.rs", r#"
|
||||||
|
fn main() {}
|
||||||
|
"#);
|
||||||
|
assert_that(p.cargo_process("publish"),
|
||||||
|
execs().with_status(101)
|
||||||
|
.with_stderr("\
|
||||||
|
the license file `foo` does not exist"));
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in a new issue