Use error-chain to define Result+Error types, refactor cmdline::parse to use it.

This commit is contained in:
Ted Mielczarek 2017-01-27 16:01:29 -05:00
Родитель 1b2b66fa58
Коммит 52630820ef
6 изменённых файлов: 109 добавлений и 44 удалений

51
Cargo.lock сгенерированный
Просмотреть файл

@ -7,6 +7,7 @@ dependencies = [
"clap 2.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fern 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -58,6 +59,29 @@ dependencies = [
"xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.4.0"
@ -118,6 +142,15 @@ dependencies = [
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dbghelp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dtoa"
version = "0.2.2"
@ -132,6 +165,14 @@ dependencies = [
"regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "error-chain"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fern"
version = "0.3.5"
@ -533,6 +574,11 @@ dependencies = [
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-serialize"
version = "0.3.19"
@ -771,6 +817,8 @@ dependencies = [
"checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9"
"checksum ansi_term 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30275ad0ad84ec1c06dde3b3f7d23c6006b7d76d61a85e7060b426b747eff70d"
"checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4"
"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
"checksum backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3602e8d8c43336088a8505fa55cae2b3884a9be29440863a11528a42f46f6bb7"
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27"
@ -779,8 +827,10 @@ dependencies = [
"checksum clap 2.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4cbebe3ce784f9c63d83684d07cf2da470b88bb149ac17dc262b3062e6fe8d93"
"checksum cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e3d6405328b6edb412158b3b7710e2634e23f3614b9bb1c412df7952489a626"
"checksum daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0239832c1b4ca406d5ec73728cf4c7336d25cf85dd32db9e047e9e706ee0e935"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
"checksum env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "82dcb9ceed3868a03b335657b85a159736c961900f7e7747d3b0b97b9ccb5ccb"
"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
"checksum fern 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d2f58d053ad7791bfaad58a3f3541fe2d2aecc564dd82aee7f92fa402c054b2"
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
@ -827,6 +877,7 @@ dependencies = [
"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
"checksum retry 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29460f6011a25fc70b22010e796bd98330baccaa0005cba6f90b858a510dec0d"
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"

Просмотреть файл

@ -12,6 +12,7 @@ app_dirs = "1.1.1"
chrono = "0.2.25"
clap = "2.3.0"
env_logger = "0.3.3"
error-chain = "0.7.2"
fern = "0.3.5"
filetime = "0.1"
futures = "0.1"

Просмотреть файл

@ -17,6 +17,7 @@ use clap::{
AppSettings,
Arg,
};
use errors::*;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
@ -24,8 +25,6 @@ use which::which_in;
/// A specific command to run.
pub enum Command {
/// Show usage and exit.
Usage,
/// Show cache statistics and exit.
ShowStats,
/// Zero cache statistics and exit.
@ -48,7 +47,7 @@ pub enum Command {
}
/// Get the `App` used for argument parsing.
fn get_app<'a, 'b>() -> App<'a, 'b> {
pub fn get_app<'a, 'b>() -> App<'a, 'b> {
App::new(env!("CARGO_PKG_NAME"))
.version(env!("CARGO_PKG_VERSION"))
.setting(AppSettings::TrailingVarArg)
@ -65,22 +64,10 @@ fn get_app<'a, 'b>() -> App<'a, 'b> {
)
}
/// Print usage summary and return a `Command::Usage`.
fn usage() -> Command {
get_app().print_help().unwrap();
println!("");
Command::Usage
}
/// Parse the commandline into a `Command` to execute.
pub fn parse() -> Command {
pub fn parse() -> Result<Command> {
trace!("parse");
let cwd = if let Ok(cwd) = env::current_dir() {
cwd
} else {
println!("sccache: Couldn't determine current working directory");
return usage();
};
let cwd = try!(env::current_dir().chain_err(|| "sccache: Couldn't determine current working directory"));
// The internal start server command is passed in the environment.
let internal_start_server = match env::var("SCCACHE_START_SERVER") {
Ok(val) => val == "1",
@ -96,21 +83,22 @@ pub fn parse() -> Command {
// as if it were invoked with `sccache $name`, but avoid $name resolving
// to ourselves again if it's in the PATH.
_ => {
let path = env::var_os("PATH");
match which_in(exe.file_name().unwrap(), path.as_ref(), &cwd) {
Ok(ref full_path) if full_path.canonicalize().unwrap() == exe.canonicalize().unwrap() => {
if let Some(dir) = full_path.parent() {
let path = env::join_paths(env::split_paths(&path.unwrap()).filter(|p| p != dir)).ok();
match which_in(exe.file_name().unwrap(), path, &cwd) {
Ok(full_path) => args[0] = full_path.into(),
Err(_) => { }
if let (Some(path), Some(exe_filename)) = (env::var_os("PATH"), exe.file_name()) {
match which_in(exe_filename, Some(&path), &cwd) {
Ok(ref full_path) if try!(full_path.canonicalize()) == try!(exe.canonicalize()) => {
if let Some(dir) = full_path.parent() {
let path = env::join_paths(env::split_paths(&path).filter(|p| p != dir)).ok();
match which_in(exe_filename, path, &cwd) {
Ok(full_path) => args[0] = full_path.into(),
Err(_) => { }
}
}
}
Ok(full_path) => args[0] = full_path.into(),
Err(_) => { }
}
Ok(full_path) => args[0] = full_path.into(),
Err(_) => { }
args.insert(0, env!("CARGO_PKG_NAME").into());
}
args.insert(0, env!("CARGO_PKG_NAME").into());
}
}
}
@ -134,33 +122,30 @@ pub fn parse() -> Command {
is_some(&cmd),
].iter()
.fold(0, |acc, &x| acc + (x as usize)) > 1 {
println!("sccache: Too many commands specified");
return usage();
bail!("Too many commands specified");
}
if internal_start_server {
Command::InternalStartServer
Ok(Command::InternalStartServer)
} else if show_stats {
Command::ShowStats
Ok(Command::ShowStats)
} else if start_server {
Command::StartServer
Ok(Command::StartServer)
} else if stop_server {
Command::StopServer
Ok(Command::StopServer)
} else if zero_stats {
Command::ZeroStats
Ok(Command::ZeroStats)
} else if let Some(mut args) = cmd {
if let Some(exe) = args.next() {
let cmdline = args.map(|s| s.to_owned()).collect::<Vec<_>>();
Command::Compile {
Ok(Command::Compile {
exe: exe.to_owned(),
cmdline: cmdline,
cwd: cwd,
}
})
} else {
println!("sccache: No compile command");
usage()
bail!("No compile command");
}
} else {
println!("sccache: No command specified");
usage()
bail!("No command specified");
}
}

Просмотреть файл

@ -560,8 +560,6 @@ pub fn do_compile<T, U, V, W, X, Y>(creator: T,
/// Run `cmd` and return the process exit status.
pub fn run_command(cmd : Command) -> i32 {
match cmd {
// Actual usage gets printed in `cmdline::parse`.
Command::Usage => 0,
Command::ShowStats => {
trace!("Command::ShowStats");
result_exit_code(connect_or_start_server(get_port()).and_then(request_stats).and_then(print_stats),

19
src/errors.rs Normal file
Просмотреть файл

@ -0,0 +1,19 @@
// Copyright 2016 Mozilla Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
error_chain! {
foreign_links {
Io(::std::io::Error);
}
}

Просмотреть файл

@ -21,6 +21,8 @@ extern crate crypto;
#[cfg(unix)]
extern crate daemonize;
extern crate env_logger;
#[macro_use]
extern crate error_chain;
extern crate filetime;
extern crate futures;
extern crate hyper;
@ -60,6 +62,7 @@ mod client;
mod cmdline;
mod commands;
mod compiler;
mod errors;
mod mock_command;
mod protocol;
mod server;
@ -69,7 +72,15 @@ use std::env;
fn main() {
init_logging();
std::process::exit(commands::run_command(cmdline::parse()));
std::process::exit(match cmdline::parse() {
Ok(cmd) => commands::run_command(cmd),
Err(e) => {
println!("sccache: {}", e);
cmdline::get_app().print_help().unwrap();
println!("");
1
}
});
}
fn init_logging() {