use clap::{
App,
AppSettings,
Arg,
};
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
pub enum Command {
Usage,
ShowStats,
InternalStartServer,
StartServer,
StopServer,
Compile {
exe: OsString,
cmdline: Vec<OsString>,
cwd: PathBuf,
},
}
fn get_app<'a, 'b>() -> App<'a, 'b> {
App::new("sccache")
.version(env!("CARGO_PKG_VERSION"))
.setting(AppSettings::TrailingVarArg)
.args_from_usage(
"-s --show-stats 'show cache statistics'
--start-server 'start background server'
--stop-server 'stop background server'"
)
.arg(
Arg::with_name("cmd")
.multiple(true)
.use_delimiter(false)
)
}
fn usage() -> Command {
get_app().print_help().unwrap();
println!("");
Command::Usage
}
pub fn parse() -> Command {
trace!("parse");
let matches = get_app().get_matches();
let internal_start_server = match env::var("SCCACHE_START_SERVER") {
Ok(val) => val == "1",
Err(_) => false,
};
let show_stats = matches.is_present("show-stats");
let start_server = matches.is_present("start-server");
let stop_server = matches.is_present("stop-server");
let cmd = matches.values_of_os("cmd");
fn is_some<T>(x : &Option<T>) -> bool {
x.is_some()
}
if [
internal_start_server,
show_stats,
start_server,
stop_server,
is_some(&cmd),
].iter()
.fold(0, |acc, &x| acc + (x as usize)) > 1 {
println!("sccache: Too many commands specified");
return usage();
}
if internal_start_server {
Command::InternalStartServer
} else if show_stats {
Command::ShowStats
} else if start_server {
Command::StartServer
} else if stop_server {
Command::StopServer
} else if let Some(mut args) = cmd {
if let Ok(cwd) = env::current_dir() {
if let Some(exe) = args.next() {
let cmdline = args.map(|s| s.to_owned()).collect::<Vec<_>>();
Command::Compile {
exe: exe.to_owned(),
cmdline: cmdline,
cwd: cwd,
}
} else {
println!("sccache: No compile command");
usage()
}
} else {
println!("sccache: Couldn't determine current working directory");
usage()
}
} else {
println!("sccache: No command specified");
usage()
}
}