Skip to content

Commit

Permalink
feat(CLI): init hub + refactor for dry-run mode
Browse files Browse the repository at this point in the history
The hub is just using preset types - we will have to implement our own
storage and auth-delegate, as well as a Hub delegate at some point.

Dry run mode allows us to check for errors and use a call builder
using the very same code.

Fixes #57
  • Loading branch information
Byron committed Apr 14, 2015
1 parent 7dc9972 commit f71c286
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 23 deletions.
69 changes: 48 additions & 21 deletions src/mako/cli/lib/engine.mako
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
<%namespace name="util" file="../../lib/util.mako"/>\
<%!
from util import hub_type
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,
cmd_ident)
v_arg = '<%s>' % VALUE_ARG
%>\
<%def name="new(c)">\
<%
hub_type_name = 'api::' + hub_type(c.schemas, util.canonical_name())
%>\
mod cmn;
use cmn::InvalidOptionsError;
use std::default::Default;
use oauth2::ApplicationSecret;
use oauth2::{Authenticator, DefaultAuthenticatorDelegate, MemoryStorage};
struct Engine {
opt: Options,
config_dir: String,
secret: ApplicationSecret,
hub: ${hub_type_name}<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, MemoryStorage, hyper::Client>>,
}
impl Engine {
// 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(&opt.flag_config_dir) {
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
Ok(p) => p,
};
match cmn::application_secret_from_directory(&config_dir, "${util.program_name()}-secret.json") {
Ok(secret) => (config_dir, secret),
Err(e) => return Err(InvalidOptionsError::single(e, 4))
}
};
fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) {
let mut err = InvalidOptionsError::new();
## RESOURCE LOOP: check for set primary subcommand
% for resource in sorted(c.rta_map.keys()):
Expand All @@ -40,15 +35,15 @@ impl Engine {
% else:
else if \
% endif
opt.${cmd_ident(resource)} {
self.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)} {
self.opt.${cmd_ident(method)} {
}\
% endfor # each method
Expand All @@ -61,18 +56,50 @@ opt.${cmd_ident(method)} {
unreachable!();
}
let mut engine = Engine {
if dry_run {
if err.issues.len() > 0 {
(None, Some(err))
} else {
(None, None)
}
} else {
unreachable!();
}
}
// 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(&opt.flag_config_dir) {
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
Ok(p) => p,
};
match cmn::application_secret_from_directory(&config_dir, "${util.program_name()}-secret.json") {
Ok(secret) => (config_dir, secret),
Err(e) => return Err(InvalidOptionsError::single(e, 4))
}
};
let auth = Authenticator::new(&secret, DefaultAuthenticatorDelegate,
hyper::Client::new(),
<MemoryStorage as Default>::default(), None);
let engine = Engine {
opt: opt,
config_dir: config_dir,
secret: secret,
hub: ${hub_type_name}::new(hyper::Client::new(), auth),
};
Ok(engine)
match engine._doit(true) {
(_, Some(err)) => Err(err),
_ => 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
self._doit(false).0
}
}
</%def>
3 changes: 2 additions & 1 deletion src/mako/cli/main.rs.mako
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
extern crate docopt;
extern crate yup_oauth2 as oauth2;
extern crate rustc_serialize;
extern crate hyper;
extern crate ${to_extern_crate_name(library_to_crate_name(library_name(name, version), make.depends_on_suffix))} as api;

use std::io;
Expand All @@ -28,7 +29,7 @@ ${engine.new(c)}\

fn main() {
let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit());
println!("{:?}", opts);
println!("DEBUG: {:?}", opts);
match Engine::new(opts) {
Err(err) => {
write!(io::stderr(), "{}", err).ok();
Expand Down
8 changes: 7 additions & 1 deletion src/rust/cli/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::env;
use std::io;
use std::fmt;
use std::path::Path;
use std::cell::RefCell;

use std::io::{Write, Read};

Expand Down Expand Up @@ -92,6 +91,13 @@ impl InvalidOptionsError {
exit_code: exit_code,
}
}

pub fn new() -> InvalidOptionsError {
InvalidOptionsError {
issues: Vec::new(),
exit_code: 1,
}
}
}

pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> {
Expand Down

0 comments on commit f71c286

Please sign in to comment.