]> git.proxmox.com Git - cargo.git/commitdiff
Move from rust-toml to toml-rs
authorAlex Crichton <alex@alexcrichton.com>
Mon, 23 Jun 2014 15:39:50 +0000 (08:39 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 23 Jun 2014 18:38:53 +0000 (11:38 -0700)
This commit should greatly improve all error messages related to decoding
Cargo.toml.

12 files changed:
.gitmodules
Makefile
libs/rust-toml [deleted submodule]
libs/toml-rs [new submodule]
src/bin/cargo-verify-project.rs
src/bin/cargo.rs
src/cargo/lib.rs
src/cargo/util/config.rs
src/cargo/util/toml.rs
tests/test_cargo_compile.rs
tests/test_cargo_compile_git_deps.rs
tests/test_cargo_compile_path_deps.rs

index b6b1c7fd8b7d591524846eeb67f32fe52e835ad6..a433e13d204ceffa642640e32d5eed263f53a97f 100644 (file)
@@ -1,9 +1,9 @@
-[submodule "libs/rust-toml"]
-       path = libs/rust-toml
-       url = https://github.com/wycats/rust-toml
 [submodule "libs/hammer.rs"]
        path = libs/hammer.rs
        url = https://github.com/wycats/hammer.rs.git
 [submodule "libs/hamcrest-rust"]
        path = libs/hamcrest-rust
        url = https://github.com/carllerche/hamcrest-rust/
+[submodule "libs/toml-rs"]
+       path = libs/toml-rs
+       url = https://github.com/alexcrichton/toml-rs
index b6c08637fa5dcbad73bc013de742931335fb283f..3a2bfb371ffd9d38fb474fc769677ab7a8aae917 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,8 +11,8 @@ BINS = cargo \
 
 SRC = $(shell find src -name '*.rs' -not -path 'src/bin*')
 
-DEPS = -L libs/hammer.rs/target -L libs/rust-toml/lib
-TOML = libs/rust-toml/lib/$(shell rustc --crate-file-name libs/rust-toml/src/toml/lib.rs)
+DEPS = -L libs/hammer.rs/target -L libs/toml-rs/build
+TOML = libs/toml-rs/lib/$(shell rustc --crate-file-name libs/toml-rs/src/toml.rs)
 HAMMER = libs/hammer.rs/target/$(shell rustc --crate-type=lib --crate-file-name libs/hammer.rs/src/hammer.rs)
 HAMCREST = libs/hamcrest-rust/target/libhamcrest.timestamp
 LIBCARGO = target/libcargo.timestamp
@@ -25,8 +25,8 @@ all: $(BIN_TARGETS)
 $(HAMMER): $(wildcard libs/hammer.rs/src/*.rs)
        $(MAKE) -C libs/hammer.rs
 
-$(TOML): $(wildcard libs/rust-toml/src/toml/*.rs)
-       $(MAKE) -C libs/rust-toml
+$(TOML): $(wildcard libs/toml-rs/src/*.rs)
+       $(MAKE) -C libs/toml-rs
 
 $(HAMCREST): $(shell find libs/hamcrest-rust/src/hamcrest -name '*.rs')
        $(MAKE) -C libs/hamcrest-rust
@@ -71,7 +71,7 @@ clean:
 distclean: clean
        cd libs/hamcrest-rust && make clean
        cd libs/hammer.rs && make clean
-       cd libs/rust-toml && make clean
+       cd libs/toml-rs && make clean
 
 # Setup phony tasks
 .PHONY: all clean distclean test test-unit test-integration libcargo
diff --git a/libs/rust-toml b/libs/rust-toml
deleted file mode 160000 (submodule)
index 3eaa0ee..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 3eaa0ee4c81aa49bdcc98cad448ef3a6386d62af
diff --git a/libs/toml-rs b/libs/toml-rs
new file mode 160000 (submodule)
index 0000000..ed88ef0
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit ed88ef0b8151277cc6a876f2daaeb1c63420717b
index 13f860b29805b17a5501f424c7cc2b61dbfdb26d..a013b035fa121c45cefb0ec3235df3beecb7e8c7 100644 (file)
@@ -1,10 +1,11 @@
 #![crate_id="cargo-verify-project"]
 
-extern crate toml = "github.com/mneumann/rust-toml#toml";
+extern crate toml;
 extern crate getopts;
 
-use std::os::{args,set_exit_status};
-use getopts::{reqopt,getopts};
+use std::io::File;
+use std::os::{args, set_exit_status};
+use getopts::{reqopt, getopts};
 
 /**
     cargo-verify-project --manifest=LOCATION
@@ -32,18 +33,17 @@ fn main() {
 
     let manifest = matches.opt_str("m").unwrap();
     let file = Path::new(manifest);
-
-    if !file.exists() {
-        fail("invalid", "not-found");
-        return;
-    }
-
-    match toml::parse_from_file(file.as_str().unwrap()) {
-        Err(_) => {
+    let contents = match File::open(&file).read_to_str() {
+        Ok(s) => s,
+        Err(e) => return fail("invalid", format!("error reading file: {}",
+                                                 e).as_slice())
+    };
+    match toml::Parser::new(contents.as_slice()).parse() {
+        None => {
             fail("invalid", "invalid-format");
             return;
         },
-        Ok(r) => r
+        Some(..) => {}
     };
 
     println!("{}", "{ \"success\": \"true\" }");
index 8873a9a030b53d74bbe29167d7b78bd3fb53c068..0508d556a230ddec5530961d12ef64114fd976d6 100644 (file)
@@ -1,7 +1,6 @@
 #![feature(phase)]
 
 extern crate cargo;
-extern crate toml = "github.com/mneumann/rust-toml#toml";
 extern crate hammer;
 extern crate serialize;
 #[phase(plugin, link)]
index bee98bdab04085fcfc3944e3944367f2c056e6b0..ccae60e3a8777d7eb47766991288bfb1f9d630b3 100644 (file)
@@ -8,7 +8,7 @@ extern crate term;
 extern crate url;
 extern crate serialize;
 extern crate semver;
-extern crate toml = "github.com/mneumann/rust-toml#toml";
+extern crate toml;
 
 #[phase(plugin, link)]
 extern crate hammer;
index 24fb603e65521bbd49c72b4060344200d467a7f1..9dcad1175e337cac48f206c63d9275c3c483a2c5 100644 (file)
@@ -5,6 +5,8 @@ use toml;
 use core::MultiShell;
 use util::{CargoResult, CargoError, ChainError, Require, internal, human};
 
+use cargo_toml = util::toml;
+
 pub struct Config<'a> {
     home_path: Path,
     shell: &'a mut MultiShell
@@ -164,11 +166,12 @@ fn walk_tree(pwd: &Path,
     Ok(())
 }
 
-fn extract_config(file: io::fs::File, key: &str) -> CargoResult<ConfigValue> {
-    let path = file.path().clone();
-    let mut buf = io::BufferedReader::new(file);
-    let root = try!(toml::parse_from_buffer(&mut buf));
-    let val = try!(root.lookup(key).require(|| internal("")));
+fn extract_config(mut file: io::fs::File, key: &str) -> CargoResult<ConfigValue> {
+    let contents = try!(file.read_to_str());
+    let toml = try!(cargo_toml::parse(contents.as_slice(),
+                                      file.path().filename_display()
+                                          .to_str().as_slice()));
+    let val = try!(toml.find_equiv(&key).require(|| internal("")));
 
     let v = match *val {
         toml::String(ref val) => String(val.clone()),
@@ -178,19 +181,16 @@ fn extract_config(file: io::fs::File, key: &str) -> CargoResult<ConfigValue> {
         _ => return Err(internal(""))
     };
 
-    Ok(ConfigValue{ value: v, path: vec!(path) })
+    Ok(ConfigValue{ value: v, path: vec![file.path().clone()] })
 }
 
-fn extract_all_configs(file: io::fs::File,
+fn extract_all_configs(mut file: io::fs::File,
                        map: &mut HashMap<String, ConfigValue>) -> CargoResult<()> {
     let path = file.path().clone();
-    let mut buf = io::BufferedReader::new(file);
-    let root = try!(toml::parse_from_buffer(&mut buf).chain_error(|| {
-        internal(format!("could not parse Toml manifest; path={}",
-                         path.display()))
-    }));
-
-    let table = try!(root.get_table().require(|| {
+    let contents = try!(file.read_to_str());
+    let file = path.filename_display().to_str();
+    let table = try!(cargo_toml::parse(contents.as_slice(),
+                                       file.as_slice()).chain_error(|| {
         internal(format!("could not parse Toml manifest; path={}",
                          path.display()))
     }));
index 36612ff554abf6847f3f89066819bf1ff5a23e5a..cf1c0158ee96227662821404a83850521e49ae91 100644 (file)
@@ -1,8 +1,9 @@
+use serialize::Decodable;
+use std::collections::HashMap;
+use std::str;
 use toml;
-use url;
 use url::Url;
-use std::collections::HashMap;
-use serialize::Decodable;
+use url;
 
 use core::{SourceId,GitKind};
 use core::manifest::{LibKind,Lib};
@@ -11,84 +12,43 @@ use util::{CargoResult, Require, human};
 
 pub fn to_manifest(contents: &[u8],
                    source_id: &SourceId) -> CargoResult<(Manifest, Vec<Path>)> {
-    let root = try!(toml::parse_from_bytes(contents).map_err(|_| {
-        human("Cargo.toml is not valid Toml")
-    }));
-    let toml = try!(toml_to_manifest(root).map_err(|_| {
-        human("Cargo.toml is not a valid manifest")
+    let contents = try!(str::from_utf8(contents).require(|| {
+        human("Cargo.toml is not valid UTF-8")
     }));
+    let root = try!(parse(contents, "Cargo.toml"));
+    let mut d = toml::Decoder::new(toml::Table(root));
+    let toml_manifest: TomlManifest = match Decodable::decode(&mut d) {
+        Ok(t) => t,
+        Err(e) => return Err(human(format!("Cargo.toml is not a valid \
+                                            manifest\n\n{}", e)))
+    };
 
-    toml.to_manifest(source_id)
+    toml_manifest.to_manifest(source_id)
 }
 
-fn toml_to_manifest(root: toml::Value) -> CargoResult<TomlManifest> {
-    fn decode<T: Decodable<toml::Decoder,toml::Error>>(root: &toml::Value,
-                                                       path: &str)
-        -> Result<T, toml::Error>
-    {
-        let root = match root.lookup(path) {
-            Some(val) => val,
-            None => return Err(toml::ParseError)
-        };
-        toml::from_toml(root.clone())
-    }
-
-    let project = try!(decode(&root, "project"));
-    let lib = decode(&root, "lib").ok();
-    let bin = decode(&root, "bin").ok();
-
-    let deps = root.lookup("dependencies");
-
-    let deps = match deps {
-        Some(deps) => {
-            let table = try!(deps.get_table().require(|| {
-                human("dependencies must be a table")
-            })).clone();
-
-            let mut deps: HashMap<String, TomlDependency> = HashMap::new();
-
-            for (k, v) in table.iter() {
-                match v {
-                    &toml::String(ref string) => {
-                        deps.insert(k.clone(), SimpleDep(string.clone()));
-                    },
-                    &toml::Table(ref table) => {
-                        let mut details = HashMap::<String, String>::new();
-
-                        for (k, v) in table.iter() {
-                            let v = try!(v.get_str().require(|| {
-                                human("dependency values must be string")
-                            }));
-
-                            details.insert(k.clone(), v.clone());
-                        }
-
-                        let version = try!(details.find_equiv(&"version")
-                                           .require(|| {
-                            human("dependencies must include a version")
-                        })).clone();
-
-                        deps.insert(k.clone(),
-                                    DetailedDep(DetailedTomlDependency {
-                            version: version,
-                            other: details
-                        }));
-                    },
-                    _ => ()
-                }
+pub fn parse(toml: &str, file: &str) -> CargoResult<toml::Table> {
+    let mut parser = toml::Parser::new(toml.as_slice());
+    match parser.parse() {
+        Some(toml) => Ok(toml),
+        None => {
+            let mut error_str = format!("could not parse input TOML\n");
+            for error in parser.errors.iter() {
+                let (loline, locol) = parser.to_linecol(error.lo);
+                let (hiline, hicol) = parser.to_linecol(error.hi);
+                error_str.push_str(format!("{}:{}:{}{} {}",
+                                           file,
+                                           loline + 1, locol + 1,
+                                           if loline != hiline || locol != hicol {
+                                               format!("-{}:{}", hiline + 1,
+                                                       hicol + 1)
+                                           } else {
+                                               "".to_string()
+                                           },
+                                           error.desc).as_slice());
             }
-
-            Some(deps)
-        },
-        None => None
-    };
-
-    Ok(TomlManifest {
-        project: box project,
-        lib: lib,
-        bin: bin,
-        dependencies: deps,
-    })
+            Err(human(error_str))
+        }
+    }
 }
 
 type TomlLibTarget = TomlTarget;
@@ -98,19 +58,20 @@ type TomlBinTarget = TomlTarget;
  * TODO: Make all struct fields private
  */
 
-#[deriving(Encodable,PartialEq,Clone,Show)]
+#[deriving(Encodable,Decodable,PartialEq,Clone,Show)]
 pub enum TomlDependency {
     SimpleDep(String),
     DetailedDep(DetailedTomlDependency)
 }
 
-#[deriving(Encodable,PartialEq,Clone,Show)]
+#[deriving(Encodable,Decodable,PartialEq,Clone,Show)]
 pub struct DetailedTomlDependency {
     version: String,
-    other: HashMap<String, String>
+    path: Option<String>,
+    git: Option<String>,
 }
 
-#[deriving(Encodable,PartialEq,Clone)]
+#[deriving(Encodable,Decodable,PartialEq,Clone)]
 pub struct TomlManifest {
     project: Box<TomlProject>,
     lib: Option<Vec<TomlLibTarget>>,
@@ -158,8 +119,7 @@ impl TomlManifest {
                             (string.clone(), SourceId::for_central())
                         },
                         DetailedDep(ref details) => {
-                            let new_source_id = details.other.find_equiv(&"git");
-                            let new_source_id = new_source_id.map(|git| {
+                            let new_source_id = details.git.as_ref().map(|git| {
                                 // TODO: Don't unwrap here
                                 let kind = GitKind("master".to_str());
                                 let url = url::from_str(git.as_slice()).unwrap();
@@ -168,7 +128,7 @@ impl TomlManifest {
                                 sources.push(source_id.clone());
                                 source_id
                             }).or_else(|| {
-                                details.other.find_equiv(&"path").map(|path| {
+                                details.path.as_ref().map(|path| {
                                     nested_paths.push(Path::new(path.as_slice()));
                                     source_id.clone()
                                 })
index 89a0c400c623b481ab66604d49552b1b0d61f274..0b8be0617843dc27388ab96307c7553c30566ed0 100644 (file)
@@ -47,7 +47,22 @@ test!(cargo_compile_with_invalid_manifest {
     assert_that(p.cargo_process("cargo-compile"),
         execs()
         .with_status(101)
-        .with_stderr("Cargo.toml is not a valid manifest\n"));
+        .with_stderr("Cargo.toml is not a valid manifest\n\n\
+                      expected a section for the key `project`\n"))
+})
+
+test!(cargo_compile_with_invalid_manifest2 {
+    let p = project("foo")
+        .file("Cargo.toml", r"
+            [project]
+            foo = bar
+        ");
+
+    assert_that(p.cargo_process("cargo-compile"),
+        execs()
+        .with_status(101)
+        .with_stderr("could not parse input TOML\n\
+                      Cargo.toml:3:19-3:20 expected a value\n"))
 })
 
 test!(cargo_compile_without_manifest {
@@ -250,9 +265,9 @@ test!(cargo_compile_with_nested_deps_longhand {
             version = "0.5.0"
             authors = ["wycats@example.com"]
 
-            [dependencies.bar]
+            [dependencies]
 
-            version = "0.5.0"
+            bar = "0.5.0"
 
             [[bin]]
 
@@ -473,7 +488,7 @@ test!(custom_build_in_dependency {
             authors = ["wycats@example.com"]
 
             [[bin]] name = "foo"
-            [dependencies.bar] version = "0.5.0"
+            [dependencies] bar = "0.5.0"
         "#)
         .file("src/foo.rs", r#"
             extern crate bar;
index 48907e5f88a81718b7ae98ed5263aef1ea34092a..3ffa6e7e96ec42e547ebe971f7ddbb121d904b50 100644 (file)
@@ -187,7 +187,8 @@ test!(recompilation {
                 version = "0.5.0"
                 authors = ["carlhuda@example.com"]
 
-                [[lib]] name = "bar"
+                [[lib]]
+                name = "bar"
             "#)
             .file("src/bar.rs", r#"
                 pub fn bar() {}
index c8072a261c57d8d1495b7952ce9ec9bfacc83313..f994e03719e0bcf5e5ed03a44ae1036e7077f726 100644 (file)
@@ -98,7 +98,7 @@ test!(no_rebuild_dependency {
             authors = ["wycats@example.com"]
 
             [[bin]] name = "foo"
-            [dependencies.bar] version = "0.5.0"
+            [dependencies] bar = "0.5.0"
         "#)
         .file("src/foo.rs", r#"
             extern crate bar;
@@ -152,8 +152,10 @@ test!(deep_dependencies_trigger_rebuild {
             version = "0.5.0"
             authors = ["wycats@example.com"]
 
-            [[bin]] name = "foo"
-            [dependencies.bar] version = "0.5.0"
+            [[bin]]
+            name = "foo"
+            [dependencies]
+            bar = "0.5.0"
         "#)
         .file("src/foo.rs", r#"
             extern crate bar;
@@ -166,8 +168,10 @@ test!(deep_dependencies_trigger_rebuild {
             version = "0.5.0"
             authors = ["wycats@example.com"]
 
-            [[lib]] name = "bar"
-            [dependencies.baz] version = "0.5.0"
+            [[lib]]
+            name = "bar"
+            [dependencies]
+            baz = "0.5.0"
         "#)
         .file("bar/src/bar.rs", r#"
             extern crate baz;
@@ -180,7 +184,8 @@ test!(deep_dependencies_trigger_rebuild {
             version = "0.5.0"
             authors = ["wycats@example.com"]
 
-            [[lib]] name = "baz"
+            [[lib]]
+            name = "baz"
         "#)
         .file("baz/src/baz.rs", r#"
             pub fn baz() {}
@@ -246,9 +251,11 @@ test!(no_rebuild_two_deps {
             version = "0.5.0"
             authors = ["wycats@example.com"]
 
-            [[bin]] name = "foo"
-            [dependencies.bar] version = "0.5.0"
-            [dependencies.baz] version = "0.5.0"
+            [[bin]]
+            name = "foo"
+            [dependencies]
+            bar = "0.5.0"
+            baz = "0.5.0"
         "#)
         .file("src/foo.rs", r#"
             extern crate bar;
@@ -261,8 +268,10 @@ test!(no_rebuild_two_deps {
             version = "0.5.0"
             authors = ["wycats@example.com"]
 
-            [[lib]] name = "bar"
-            [dependencies.baz] version = "0.5.0"
+            [[lib]]
+            name = "bar"
+            [dependencies]
+            baz = "0.5.0"
         "#)
         .file("bar/src/bar.rs", r#"
             pub fn bar() {}
@@ -274,7 +283,8 @@ test!(no_rebuild_two_deps {
             version = "0.5.0"
             authors = ["wycats@example.com"]
 
-            [[lib]] name = "baz"
+            [[lib]]
+            name = "baz"
         "#)
         .file("baz/src/baz.rs", r#"
             pub fn baz() {}