mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-01-07 03:56:42 +01:00
feat(CLI): engine checks resource and method args
We are now at a spot where we can actually start parsing arguments. * ArgumentError -> ClIError - seems more fitting Fixes #55
This commit is contained in:
@@ -74,6 +74,9 @@ def is_request_value_property(mc, p):
|
||||
def mangle_subcommand(name):
|
||||
return util.camel_to_under(name).replace('_', '-').replace('.', '-')
|
||||
|
||||
# return the identifier of a command for the given name, suitable to address the command field in the docopt structure
|
||||
def cmd_ident(name):
|
||||
return 'cmd_' + mangle_subcommand(name).replace('-', '_')
|
||||
|
||||
# transform the resource name into a suitable filename to contain the markdown documentation for it
|
||||
def subcommand_md_filename(resource, method):
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<%namespace name="util" file="../../lib/util.mako"/>\
|
||||
<%!
|
||||
from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG,
|
||||
CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG)
|
||||
CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG,
|
||||
cmd_ident)
|
||||
|
||||
v_arg = '<%s>' % VALUE_ARG
|
||||
%>\
|
||||
@@ -12,16 +13,16 @@ use cmn::InvalidOptionsError;
|
||||
use oauth2::ApplicationSecret;
|
||||
|
||||
struct Engine {
|
||||
opts: Options,
|
||||
config_dir: String,
|
||||
secret: ApplicationSecret,
|
||||
}
|
||||
|
||||
|
||||
impl Engine {
|
||||
fn new(options: Options) -> Result<Engine, InvalidOptionsError> {
|
||||
// Please note that this call will fail if any part of the opt can't be handled
|
||||
fn new(opt: Options) -> Result<Engine, InvalidOptionsError> {
|
||||
let (config_dir, secret) = {
|
||||
let config_dir = match cmn::assure_config_dir_exists(&options.flag_config_dir) {
|
||||
let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) {
|
||||
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
|
||||
Ok(p) => p,
|
||||
};
|
||||
@@ -32,13 +33,46 @@ impl Engine {
|
||||
}
|
||||
};
|
||||
|
||||
## RESOURCE LOOP: check for set primary subcommand
|
||||
% for resource in sorted(c.rta_map.keys()):
|
||||
% if loop.first:
|
||||
if \
|
||||
% else:
|
||||
else if \
|
||||
% endif
|
||||
opt.${cmd_ident(resource)} {
|
||||
## METHOD LOOP: Check for method subcommand
|
||||
% for method in sorted(c.rta_map[resource]):
|
||||
% if loop.first:
|
||||
if \
|
||||
% else:
|
||||
else if \
|
||||
% endif
|
||||
opt.${cmd_ident(method)} {
|
||||
|
||||
}\
|
||||
% endfor # each method
|
||||
else {
|
||||
unreachable!();
|
||||
}
|
||||
}\
|
||||
% endfor # each resource
|
||||
else {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
let mut engine = Engine {
|
||||
opts: options,
|
||||
config_dir: config_dir,
|
||||
secret: secret,
|
||||
};
|
||||
|
||||
Ok(engine)
|
||||
}
|
||||
|
||||
// Execute the call with all the bells and whistles, informing the caller only if there was an error.
|
||||
// The absense of one indicates success.
|
||||
fn doit(&self) -> Option<api::Error> {
|
||||
None
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
@@ -2,7 +2,7 @@
|
||||
<%namespace name="engine" file="lib/engine.mako"/>\
|
||||
<%namespace name="util" file="../lib/util.mako"/>\
|
||||
<%
|
||||
from util import (new_context, rust_comment)
|
||||
from util import (new_context, rust_comment, to_extern_crate_name, library_to_crate_name, library_name)
|
||||
|
||||
c = new_context(schemas, resources, context.get('methods'))
|
||||
default_user_agent = "google-cli-rust-client/" + cargo.build_version
|
||||
@@ -16,6 +16,7 @@
|
||||
extern crate docopt;
|
||||
extern crate yup_oauth2 as oauth2;
|
||||
extern crate rustc_serialize;
|
||||
extern crate ${to_extern_crate_name(library_to_crate_name(library_name(name, version), make.depends_on_suffix))} as api;
|
||||
|
||||
use std::io;
|
||||
use std::env;
|
||||
@@ -29,12 +30,15 @@ fn main() {
|
||||
let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit());
|
||||
println!("{:?}", opts);
|
||||
match Engine::new(opts) {
|
||||
Err(e) => {
|
||||
write!(io::stderr(), "{}", e).ok();
|
||||
env::set_exit_status(e.exit_code);
|
||||
Err(err) => {
|
||||
write!(io::stderr(), "{}", err).ok();
|
||||
env::set_exit_status(err.exit_code);
|
||||
},
|
||||
Ok(mut engine) => {
|
||||
|
||||
Ok(engine) => {
|
||||
if let Some(err) = engine.doit() {
|
||||
write!(io::stderr(), "TODO: display {:?}", err).ok();
|
||||
env::set_exit_status(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,7 +215,7 @@ pub struct DefaultDelegate;
|
||||
impl Delegate for DefaultDelegate {}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// The http connection failed
|
||||
HttpError(hyper::HttpError),
|
||||
|
||||
@@ -58,21 +58,21 @@ impl fmt::Display for ConfigurationError {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ArgumentError {
|
||||
pub enum CLIError {
|
||||
Configuration(ConfigurationError),
|
||||
}
|
||||
|
||||
impl fmt::Display for ArgumentError {
|
||||
impl fmt::Display for CLIError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
ArgumentError::Configuration(ref err) => writeln!(f, "Configuration -> {}", err)
|
||||
CLIError::Configuration(ref err) => writeln!(f, "Configuration -> {}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InvalidOptionsError {
|
||||
pub issues: Vec<ArgumentError>,
|
||||
pub issues: Vec<CLIError>,
|
||||
pub exit_code: i32,
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ impl fmt::Display for InvalidOptionsError {
|
||||
}
|
||||
|
||||
impl InvalidOptionsError {
|
||||
pub fn single(err: ArgumentError, exit_code: i32) -> InvalidOptionsError {
|
||||
pub fn single(err: CLIError, exit_code: i32) -> InvalidOptionsError {
|
||||
InvalidOptionsError {
|
||||
issues: vec![err],
|
||||
exit_code: exit_code,
|
||||
@@ -94,16 +94,16 @@ impl InvalidOptionsError {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assure_config_dir_exists(dir: &str) -> Result<String, ArgumentError> {
|
||||
pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> {
|
||||
let trdir = dir.trim();
|
||||
if trdir.len() == 0 {
|
||||
return Err(ArgumentError::Configuration(ConfigurationError::DirectoryUnset))
|
||||
return Err(CLIError::Configuration(ConfigurationError::DirectoryUnset))
|
||||
}
|
||||
|
||||
let expanded_config_dir =
|
||||
if trdir.as_bytes()[0] == b'~' {
|
||||
match env::var("HOME").ok().or(env::var("UserProfile").ok()) {
|
||||
None => return Err(ArgumentError::Configuration(ConfigurationError::HomeExpansionFailed(trdir.to_string()))),
|
||||
None => return Err(CLIError::Configuration(ConfigurationError::HomeExpansionFailed(trdir.to_string()))),
|
||||
Some(mut user) => {
|
||||
user.push_str(&trdir[1..]);
|
||||
user
|
||||
@@ -115,7 +115,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, ArgumentError> {
|
||||
|
||||
if let Err(err) = fs::create_dir(&expanded_config_dir) {
|
||||
if err.kind() != io::ErrorKind::AlreadyExists {
|
||||
return Err(ArgumentError::Configuration(
|
||||
return Err(CLIError::Configuration(
|
||||
ConfigurationError::DirectoryCreationFailed((expanded_config_dir, err))))
|
||||
}
|
||||
}
|
||||
@@ -123,11 +123,11 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, ArgumentError> {
|
||||
Ok(expanded_config_dir)
|
||||
}
|
||||
|
||||
pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Result<ApplicationSecret, ArgumentError> {
|
||||
pub fn application_secret_from_directory(dir: &str, secret_basename: &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();
|
||||
let secret_io_error = |io_err: io::Error| {
|
||||
Err(ArgumentError::Configuration(ConfigurationError::IOError(
|
||||
Err(CLIError::Configuration(ConfigurationError::IOError(
|
||||
(secret_str(), io_err)
|
||||
)))
|
||||
};
|
||||
@@ -173,14 +173,14 @@ pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Re
|
||||
return secret_io_error(io_err)
|
||||
}
|
||||
match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) {
|
||||
Err(json_decode_error) => return Err(ArgumentError::Configuration(
|
||||
Err(json_decode_error) => return Err(CLIError::Configuration(
|
||||
ConfigurationError::Secret(ApplicationSecretError::DecoderError(
|
||||
(secret_str(), json_decode_error)
|
||||
)))),
|
||||
Ok(console_secret) => match console_secret.installed {
|
||||
Some(secret) => return Ok(secret),
|
||||
None => return Err(
|
||||
ArgumentError::Configuration(
|
||||
CLIError::Configuration(
|
||||
ConfigurationError::Secret(
|
||||
ApplicationSecretError::FormatError(secret_str())
|
||||
)))
|
||||
|
||||
Reference in New Issue
Block a user