mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-01-02 01:20:02 +01:00
fix(CLI): added latest reference CLI code
Just to have something to link to
This commit is contained in:
@@ -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())
|
||||
)))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
// This file was generated automatically from 'src/mako/cli/main.rs.mako'
|
||||
// DO NOT EDIT !
|
||||
#![feature(plugin, exit_status)]
|
||||
#![plugin(docopt_macros)]
|
||||
#![allow(unused_variables, unused_imports, dead_code, unused_mut)]
|
||||
|
||||
extern crate docopt;
|
||||
extern crate clap;
|
||||
extern crate yup_oauth2 as oauth2;
|
||||
extern crate yup_hyper_mock as mock;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde;
|
||||
extern crate hyper;
|
||||
extern crate mime;
|
||||
@@ -16,53 +14,37 @@ extern crate google_groupsmigration1 as api;
|
||||
|
||||
use std::env;
|
||||
use std::io::{self, Write};
|
||||
|
||||
docopt!(Options derive Debug, "
|
||||
Usage:
|
||||
groupsmigration1 [options] archive insert <group-id> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>]
|
||||
groupsmigration1 --help
|
||||
|
||||
All documentation details can be found at
|
||||
http://byron.github.io/google-apis-rs/google_groupsmigration1_cli/index.html
|
||||
|
||||
Configuration:
|
||||
--scope <url>
|
||||
Specify the authentication a method should be executed in. Each scope
|
||||
requires the user to grant this application permission to use it.
|
||||
If unset, it defaults to the shortest scope url for a particular method.
|
||||
--config-dir <folder>
|
||||
A directory into which we will store our persistent data. Defaults to
|
||||
a user-writable directory that we will create during the first invocation.
|
||||
[default: ~/.google-service-cli]
|
||||
--debug
|
||||
Output all server communication to standard error. `tx` and `rx` are placed
|
||||
into the same stream.
|
||||
--debug-auth
|
||||
Output all communication related to authentication to standard error. `tx`
|
||||
and `rx` are placed into the same stream.
|
||||
");
|
||||
use clap::{App, SubCommand, Arg};
|
||||
|
||||
mod cmn;
|
||||
|
||||
use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg,
|
||||
input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError};
|
||||
input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol,
|
||||
protocol_from_str};
|
||||
|
||||
use std::default::Default;
|
||||
use std::str::FromStr;
|
||||
|
||||
use oauth2::{Authenticator, DefaultAuthenticatorDelegate};
|
||||
use rustc_serialize::json;
|
||||
use serde::json;
|
||||
use clap::ArgMatches;
|
||||
|
||||
struct Engine {
|
||||
opt: Options,
|
||||
enum DoitError {
|
||||
IoError(String, io::Error),
|
||||
ApiError(api::Error),
|
||||
}
|
||||
|
||||
struct Engine<'n, 'a> {
|
||||
opt: ArgMatches<'n, 'a>,
|
||||
hub: api::GroupsMigration<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>,
|
||||
}
|
||||
|
||||
|
||||
impl Engine {
|
||||
fn _archive_insert(&self, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Option<api::Error> {
|
||||
let mut call = self.hub.archive().insert(&self.opt.arg_group_id);
|
||||
for parg in self.opt.arg_v.iter() {
|
||||
impl<'n, 'a> Engine<'n, 'a> {
|
||||
fn _archive_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
let mut call = self.hub.archive().insert(opt.value_of("group-id").unwrap_or(""));
|
||||
for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() {
|
||||
let (key, value) = parse_kv_arg(&*parg, err, false);
|
||||
match key {
|
||||
"alt"
|
||||
@@ -83,65 +65,71 @@ impl Engine {
|
||||
_ => err.issues.push(CLIError::UnknownParameter(key.to_string())),
|
||||
}
|
||||
}
|
||||
let protocol =
|
||||
if self.opt.cmd_simple {
|
||||
"simple"
|
||||
} else if self.opt.cmd_resumable {
|
||||
"resumable"
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
let mut input_file = input_file_from_opts(&self.opt.arg_file, err);
|
||||
let mime_type = input_mime_from_opts(&self.opt.arg_mime, err);
|
||||
let vals = opt.values_of("mode").unwrap();
|
||||
let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err);
|
||||
let mut input_file = input_file_from_opts(vals[1], err);
|
||||
let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err);
|
||||
if dry_run {
|
||||
None
|
||||
Ok(())
|
||||
} else {
|
||||
assert!(err.issues.len() == 0);
|
||||
if self.opt.flag_scope.len() > 0 {
|
||||
call = call.add_scope(&self.opt.flag_scope);
|
||||
for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() {
|
||||
call = call.add_scope(scope);
|
||||
}
|
||||
let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out);
|
||||
let mut ostream = match writer_from_opts(opt.value_of("out")) {
|
||||
Ok(mut f) => f,
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
"simple" => call.upload(input_file.unwrap(), mime_type.unwrap()),
|
||||
"resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()),
|
||||
_ => unreachable!(),
|
||||
CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()),
|
||||
CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()),
|
||||
CallType::Standard => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Some(api_err),
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
Ok((mut response, output_schema)) => {
|
||||
serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap();
|
||||
None
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) {
|
||||
fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> {
|
||||
let mut err = InvalidOptionsError::new();
|
||||
let mut call_result: Option<api::Error>;
|
||||
let mut call_result: Result<(), DoitError> = Ok(());
|
||||
let mut err_opt: Option<InvalidOptionsError> = None;
|
||||
|
||||
if self.opt.cmd_archive {
|
||||
if self.opt.cmd_insert {
|
||||
call_result = self._archive_insert(dry_run, &mut err);
|
||||
} else {
|
||||
unreachable!();
|
||||
match self.opt.subcommand() {
|
||||
("archive", Some(opt)) => {
|
||||
match opt.subcommand() {
|
||||
("insert", Some(opt)) => {
|
||||
call_result = self._archive_insert(opt, dry_run, &mut err);
|
||||
},
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingMethodError("archive".to_string()));
|
||||
writeln!(io::stderr(), "{}\n", opt.usage()).ok();
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingCommandError);
|
||||
writeln!(io::stderr(), "{}\n", self.opt.usage()).ok();
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
if dry_run {
|
||||
if err.issues.len() > 0 {
|
||||
err_opt = Some(err);
|
||||
}
|
||||
Err(err_opt)
|
||||
} else {
|
||||
Ok(call_result)
|
||||
}
|
||||
(call_result, err_opt)
|
||||
}
|
||||
|
||||
// Please note that this call will fail if any part of the opt can't be handled
|
||||
fn new(opt: Options) -> Result<Engine, InvalidOptionsError> {
|
||||
fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> {
|
||||
let (config_dir, secret) = {
|
||||
let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) {
|
||||
let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) {
|
||||
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
|
||||
Ok(p) => p,
|
||||
};
|
||||
@@ -154,7 +142,7 @@ impl Engine {
|
||||
};
|
||||
|
||||
let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate,
|
||||
if opt.flag_debug_auth {
|
||||
if opt.is_present("debug-auth") {
|
||||
hyper::Client::with_connector(mock::TeeConnector {
|
||||
connector: hyper::net::HttpConnector(None)
|
||||
})
|
||||
@@ -167,7 +155,7 @@ impl Engine {
|
||||
}, None);
|
||||
|
||||
let client =
|
||||
if opt.flag_debug {
|
||||
if opt.is_present("debug") {
|
||||
hyper::Client::with_connector(mock::TeeConnector {
|
||||
connector: hyper::net::HttpConnector(None)
|
||||
})
|
||||
@@ -180,34 +168,153 @@ impl Engine {
|
||||
};
|
||||
|
||||
match engine._doit(true) {
|
||||
(_, Some(err)) => Err(err),
|
||||
_ => Ok(engine),
|
||||
Err(Some(err)) => Err(err),
|
||||
Err(None) => Ok(engine),
|
||||
Ok(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
// 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> {
|
||||
self._doit(false).0
|
||||
fn doit(&self) -> Result<(), DoitError> {
|
||||
match self._doit(false) {
|
||||
Ok(res) => res,
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit());
|
||||
let debug = opts.flag_debug;
|
||||
match Engine::new(opts) {
|
||||
let upload_value_names = ["mode", "file"];
|
||||
let arg_data = [
|
||||
("archive", "methods: 'insert'", vec![
|
||||
("insert", Some("Inserts a new mail into the archive of the Google group."),
|
||||
vec![
|
||||
(Some("group-id"),
|
||||
None,
|
||||
Some("The group ID"),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
(Some("mode"),
|
||||
Some("u"),
|
||||
Some("Specify the upload protocol (simple|resumable) and the file to upload"),
|
||||
Some(true),
|
||||
Some(true)),
|
||||
|
||||
(Some("v"),
|
||||
Some("p"),
|
||||
Some("Set various fields of the request structure"),
|
||||
Some(false),
|
||||
Some(true)),
|
||||
|
||||
(Some("out"),
|
||||
Some("o"),
|
||||
Some("Specify the file into which to write the programs output"),
|
||||
Some(false),
|
||||
Some(false)),
|
||||
]),
|
||||
]),
|
||||
|
||||
];
|
||||
|
||||
let mut app = App::new("groupsmigration1")
|
||||
.author("Sebastian Thiel <byronimo@gmail.com>")
|
||||
.version("0.2.0+20140416")
|
||||
.about("Groups Migration Api.")
|
||||
.after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_groupsmigration1_cli")
|
||||
.arg(Arg::with_name("url")
|
||||
.long("scope")
|
||||
.help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.")
|
||||
.multiple(true)
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("folder")
|
||||
.long("config-dir")
|
||||
.help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli")
|
||||
.multiple(false)
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("debug")
|
||||
.long("debug")
|
||||
.help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.")
|
||||
.multiple(false)
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("debug-auth")
|
||||
.long("debug-auth")
|
||||
.help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.")
|
||||
.multiple(false)
|
||||
.takes_value(false));
|
||||
|
||||
for &(main_command_name, ref about, ref subcommands) in arg_data.iter() {
|
||||
let mut mcmd = SubCommand::new(main_command_name).about(about);
|
||||
|
||||
for &(sub_command_name, ref desc, ref args) in subcommands {
|
||||
let mut scmd = SubCommand::new(sub_command_name);
|
||||
if let &Some(desc) = desc {
|
||||
scmd = scmd.about(desc);
|
||||
}
|
||||
|
||||
for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args {
|
||||
let arg_name_str =
|
||||
match (arg_name, flag) {
|
||||
(&Some(an), _ ) => an,
|
||||
(_ , &Some(f)) => f,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let mut arg = Arg::with_name(arg_name_str);
|
||||
if let &Some(short_flag) = flag {
|
||||
arg = arg.short(short_flag);
|
||||
}
|
||||
if let &Some(desc) = desc {
|
||||
arg = arg.help(desc);
|
||||
}
|
||||
if arg_name.is_some() && flag.is_some() {
|
||||
arg = arg.takes_value(true);
|
||||
}
|
||||
if let &Some(required) = required {
|
||||
arg = arg.required(required);
|
||||
}
|
||||
if let &Some(multi) = multi {
|
||||
arg = arg.multiple(multi);
|
||||
}
|
||||
if arg_name_str == "mode" {
|
||||
arg = arg.number_of_values(2);
|
||||
arg = arg.value_names(&upload_value_names);
|
||||
|
||||
scmd = scmd.arg(Arg::with_name("mime")
|
||||
.short("m")
|
||||
.requires("mode")
|
||||
.required(false)
|
||||
.help("The file's mime time, like 'application/octet-stream'")
|
||||
.takes_value(true));
|
||||
}
|
||||
scmd = scmd.arg(arg);
|
||||
}
|
||||
mcmd = mcmd.subcommand(scmd);
|
||||
}
|
||||
app = app.subcommand(mcmd);
|
||||
}
|
||||
|
||||
let matches = app.get_matches();
|
||||
|
||||
let debug = matches.is_present("debug");
|
||||
match Engine::new(matches) {
|
||||
Err(err) => {
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
env::set_exit_status(err.exit_code);
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
},
|
||||
Ok(engine) => {
|
||||
if let Some(err) = engine.doit() {
|
||||
if debug {
|
||||
writeln!(io::stderr(), "{:?}", err).ok();
|
||||
} else {
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
}
|
||||
if let Err(doit_err) = engine.doit() {
|
||||
env::set_exit_status(1);
|
||||
match doit_err {
|
||||
DoitError::IoError(path, err) => {
|
||||
writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok();
|
||||
},
|
||||
DoitError::ApiError(err) => {
|
||||
if debug {
|
||||
writeln!(io::stderr(), "{:?}", err).ok();
|
||||
} else {
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user