mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
Encoding and decoding now in libcargo
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.
This commit is contained in:
parent
aec45be721
commit
1b1044b639
@ -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]) {
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user