fix(CLI): added latest reference CLI code

Just to have something to link to
This commit is contained in:
Sebastian Thiel
2015-05-02 10:22:55 +02:00
parent 89432cc646
commit d2a4e2ff8b
26 changed files with 16333 additions and 4482 deletions

View File

@@ -1,8 +1,9 @@
// COPY OF 'src/rust/cli/cmn.rs'
// DO NOT EDIT
use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token};
use rustc_serialize::json;
use serde::json;
use mime::Mime;
use clap::{App, SubCommand};
use std::fs;
use std::env;
@@ -17,6 +18,46 @@ use std::default::Default;
const FIELD_SEP: char = '.';
pub enum CallType {
Upload(UploadProtocol),
Standard,
}
pub enum UploadProtocol {
Simple,
Resumable,
}
impl AsRef<str> for UploadProtocol {
fn as_ref(&self) -> &str {
match *self {
UploadProtocol::Simple => "simple",
UploadProtocol::Resumable => "resumable"
}
}
}
impl AsRef<str> for CallType {
fn as_ref(&self) -> &str {
match *self {
CallType::Upload(ref proto) => proto.as_ref(),
CallType::Standard => "standard-request"
}
}
}
impl FromStr for UploadProtocol {
type Err = String;
fn from_str(s: &str) -> Result<UploadProtocol, String> {
match s {
"simple" => Ok(UploadProtocol::Simple),
"resumable" => Ok(UploadProtocol::Resumable),
_ => Err(format!("Protocol '{}' is unknown", s)),
}
}
}
#[derive(Clone, Default)]
pub struct FieldCursor(Vec<String>);
@@ -112,6 +153,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap:
}
}
pub fn protocol_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType {
CallType::Upload(
match UploadProtocol::from_str(name) {
Ok(up) => up,
Err(msg) => {
err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols));
UploadProtocol::Simple
}
})
}
pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> {
match fs::File::open(file_path) {
Ok(f) => Some(f),
@@ -132,13 +184,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option
}
}
// May panic if we can't open the file - this is anticipated, we can't currently communicate this
// kind of error: TODO: fix this architecture :)
pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> {
if !flag || arg == "-" {
Box::new(stdout())
} else {
Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap())
pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> {
let f = arg.unwrap_or("-");
match f {
"-" => Ok(Box::new(stdout())),
_ => match fs::OpenOptions::new().create(true).write(true).open(f) {
Ok(f) => Ok(Box::new(f)),
Err(io_err) => Err(io_err),
}
}
}
@@ -151,7 +204,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError,
match FromStr::from_str(arg) {
Err(perr) => {
err.issues.push(
CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr)))
CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr))
);
Default::default()
},
@@ -171,49 +224,47 @@ impl JsonTokenStorage {
}
impl TokenStorage for JsonTokenStorage {
type Error = io::Error;
type Error = json::Error;
// NOTE: logging might be interesting, currently we swallow all errors
fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> {
fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> {
match token {
None => {
match fs::remove_file(self.path(scope_hash)) {
Err(err) =>
match err.kind() {
io::ErrorKind::NotFound => None,
_ => Some(err)
io::ErrorKind::NotFound => Ok(()),
_ => Err(json::Error::IoError(err))
},
Ok(_) => None
Ok(_) => Ok(()),
}
}
Some(token) => {
let json_token = json::encode(&token).unwrap();
match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) {
Ok(mut f) => {
match f.write(json_token.as_bytes()) {
Ok(_) => None,
Err(io_err) => Some(io_err),
match json::to_writer_pretty(&mut f, &token) {
Ok(_) => Ok(()),
Err(io_err) => Err(json::Error::IoError(io_err)),
}
},
Err(io_err) => Some(io_err)
Err(io_err) => Err(json::Error::IoError(io_err))
}
}
}
}
fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> {
fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> {
match fs::File::open(&self.path(scope_hash)) {
Ok(mut f) => {
let mut json_string = String::new();
match f.read_to_string(&mut json_string) {
Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())),
Err(io_err) => Err(io_err),
match json::de::from_reader(f) {
Ok(token) => Ok(Some(token)),
Err(err) => Err(err),
}
},
Err(io_err) => {
match io_err.kind() {
io::ErrorKind::NotFound => Ok(None),
_ => Err(io_err)
_ => Err(json::Error::IoError(io_err))
}
}
}
@@ -223,7 +274,7 @@ impl TokenStorage for JsonTokenStorage {
#[derive(Debug)]
pub enum ApplicationSecretError {
DecoderError((String, json::DecoderError)),
DecoderError((String, json::Error)),
FormatError(String),
}
@@ -311,11 +362,14 @@ impl fmt::Display for FieldError {
#[derive(Debug)]
pub enum CLIError {
Configuration(ConfigurationError),
ParseError((&'static str, &'static str, String, String)),
ParseError(&'static str, &'static str, String, String),
UnknownParameter(String),
InvalidUploadProtocol(String, Vec<String>),
InvalidKeyValueSyntax(String, bool),
Input(InputError),
Field(FieldError),
MissingCommandError,
MissingMethodError(String),
}
impl fmt::Display for CLIError {
@@ -324,7 +378,9 @@ impl fmt::Display for CLIError {
CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err),
CLIError::Input(ref err) => write!(f, "Input -> {}", err),
CLIError::Field(ref err) => write!(f, "Field -> {}", err),
CLIError::ParseError((arg_name, type_name, ref value, ref err_desc))
CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names)
=> writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}", proto_name, valid_names.connect(", ")),
CLIError::ParseError(arg_name, type_name, ref value, ref err_desc)
=> writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}",
arg_name, value, type_name, err_desc),
CLIError::UnknownParameter(ref param_name)
@@ -333,6 +389,8 @@ impl fmt::Display for CLIError {
let hashmap_info = if is_hashmap { "hashmap " } else { "" };
writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info)
},
CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command"),
CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command", cmd),
}
}
}
@@ -399,7 +457,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> {
pub fn application_secret_from_directory(dir: &str,
secret_basename: &str,
json_app_secret: &str)
json_console_secret: &str)
-> Result<ApplicationSecret, CLIError> {
let secret_path = Path::new(dir).join(secret_basename);
let secret_str = || secret_path.as_path().to_str().unwrap().to_string();
@@ -418,7 +476,10 @@ pub fn application_secret_from_directory(dir: &str,
err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) {
Err(cfe) => cfe,
Ok(mut f) => {
match f.write(json_app_secret.as_bytes()) {
// Assure we convert 'ugly' json string into pretty one
let console_secret: ConsoleApplicationSecret
= json::from_str(json_console_secret).unwrap();
match json::to_writer_pretty(&mut f, &console_secret) {
Err(io_err) => io_err,
Ok(_) => continue,
}
@@ -429,23 +490,24 @@ pub fn application_secret_from_directory(dir: &str,
return secret_io_error(err)
},
Ok(mut f) => {
let mut json_encoded_secret = String::new();
if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) {
return secret_io_error(io_err)
}
match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) {
Err(json_decode_error) => return Err(CLIError::Configuration(
ConfigurationError::Secret(ApplicationSecretError::DecoderError(
(secret_str(), json_decode_error)
match json::de::from_reader::<_, ConsoleApplicationSecret>(f) {
Err(json::Error::IoError(err)) =>
return secret_io_error(err),
Err(json_err) =>
return Err(CLIError::Configuration(
ConfigurationError::Secret(
ApplicationSecretError::DecoderError(
(secret_str(), json_err)
)))),
Ok(console_secret) => match console_secret.installed {
Some(secret) => return Ok(secret),
None => return Err(
CLIError::Configuration(
ConfigurationError::Secret(
ApplicationSecretError::FormatError(secret_str())
)))
},
Ok(console_secret) =>
match console_secret.installed {
Some(secret) => return Ok(secret),
None => return Err(
CLIError::Configuration(
ConfigurationError::Secret(
ApplicationSecretError::FormatError(secret_str())
)))
},
}
}
}