-
Notifications
You must be signed in to change notification settings - Fork 552
/
cmdline.rs
123 lines (117 loc) · 3.8 KB
/
cmdline.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// 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.
use clap::{
App,
AppSettings,
Arg,
};
use log::LogLevel::Trace;
use std::env;
/// A specific command to run.
pub enum Command {
/// Show usage and exit.
Usage,
/// Show cache statistics and exit.
ShowStats,
/// Run background server.
InternalStartServer,
/// Start background server as a subprocess.
StartServer,
/// Stop background server.
StopServer,
/// Run a compiler command.
Compile {
/// The command to execute
cmdline: Vec<String>,
/// The directory in which to execute the command.
cwd: String,
},
}
/// Get the `App` used for argument parsing.
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)
)
}
/// Print usage summary and return a `Command::Usage`.
fn usage() -> Command {
get_app().print_help().unwrap();
Command::Usage
}
/// Parse the commandline into a `Command` to execute.
pub fn parse<'a>() -> Command {
let matches = get_app().get_matches();
// The internal start server command is passed in the environment.
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("cmd");
// Ensure that we've only received one command to run.
fn is_some<T>(x : &Option<T>) -> bool {
x.is_some() // .as_ref().and(Some(true)).unwrap_or(false)
}
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(a) = cmd {
if let Some(cwd) = env::current_dir().ok()
.and_then(|d| d.to_str().and_then(|s| Some(s.to_owned()))) {
let cmdline = a.map(|s| s.to_owned()).collect::<Vec<_>>();
if log_enabled!(Trace) {
let cmd_str = cmdline.join(" ");
trace!("parse: `{}`", cmd_str);
}
Command::Compile {
cmdline: cmdline,
cwd: cwd,
}
} else {
println!("sccache: Couldn't determine current working directory");
usage()
}
} else {
println!("sccache: No command specified");
usage()
}
}