Skip to content

Commit

Permalink
feat(CLI): engine checks resource and method args
Browse files Browse the repository at this point in the history
We are now at a spot where we can actually start parsing arguments.

* ArgumentError -> ClIError - seems more fitting

Fixes #55
  • Loading branch information
Byron committed Apr 14, 2015
1 parent e45eb05 commit be228f1
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 25 deletions.
3 changes: 3 additions & 0 deletions src/mako/cli/lib/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
44 changes: 39 additions & 5 deletions src/mako/cli/lib/engine.mako
Original file line number Diff line number Diff line change
@@ -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
%>\
Expand All @@ -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,
};
Expand All @@ -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>
16 changes: 10 additions & 6 deletions src/mako/cli/main.rs.mako
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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);
}
}
}
}
2 changes: 1 addition & 1 deletion src/rust/api/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ pub struct DefaultDelegate;
impl Delegate for DefaultDelegate {}



#[derive(Debug)]
pub enum Error {
/// The http connection failed
HttpError(hyper::HttpError),
Expand Down
26 changes: 13 additions & 13 deletions src/rust/cli/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand All @@ -86,24 +86,24 @@ 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,
}
}
}

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
Expand All @@ -115,19 +115,19 @@ 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))))
}
}

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)
)))
};
Expand Down Expand Up @@ -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())
)))
Expand Down

0 comments on commit be228f1

Please sign in to comment.