Skip to content

Commit be228f1

Browse files
committed
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
1 parent e45eb05 commit be228f1

5 files changed

Lines changed: 66 additions & 25 deletions

File tree

src/mako/cli/lib/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ def is_request_value_property(mc, p):
7474
def mangle_subcommand(name):
7575
return util.camel_to_under(name).replace('_', '-').replace('.', '-')
7676

77+
# return the identifier of a command for the given name, suitable to address the command field in the docopt structure
78+
def cmd_ident(name):
79+
return 'cmd_' + mangle_subcommand(name).replace('-', '_')
7780

7881
# transform the resource name into a suitable filename to contain the markdown documentation for it
7982
def subcommand_md_filename(resource, method):

src/mako/cli/lib/engine.mako

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<%namespace name="util" file="../../lib/util.mako"/>\
22
<%!
33
from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG,
4-
CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG)
4+
CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG,
5+
cmd_ident)
56
67
v_arg = '<%s>' % VALUE_ARG
78
%>\
@@ -12,16 +13,16 @@ use cmn::InvalidOptionsError;
1213
use oauth2::ApplicationSecret;
1314
1415
struct Engine {
15-
opts: Options,
1616
config_dir: String,
1717
secret: ApplicationSecret,
1818
}
1919
2020
2121
impl Engine {
22-
fn new(options: Options) -> Result<Engine, InvalidOptionsError> {
22+
// Please note that this call will fail if any part of the opt can't be handled
23+
fn new(opt: Options) -> Result<Engine, InvalidOptionsError> {
2324
let (config_dir, secret) = {
24-
let config_dir = match cmn::assure_config_dir_exists(&options.flag_config_dir) {
25+
let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) {
2526
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
2627
Ok(p) => p,
2728
};
@@ -32,13 +33,46 @@ impl Engine {
3233
}
3334
};
3435
36+
## RESOURCE LOOP: check for set primary subcommand
37+
% for resource in sorted(c.rta_map.keys()):
38+
% if loop.first:
39+
if \
40+
% else:
41+
else if \
42+
% endif
43+
opt.${cmd_ident(resource)} {
44+
## METHOD LOOP: Check for method subcommand
45+
% for method in sorted(c.rta_map[resource]):
46+
% if loop.first:
47+
if \
48+
% else:
49+
else if \
50+
% endif
51+
opt.${cmd_ident(method)} {
52+
53+
}\
54+
% endfor # each method
55+
else {
56+
unreachable!();
57+
}
58+
}\
59+
% endfor # each resource
60+
else {
61+
unreachable!();
62+
}
63+
3564
let mut engine = Engine {
36-
opts: options,
3765
config_dir: config_dir,
3866
secret: secret,
3967
};
4068
4169
Ok(engine)
4270
}
71+
72+
// Execute the call with all the bells and whistles, informing the caller only if there was an error.
73+
// The absense of one indicates success.
74+
fn doit(&self) -> Option<api::Error> {
75+
None
76+
}
4377
}
4478
</%def>

src/mako/cli/main.rs.mako

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<%namespace name="engine" file="lib/engine.mako"/>\
33
<%namespace name="util" file="../lib/util.mako"/>\
44
<%
5-
from util import (new_context, rust_comment)
5+
from util import (new_context, rust_comment, to_extern_crate_name, library_to_crate_name, library_name)
66
77
c = new_context(schemas, resources, context.get('methods'))
88
default_user_agent = "google-cli-rust-client/" + cargo.build_version
@@ -16,6 +16,7 @@
1616
extern crate docopt;
1717
extern crate yup_oauth2 as oauth2;
1818
extern crate rustc_serialize;
19+
extern crate ${to_extern_crate_name(library_to_crate_name(library_name(name, version), make.depends_on_suffix))} as api;
1920

2021
use std::io;
2122
use std::env;
@@ -29,12 +30,15 @@ fn main() {
2930
let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit());
3031
println!("{:?}", opts);
3132
match Engine::new(opts) {
32-
Err(e) => {
33-
write!(io::stderr(), "{}", e).ok();
34-
env::set_exit_status(e.exit_code);
33+
Err(err) => {
34+
write!(io::stderr(), "{}", err).ok();
35+
env::set_exit_status(err.exit_code);
3536
},
36-
Ok(mut engine) => {
37-
37+
Ok(engine) => {
38+
if let Some(err) = engine.doit() {
39+
write!(io::stderr(), "TODO: display {:?}", err).ok();
40+
env::set_exit_status(1);
41+
}
3842
}
3943
}
4044
}

src/rust/api/cmn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ pub struct DefaultDelegate;
215215
impl Delegate for DefaultDelegate {}
216216

217217

218-
218+
#[derive(Debug)]
219219
pub enum Error {
220220
/// The http connection failed
221221
HttpError(hyper::HttpError),

src/rust/cli/cmn.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,21 @@ impl fmt::Display for ConfigurationError {
5858
}
5959

6060
#[derive(Debug)]
61-
pub enum ArgumentError {
61+
pub enum CLIError {
6262
Configuration(ConfigurationError),
6363
}
6464

65-
impl fmt::Display for ArgumentError {
65+
impl fmt::Display for CLIError {
6666
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
6767
match *self {
68-
ArgumentError::Configuration(ref err) => writeln!(f, "Configuration -> {}", err)
68+
CLIError::Configuration(ref err) => writeln!(f, "Configuration -> {}", err)
6969
}
7070
}
7171
}
7272

7373
#[derive(Debug)]
7474
pub struct InvalidOptionsError {
75-
pub issues: Vec<ArgumentError>,
75+
pub issues: Vec<CLIError>,
7676
pub exit_code: i32,
7777
}
7878

@@ -86,24 +86,24 @@ impl fmt::Display for InvalidOptionsError {
8686
}
8787

8888
impl InvalidOptionsError {
89-
pub fn single(err: ArgumentError, exit_code: i32) -> InvalidOptionsError {
89+
pub fn single(err: CLIError, exit_code: i32) -> InvalidOptionsError {
9090
InvalidOptionsError {
9191
issues: vec![err],
9292
exit_code: exit_code,
9393
}
9494
}
9595
}
9696

97-
pub fn assure_config_dir_exists(dir: &str) -> Result<String, ArgumentError> {
97+
pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> {
9898
let trdir = dir.trim();
9999
if trdir.len() == 0 {
100-
return Err(ArgumentError::Configuration(ConfigurationError::DirectoryUnset))
100+
return Err(CLIError::Configuration(ConfigurationError::DirectoryUnset))
101101
}
102102

103103
let expanded_config_dir =
104104
if trdir.as_bytes()[0] == b'~' {
105105
match env::var("HOME").ok().or(env::var("UserProfile").ok()) {
106-
None => return Err(ArgumentError::Configuration(ConfigurationError::HomeExpansionFailed(trdir.to_string()))),
106+
None => return Err(CLIError::Configuration(ConfigurationError::HomeExpansionFailed(trdir.to_string()))),
107107
Some(mut user) => {
108108
user.push_str(&trdir[1..]);
109109
user
@@ -115,19 +115,19 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, ArgumentError> {
115115

116116
if let Err(err) = fs::create_dir(&expanded_config_dir) {
117117
if err.kind() != io::ErrorKind::AlreadyExists {
118-
return Err(ArgumentError::Configuration(
118+
return Err(CLIError::Configuration(
119119
ConfigurationError::DirectoryCreationFailed((expanded_config_dir, err))))
120120
}
121121
}
122122

123123
Ok(expanded_config_dir)
124124
}
125125

126-
pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Result<ApplicationSecret, ArgumentError> {
126+
pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Result<ApplicationSecret, CLIError> {
127127
let secret_path = Path::new(dir).join(secret_basename);
128128
let secret_str = || secret_path.as_path().to_str().unwrap().to_string();
129129
let secret_io_error = |io_err: io::Error| {
130-
Err(ArgumentError::Configuration(ConfigurationError::IOError(
130+
Err(CLIError::Configuration(ConfigurationError::IOError(
131131
(secret_str(), io_err)
132132
)))
133133
};
@@ -173,14 +173,14 @@ pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Re
173173
return secret_io_error(io_err)
174174
}
175175
match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) {
176-
Err(json_decode_error) => return Err(ArgumentError::Configuration(
176+
Err(json_decode_error) => return Err(CLIError::Configuration(
177177
ConfigurationError::Secret(ApplicationSecretError::DecoderError(
178178
(secret_str(), json_decode_error)
179179
)))),
180180
Ok(console_secret) => match console_secret.installed {
181181
Some(secret) => return Ok(secret),
182182
None => return Err(
183-
ArgumentError::Configuration(
183+
CLIError::Configuration(
184184
ConfigurationError::Secret(
185185
ApplicationSecretError::FormatError(secret_str())
186186
)))

0 commit comments

Comments
 (0)