]> git.proxmox.com Git - cargo.git/commitdiff
Encoding and decoding now in libcargo
authorYehuda Katz <wycats@gmail.com>
Fri, 21 Mar 2014 00:55:33 +0000 (17:55 -0700)
committerYehuda Katz <wycats@gmail.com>
Fri, 21 Mar 2014 00:57:34 +0000 (17:57 -0700)
Commands can now call a simple function (execute_main) with some type
params, and get flags and stdin converted into their expected structs
automatically. Commands that return a json-serializable struct will also
get that struct automatically serialized into the output.

Additionally, error handling is now handled in a central location. If a
command returns a CargoError, its message will be printed (soon in
color!) and its exit code will be used to exit the process.

src/bin/cargo-read-manifest.rs
src/bin/cargo-rustc.rs
src/cargo/mod.rs

index ce2215c8a62bc29d49a7f07bad88413a3c134aa0..a5ed0e49accb48159bed8b3e35a9a008654d80f8 100644 (file)
@@ -8,9 +8,8 @@ extern crate toml;
 
 use hammer::FlagConfig;
 use serialize::Decoder;
-use serialize::json::Encoder;
 use toml::from_toml;
-use cargo::{Manifest,LibTarget,ExecTarget,Project,CargoResult,ToCargoError,execute_main};
+use cargo::{Manifest,LibTarget,ExecTarget,Project,CargoResult,ToCargoError,execute_main_without_stdin};
 use std::path::Path;
 
 #[deriving(Decodable,Encodable,Eq,Clone,Ord)]
@@ -38,10 +37,10 @@ struct ReadManifestFlags {
 impl FlagConfig for ReadManifestFlags {}
 
 fn main() {
-    execute_main::<ReadManifestFlags>(execute);
+    execute_main_without_stdin::<ReadManifestFlags, Manifest>(execute);
 }
 
-fn execute(flags: ReadManifestFlags) -> CargoResult<()> {
+fn execute(flags: ReadManifestFlags) -> CargoResult<Option<Manifest>> {
     let manifest_path = flags.manifest_path;
     let root = try!(toml::parse_from_file(manifest_path.clone()).to_cargo_error(format!("Couldn't parse Toml file: {}", manifest_path), 1));
 
@@ -49,18 +48,12 @@ fn execute(flags: ReadManifestFlags) -> CargoResult<()> {
 
     let (lib, bin) = normalize(&toml_manifest.lib, &toml_manifest.bin);
 
-    let manifest = Manifest{
+    Ok(Some(Manifest {
         root: try!(Path::new(manifest_path.clone()).dirname_str().to_cargo_error(format!("Could not get dirname from {}", manifest_path), 1)).to_owned(),
         project: toml_manifest.project,
         lib: lib,
         bin: bin
-    };
-
-    let encoded: ~str = Encoder::str_encode(&manifest);
-
-    println!("{}", encoded);
-
-    Ok(())
+    }))
 }
 
 fn normalize(lib: &Option<~[SerializedLibTarget]>, bin: &Option<~[SerializedExecTarget]>) -> (~[LibTarget], ~[ExecTarget]) {
index 8967c6ce2aa53ecdd0e145f744c0041feb7809be..3c0a9b0d7eba3a2d71a75ca02d245855d06bda12 100644 (file)
@@ -6,14 +6,11 @@ extern crate hammer;
 extern crate serialize;
 extern crate cargo;
 
-use hammer::FlagConfig;
 use std::os::args;
 use std::io;
 use std::io::process::{Process,ProcessConfig,InheritFd};
-use serialize::json;
-use serialize::Decodable;
 use std::path::Path;
-use cargo::{Manifest,CargoResult,CargoError,ToCargoError,execute_main};
+use cargo::{Manifest,CargoResult,CargoError,ToCargoError,NoFlags,execute_main};
 
 /**
     cargo-rustc -- ...args
@@ -22,22 +19,10 @@ use cargo::{Manifest,CargoResult,CargoError,ToCargoError,execute_main};
 */
 
 fn main() {
-    execute_main::<RustcFlags>(execute);
+    execute_main::<NoFlags, Manifest, Manifest>(execute);
 }
 
-#[deriving(Decodable,Eq,Clone,Ord)]
-struct RustcFlags;
-
-impl FlagConfig for RustcFlags {}
-
-fn execute(_: RustcFlags) -> CargoResult<()> {
-    let mut reader = io::stdin();
-    let input = try!(reader.read_to_str().to_cargo_error(~"Cannot read stdin to a string", 1));
-
-    let json = try!(json::from_str(input).to_cargo_error(format!("Cannot parse json: {}", input), 1));
-    let mut decoder = json::Decoder::new(json);
-    let manifest: Manifest = Decodable::decode(&mut decoder);
-
+fn execute(_: NoFlags, manifest: Manifest) -> CargoResult<Option<Manifest>> {
     let Manifest{ root, lib, bin, .. } = manifest;
 
     let (crate_type, out_dir) = if lib.len() > 0 {
@@ -78,7 +63,7 @@ fn execute(_: RustcFlags) -> CargoResult<()> {
         fail!("Failed to execute")
     }
 
-    Ok(())
+    Ok(None)
 }
 
 fn join(path: &Path, part: ~str) -> ~str {
index 33f5a0169cf1fe550e6aab1a5d02de376fab952b..30d21629576c0d4762778dd8d06a8cdbd5e05ee2 100644 (file)
@@ -6,7 +6,8 @@
 extern crate serialize;
 extern crate hammer;
 
-use serialize::{Decoder,Decodable};
+use serialize::{Decoder,Encoder,Decodable,Encodable,json};
+use std::io;
 use std::fmt;
 use std::fmt::{Show,Formatter};
 use hammer::{FlagDecoder,FlagConfig};
@@ -84,22 +85,54 @@ impl<T> ToCargoError<T> for Option<T> {
     }
 }
 
-pub fn execute_main<T: FlagConfig + Decodable<FlagDecoder>>(exec: fn(T) -> CargoResult<()>) {
-    fn call<T: FlagConfig + Decodable<FlagDecoder>>(exec: fn(T) -> CargoResult<()>) -> CargoResult<()> {
+trait RepresentsFlags : FlagConfig + Decodable<FlagDecoder> {}
+impl<T: FlagConfig + Decodable<FlagDecoder>> RepresentsFlags for T {}
+
+trait RepresentsJSON : Decodable<json::Decoder> {}
+impl <T: Decodable<json::Decoder>> RepresentsJSON for T {}
+
+#[deriving(Decodable)]
+pub struct NoFlags;
+
+impl FlagConfig for NoFlags {}
+
+pub fn execute_main<'a, T: RepresentsFlags, U: RepresentsJSON, V: Encodable<json::Encoder<'a>>>(exec: fn(T, U) -> CargoResult<Option<V>>) {
+    fn call<'a, T: RepresentsFlags, U: RepresentsJSON, V: Encodable<json::Encoder<'a>>>(exec: fn(T, U) -> CargoResult<Option<V>>) -> CargoResult<Option<V>> {
+        let flags = try!(flags_from_args::<T>());
+        let json = try!(json_from_stdin::<U>());
+
+        exec(flags, json)
+    }
+
+    process_executed(call(exec))
+}
+
+pub fn execute_main_without_stdin<'a, T: RepresentsFlags, V: Encodable<json::Encoder<'a>>>(exec: fn(T) -> CargoResult<Option<V>>) {
+    fn call<'a, T: RepresentsFlags, V: Encodable<json::Encoder<'a>>>(exec: fn(T) -> CargoResult<Option<V>>) -> CargoResult<Option<V>> {
         let flags = try!(flags_from_args::<T>());
+
         exec(flags)
     }
 
-    match call(exec) {
+    process_executed(call(exec))
+}
+
+fn process_executed<'a, T: Encodable<json::Encoder<'a>>>(result: CargoResult<Option<T>>) {
+    match result {
         Err(e) => {
             let _ = write!(&mut std::io::stderr(), "{}", e.message);
             std::os::set_exit_status(e.exit_code as int);
         },
-        Ok(_) => ()
+        Ok(encodable) => {
+            encodable.map(|encodable| {
+                let encoded: ~str = json::Encoder::str_encode(&encodable);
+                println!("{}", encoded);
+            });
+        }
     }
 }
 
-fn flags_from_args<T: FlagConfig + Decodable<FlagDecoder>>() -> CargoResult<T> {
+fn flags_from_args<T: RepresentsFlags>() -> CargoResult<T> {
     let mut decoder = FlagDecoder::new::<T>(std::os::args().tail());
     let flags: T = Decodable::decode(&mut decoder);
 
@@ -108,3 +141,13 @@ fn flags_from_args<T: FlagConfig + Decodable<FlagDecoder>>() -> CargoResult<T> {
         None => Ok(flags)
     }
 }
+
+fn json_from_stdin<T: RepresentsJSON>() -> CargoResult<T> {
+    let mut reader = io::stdin();
+    let input = try!(reader.read_to_str().to_cargo_error(~"Cannot read stdin to a string", 1));
+
+    let json = try!(json::from_str(input).to_cargo_error(format!("Cannot parse json: {}", input), 1));
+    let mut decoder = json::Decoder::new(json);
+
+    Ok(Decodable::decode(&mut decoder))
+}