use clap::{self, SubCommand, App};
use libgerrit::error::GGRError;
use libgerrit::error::GGRResult;
use std::env;
use std::fmt;
use std::fs;
use std::io;
use std::path::Path;
use toml_config;
pub fn menu<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("config")
.about("config management for ggr")
.subcommand(SubCommand::with_name("list")
.help("List all config options")
)
}
pub fn manage(x: &clap::ArgMatches) -> GGRResult<()> {
match x.subcommand() {
("list", Some(y)) => { list(y) },
_ => {
println!("{}", x.usage());
Ok(())
},
}
}
fn list(_: &clap::ArgMatches) -> GGRResult<()> {
let cf = try!(ConfigFile::discover(".", ".ggr.conf"));
let c = Config::from_configfile(cf);
println!("{}", c);
Ok(())
}
#[derive(RustcDecodable, RustcEncodable)]
pub struct Config {
api: String,
username: Option<String>,
password: Option<String>,
root: bool,
dryrun: bool,
}
impl Default for Config {
fn default() -> Config {
Config {
api: "".to_owned(),
username: None,
password: None,
root: true,
dryrun: false,
}
}
}
impl fmt::Display for Config {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(writeln!(f, "* url ......... : {api}",
api = self.api.clone(),
));
try!(writeln!(f, " user/pass ... : from .netrc file"));
write!(f, " root ........ : {root}", root = self.root)
}
}
impl Config {
pub fn from_configfile(cf: ConfigFile) -> Config {
let config: Config = toml_config::ConfigFactory::load(cf.file.path().as_path());
if config.username.is_some() || config.password.is_some() {
info!("ignoring username and password from configfile using .netrc file now");
}
config
}
pub fn is_valid(&self) -> bool {
!self.api.is_empty()
}
pub fn get_base_url(&self) -> &str {
&self.api
}
pub fn is_root(&self) -> &bool {
&self.root
}
pub fn dry_run(&self) -> &bool {
&self.dryrun
}
pub fn set_dry_run(&mut self, new: bool) {
self.dryrun = new
}
}
pub struct ConfigFile {
file: fs::DirEntry,
}
impl fmt::Display for ConfigFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.file.file_name())
}
}
impl ConfigFile {
fn new_with_path(p: fs::DirEntry) -> ConfigFile {
ConfigFile {
file: p,
}
}
pub fn discover(folder: &str, name: &str) -> GGRResult<ConfigFile> {
let cwd = try!(env::current_dir());
let mut folder = folder;
if folder.eq(".") {
folder = match cwd.to_str().ok_or_else(|| GGRError::General("something is wrong with current directory".to_string())) {
Ok(x) => x,
Err(x) => return Err(x),
}
}
let mut path = Path::new(folder.into());
let pathtemp = path;
loop {
for entry in try!(fs::read_dir(path)) {
let entry = try!(entry);
if entry.file_name() == *name {
return Ok(ConfigFile::new_with_path(entry));
}
}
match path.parent() {
Some(x) => {
path = x;
},
None => {
break;
}
}
}
Err(GGRError::StdIo(io::Error::new( io::ErrorKind::NotFound,
format!("conf file {} in {:?} and all parent directories not found", name, pathtemp)
)
)
)
}
}