Update TOML parser to pick up a bugfix

Cargo has previously accepted invalid TOML as valid, but this bugfix should fix
the problem. In order to prevent breaking all crates immediately toml-rs has a
compatibility mode which emulates the bug that was fixed. Cargo will issue a
warning if this compatibility is required to parse a crate.
This commit is contained in:
Alex Crichton 2016-05-12 11:44:00 -07:00
parent 07c1d9900d
commit 2a1e16c08a
7 changed files with 66 additions and 16 deletions

4
Cargo.lock generated
View file

@ -29,7 +29,7 @@ dependencies = [
"tar 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -437,7 +437,7 @@ dependencies = [
[[package]]
name = "toml"
version = "0.1.28"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -41,7 +41,7 @@ semver = "0.2.2"
tar = "0.4"
tempdir = "0.3"
term = "0.4.4"
toml = "0.1"
toml = "0.1.29"
url = "1.1"
winapi = "0.2"

View file

@ -22,7 +22,7 @@ pub fn load_pkg_lockfile(pkg: &Package, config: &Config)
}));
(|| {
let table = toml::Value::Table(try!(cargo_toml::parse(&s, f.path())));
let table = toml::Value::Table(try!(cargo_toml::parse(&s, f.path(), config)));
let mut d = toml::Decoder::new(table);
let v: resolver::EncodableResolve = try!(Decodable::decode(&mut d));
Ok(Some(try!(v.to_resolve(pkg, config))))

View file

@ -330,7 +330,9 @@ impl Config {
try!(walk_tree(&self.cwd, |mut file, path| {
let mut contents = String::new();
try!(file.read_to_string(&mut contents));
let table = try!(cargo_toml::parse(&contents, &path).chain_error(|| {
let table = try!(cargo_toml::parse(&contents,
&path,
self).chain_error(|| {
human(format!("could not parse TOML configuration in `{}`",
path.display()))
}));
@ -717,7 +719,7 @@ pub fn set_config(cfg: &Config,
};
let mut contents = String::new();
let _ = file.read_to_string(&mut contents);
let mut toml = try!(cargo_toml::parse(&contents, file.path()));
let mut toml = try!(cargo_toml::parse(&contents, file.path(), cfg));
toml.insert(key.to_string(), value.into_toml());
let contents = toml::Value::Table(toml).to_string();

View file

@ -114,7 +114,7 @@ pub fn to_manifest(contents: &[u8],
let contents = try!(str::from_utf8(contents).map_err(|_| {
human(format!("{} is not valid UTF-8", manifest.display()))
}));
let root = try!(parse(contents, &manifest));
let root = try!(parse(contents, &manifest, config));
let mut d = toml::Decoder::new(toml::Value::Table(root));
let manifest: TomlManifest = try!(Decodable::decode(&mut d).map_err(|e| {
human(e.to_string())
@ -154,15 +154,33 @@ pub fn to_manifest(contents: &[u8],
}
}
pub fn parse(toml: &str, file: &Path) -> CargoResult<toml::Table> {
let mut parser = toml::Parser::new(&toml);
if let Some(toml) = parser.parse() {
pub fn parse(toml: &str,
file: &Path,
config: &Config) -> CargoResult<toml::Table> {
let mut first_parser = toml::Parser::new(&toml);
if let Some(toml) = first_parser.parse() {
return Ok(toml);
}
let mut second_parser = toml::Parser::new(toml);
second_parser.set_require_newline_after_table(false);
if let Some(toml) = second_parser.parse() {
let msg = format!("\
TOML file found which contains invalid syntax and will soon not parse
at `{}`.
The TOML spec requires newlines after table definitions (e.g. `[a] b = 1` is
invalid), but this file has a table header which does not have a newline after
it. A newline needs to be added and this warning will soon become a hard error
in the future.", file.display());
try!(config.shell().warn(&msg));
return Ok(toml)
}
let mut error_str = format!("could not parse input as TOML\n");
for error in parser.errors.iter() {
let (loline, locol) = parser.to_linecol(error.lo);
let (hiline, hicol) = parser.to_linecol(error.hi);
for error in first_parser.errors.iter() {
let (loline, locol) = first_parser.to_linecol(error.lo);
let (hiline, hicol) = first_parser.to_linecol(error.hi);
error_str.push_str(&format!("{}:{}:{}{} {}\n",
file.display(),
loline + 1, locol + 1,

View file

@ -479,3 +479,30 @@ warning: dependency (foo) specified without providing a local path, Git reposito
to use. This will be considered an error in future versions
"));
}
#[test]
fn invalid_toml_historically_allowed_is_warned() {
let p = project("empty_deps")
.file("Cargo.toml", r#"
[package]
name = "empty_deps"
version = "0.0.0"
authors = []
"#)
.file(".cargo/config", r#"
[foo] bar = 2
"#)
.file("src/main.rs", "fn main() {}");
assert_that(p.cargo_process("build"),
execs().with_status(0).with_stderr("\
warning: TOML file found which contains invalid syntax and will soon not parse
at `[..]config`.
The TOML spec requires newlines after table definitions (e.g. `[a] b = 1` is
invalid), but this file has a table header which does not have a newline after
it. A newline needs to be added and this warning will soon become a hard error
in the future.
[COMPILING] empty_deps v0.0.0 ([..])
"));
}

View file

@ -256,8 +256,10 @@ fn no_rebuild_dependency() {
version = "0.5.0"
authors = ["wycats@example.com"]
[[bin]] name = "foo"
[dependencies.bar] path = "bar"
[[bin]]
name = "foo"
[dependencies.bar]
path = "bar"
"#)
.file("src/foo.rs", r#"
extern crate bar;
@ -270,7 +272,8 @@ fn no_rebuild_dependency() {
version = "0.5.0"
authors = ["wycats@example.com"]
[lib] name = "bar"
[lib]
name = "bar"
"#)
.file("bar/src/bar.rs", r#"
pub fn bar() {}