mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-02-23 15:49:49 +01:00
chore(code-up): latest version of all code
This commit is contained in:
@@ -4,6 +4,7 @@ use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token};
|
||||
use serde::json;
|
||||
use mime::Mime;
|
||||
use clap::{App, SubCommand};
|
||||
use strsim;
|
||||
|
||||
use std::fs;
|
||||
use std::env;
|
||||
@@ -18,14 +19,54 @@ use std::default::Default;
|
||||
|
||||
const FIELD_SEP: char = '.';
|
||||
|
||||
// Based on @erickt user comment. Thanks for the idea !
|
||||
// Remove all keys whose values are null from given value (changed in place)
|
||||
pub fn remove_json_null_values(value: &mut json::value::Value) {
|
||||
match *value {
|
||||
json::value::Value::Object(ref mut map) => {
|
||||
let mut for_removal = Vec::new();
|
||||
|
||||
for (key, mut value) in map.iter_mut() {
|
||||
if value.is_null() {
|
||||
for_removal.push(key.clone());
|
||||
} else {
|
||||
remove_json_null_values(&mut value);
|
||||
}
|
||||
}
|
||||
|
||||
for key in &for_removal {
|
||||
map.remove(key);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> {
|
||||
|
||||
let mut candidate: Option<(f64, &str)> = None;
|
||||
for pv in possible_values {
|
||||
let confidence = strsim::jaro_winkler(v, pv);
|
||||
if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) {
|
||||
candidate = Some((confidence, pv));
|
||||
}
|
||||
}
|
||||
match candidate {
|
||||
None => None,
|
||||
Some((_, candidate)) => Some(candidate),
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CallType {
|
||||
Upload(UploadProtocol),
|
||||
Standard,
|
||||
}
|
||||
|
||||
pub enum UploadProtocol {
|
||||
Simple,
|
||||
Resumable,
|
||||
arg_enum!{
|
||||
pub enum UploadProtocol {
|
||||
Simple,
|
||||
Resumable
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for UploadProtocol {
|
||||
@@ -46,18 +87,6 @@ impl AsRef<str> for CallType {
|
||||
}
|
||||
}
|
||||
|
||||
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>);
|
||||
|
||||
@@ -129,6 +158,49 @@ impl FieldCursor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> {
|
||||
if value.len() == 0 {
|
||||
return None
|
||||
}
|
||||
|
||||
let mut last_c = FIELD_SEP;
|
||||
|
||||
let mut field = String::new();
|
||||
let mut output = String::new();
|
||||
|
||||
let push_field = |fs: &mut String, f: &mut String| {
|
||||
if f.len() > 0 {
|
||||
fs.push_str(
|
||||
match did_you_mean(&f, possible_values) {
|
||||
Some(candidate) => candidate,
|
||||
None => &f,
|
||||
});
|
||||
f.truncate(0);
|
||||
}
|
||||
};
|
||||
|
||||
for (cid, c) in value.chars().enumerate() {
|
||||
if c == FIELD_SEP {
|
||||
if last_c != FIELD_SEP {
|
||||
push_field(&mut output, &mut field);
|
||||
}
|
||||
output.push(c);
|
||||
} else {
|
||||
field.push(c);
|
||||
}
|
||||
|
||||
last_c = c;
|
||||
}
|
||||
|
||||
push_field(&mut output, &mut field);
|
||||
|
||||
if &output == value {
|
||||
None
|
||||
} else {
|
||||
Some(output)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_fields(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
@@ -153,7 +225,7 @@ 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 {
|
||||
pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType {
|
||||
CallType::Upload(
|
||||
match UploadProtocol::from_str(name) {
|
||||
Ok(up) => up,
|
||||
@@ -282,10 +354,10 @@ impl fmt::Display for ApplicationSecretError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
ApplicationSecretError::DecoderError((ref path, ref err))
|
||||
=> writeln!(f, "Could not decode file at '{}' with error: {}",
|
||||
=> writeln!(f, "Could not decode file at '{}' with error: {}.",
|
||||
path, err),
|
||||
ApplicationSecretError::FormatError(ref path)
|
||||
=> writeln!(f, "'installed' field is unset in secret file at '{}'",
|
||||
=> writeln!(f, "'installed' field is unset in secret file at '{}'.",
|
||||
path),
|
||||
}
|
||||
}
|
||||
@@ -304,15 +376,15 @@ impl fmt::Display for ConfigurationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
ConfigurationError::DirectoryCreationFailed((ref dir, ref err))
|
||||
=> writeln!(f, "Directory '{}' could not be created with error: {}", dir, err),
|
||||
=> writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err),
|
||||
ConfigurationError::DirectoryUnset
|
||||
=> writeln!(f, "--config-dir was unset or empty"),
|
||||
=> writeln!(f, "--config-dir was unset or empty."),
|
||||
ConfigurationError::HomeExpansionFailed(ref dir)
|
||||
=> writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir),
|
||||
=> writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir),
|
||||
ConfigurationError::Secret(ref err)
|
||||
=> writeln!(f, "Secret -> {}", err),
|
||||
ConfigurationError::IOError((ref path, ref err))
|
||||
=> writeln!(f, "IO operation failed on path '{}' with error: {}", path, err),
|
||||
=> writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,9 +399,9 @@ impl fmt::Display for InputError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
InputError::IOError((ref file_path, ref io_err))
|
||||
=> writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err),
|
||||
=> writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err),
|
||||
InputError::Mime(ref mime)
|
||||
=> writeln!(f, "'{}' is not a known mime-type", mime),
|
||||
=> writeln!(f, "'{}' is not a known mime-type.", mime),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,7 +410,7 @@ impl fmt::Display for InputError {
|
||||
pub enum FieldError {
|
||||
PopOnEmpty(String),
|
||||
TrailingFieldSep(String),
|
||||
Unknown(String),
|
||||
Unknown(String, Option<String>, Option<String>),
|
||||
Empty,
|
||||
}
|
||||
|
||||
@@ -347,13 +419,26 @@ impl fmt::Display for FieldError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
FieldError::PopOnEmpty(ref field)
|
||||
=> writeln!(f, "'{}': Cannot move up on empty field cursor", field),
|
||||
=> writeln!(f, "'{}': Cannot move up on empty field cursor.", field),
|
||||
FieldError::TrailingFieldSep(ref field)
|
||||
=> writeln!(f, "'{}': Single field separator may not be last character", field),
|
||||
FieldError::Unknown(ref field)
|
||||
=> writeln!(f, "Field '{}' does not exist", field),
|
||||
=> writeln!(f, "'{}': Single field separator may not be last character.", field),
|
||||
FieldError::Unknown(ref field, ref suggestion, ref value) => {
|
||||
let suffix =
|
||||
match *suggestion {
|
||||
Some(ref s) => {
|
||||
let kv =
|
||||
match *value {
|
||||
Some(ref v) => format!("{}={}", s, v),
|
||||
None => s.clone(),
|
||||
};
|
||||
format!(" Did you mean '{}' ?", kv)
|
||||
},
|
||||
None => String::new(),
|
||||
};
|
||||
writeln!(f, "Field '{}' does not exist.{}", field, suffix)
|
||||
},
|
||||
FieldError::Empty
|
||||
=> writeln!(f, "Field names must not be empty"),
|
||||
=> writeln!(f, "Field names must not be empty."),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,7 +448,7 @@ impl fmt::Display for FieldError {
|
||||
pub enum CLIError {
|
||||
Configuration(ConfigurationError),
|
||||
ParseError(&'static str, &'static str, String, String),
|
||||
UnknownParameter(String),
|
||||
UnknownParameter(String, Vec<&'static str>),
|
||||
InvalidUploadProtocol(String, Vec<String>),
|
||||
InvalidKeyValueSyntax(String, bool),
|
||||
Input(InputError),
|
||||
@@ -379,18 +464,24 @@ impl fmt::Display for CLIError {
|
||||
CLIError::Input(ref err) => write!(f, "Input -> {}", err),
|
||||
CLIError::Field(ref err) => write!(f, "Field -> {}", err),
|
||||
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(", ")),
|
||||
=> 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: {}",
|
||||
=> writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.",
|
||||
arg_name, value, type_name, err_desc),
|
||||
CLIError::UnknownParameter(ref param_name)
|
||||
=> writeln!(f, "Parameter '{}' is unknown.", param_name),
|
||||
CLIError::UnknownParameter(ref param_name, ref possible_values) => {
|
||||
let mut suffix =
|
||||
match did_you_mean(param_name, &possible_values) {
|
||||
Some(v) => format!(" Did you mean '{}' ?", v),
|
||||
None => String::new(),
|
||||
};
|
||||
write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix)
|
||||
},
|
||||
CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => {
|
||||
let hashmap_info = if is_hashmap { "hashmap " } else { "" };
|
||||
writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info)
|
||||
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),
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
#![feature(plugin, exit_status)]
|
||||
#![allow(unused_variables, unused_imports, dead_code, unused_mut)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate yup_oauth2 as oauth2;
|
||||
extern crate yup_hyper_mock as mock;
|
||||
extern crate serde;
|
||||
extern crate hyper;
|
||||
extern crate mime;
|
||||
extern crate strsim;
|
||||
extern crate google_groupsmigration1 as api;
|
||||
|
||||
use std::env;
|
||||
@@ -20,7 +22,7 @@ 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, CallType, UploadProtocol,
|
||||
protocol_from_str};
|
||||
calltype_from_str, remove_json_null_values};
|
||||
|
||||
use std::default::Default;
|
||||
use std::str::FromStr;
|
||||
@@ -37,6 +39,8 @@ enum DoitError {
|
||||
struct Engine<'n, 'a> {
|
||||
opt: ArgMatches<'n, 'a>,
|
||||
hub: api::GroupsMigration<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>,
|
||||
gp: Vec<&'static str>,
|
||||
gpm: Vec<(&'static str, &'static str)>,
|
||||
}
|
||||
|
||||
|
||||
@@ -47,26 +51,25 @@ impl<'n, 'a> Engine<'n, 'a> {
|
||||
for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() {
|
||||
let (key, value) = parse_kv_arg(&*parg, err, false);
|
||||
match key {
|
||||
"alt"
|
||||
|"fields"
|
||||
|"key"
|
||||
|"oauth-token"
|
||||
|"pretty-print"
|
||||
|"quota-user"
|
||||
|"user-ip" => {
|
||||
let map = [
|
||||
("oauth-token", "oauth_token"),
|
||||
("pretty-print", "prettyPrint"),
|
||||
("quota-user", "quotaUser"),
|
||||
("user-ip", "userIp"),
|
||||
];
|
||||
call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset"))
|
||||
},
|
||||
_ => err.issues.push(CLIError::UnknownParameter(key.to_string())),
|
||||
_ => {
|
||||
let mut found = false;
|
||||
for param in &self.gp {
|
||||
if key == *param {
|
||||
found = true;
|
||||
call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
err.issues.push(CLIError::UnknownParameter(key.to_string(),
|
||||
Vec::new() + &self.gp + &[]
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 protocol = calltype_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 {
|
||||
@@ -87,7 +90,9 @@ impl<'n, 'a> Engine<'n, 'a> {
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
Ok((mut response, output_schema)) => {
|
||||
serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap();
|
||||
let mut value = json::value::to_value(&output_schema);
|
||||
remove_json_null_values(&mut value);
|
||||
serde::json::to_writer_pretty(&mut ostream, &value).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -165,6 +170,13 @@ impl<'n, 'a> Engine<'n, 'a> {
|
||||
let engine = Engine {
|
||||
opt: opt,
|
||||
hub: api::GroupsMigration::new(client, auth),
|
||||
gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"],
|
||||
gpm: vec![
|
||||
("oauth-token", "oauth_token"),
|
||||
("pretty-print", "prettyPrint"),
|
||||
("quota-user", "quotaUser"),
|
||||
("user-ip", "userIp"),
|
||||
]
|
||||
};
|
||||
|
||||
match engine._doit(true) {
|
||||
@@ -186,29 +198,31 @@ fn main() {
|
||||
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."),
|
||||
("insert",
|
||||
Some(r##"Inserts a new mail into the archive of the Google group."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_groupsmigration1_cli/archive_insert",
|
||||
vec![
|
||||
(Some("group-id"),
|
||||
(Some(r##"group-id"##),
|
||||
None,
|
||||
Some("The group ID"),
|
||||
Some(r##"The group ID"##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
(Some("mode"),
|
||||
Some("u"),
|
||||
Some("Specify the upload protocol (simple|resumable) and the file to upload"),
|
||||
(Some(r##"mode"##),
|
||||
Some(r##"u"##),
|
||||
Some(r##"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(r##"v"##),
|
||||
Some(r##"p"##),
|
||||
Some(r##"Set various optional parameters, matching the key=value form"##),
|
||||
Some(false),
|
||||
Some(true)),
|
||||
|
||||
(Some("out"),
|
||||
Some("o"),
|
||||
Some("Specify the file into which to write the programs output"),
|
||||
(Some(r##"out"##),
|
||||
Some(r##"o"##),
|
||||
Some(r##"Specify the file into which to write the program's output"##),
|
||||
Some(false),
|
||||
Some(false)),
|
||||
]),
|
||||
@@ -245,11 +259,12 @@ fn main() {
|
||||
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 {
|
||||
for &(sub_command_name, ref desc, url_info, ref args) in subcommands {
|
||||
let mut scmd = SubCommand::new(sub_command_name);
|
||||
if let &Some(desc) = desc {
|
||||
scmd = scmd.about(desc);
|
||||
}
|
||||
scmd = scmd.after_help(url_info);
|
||||
|
||||
for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args {
|
||||
let arg_name_str =
|
||||
|
||||
Reference in New Issue
Block a user