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
|
#![deny(rust_2018_idioms)]
use clap::{crate_authors, crate_name};
use mullvad_problem_report::{collect_report, metadata, send_problem_report, Error};
use std::{env, path::Path, process};
use talpid_types::ErrorExt;
fn main() {
process::exit(match run() {
Ok(()) => 0,
Err(error) => {
eprintln!("{}", error.display_chain());
1
}
})
}
fn run() -> Result<(), Error> {
env_logger::init();
let app = clap::App::new(crate_name!())
.version(metadata::PRODUCT_VERSION)
.author(crate_authors!())
.about("Mullvad VPN problem report tool. Collects logs and sends them to Mullvad support.")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.global_settings(&[
clap::AppSettings::DisableHelpSubcommand,
clap::AppSettings::VersionlessSubcommands,
])
.subcommand(
clap::SubCommand::with_name("collect")
.about("Collect problem report")
.arg(
clap::Arg::with_name("output")
.help("The destination path for saving the collected report.")
.long("output")
.short("o")
.value_name("PATH")
.takes_value(true)
.required(true),
)
.arg(
clap::Arg::with_name("extra_logs")
.help("Paths to additional log files to be included.")
.multiple(true)
.value_name("EXTRA LOGS")
.takes_value(true)
.required(false),
)
.arg(
clap::Arg::with_name("redact")
.help("List of words and expressions to remove from the report")
.long("redact")
.value_name("PHRASE")
.multiple(true)
.takes_value(true),
),
)
.subcommand(
clap::SubCommand::with_name("send")
.about("Send collected problem report")
.arg(
clap::Arg::with_name("report")
.long("report")
.short("r")
.help("The path to previously collected report file.")
.takes_value(true)
.required(true),
)
.arg(
clap::Arg::with_name("email")
.long("email")
.short("e")
.help("Reporter's email")
.takes_value(true)
.required(false),
)
.arg(
clap::Arg::with_name("message")
.long("message")
.short("m")
.help("Reporter's message")
.takes_value(true)
.required(false),
),
);
let matches = app.get_matches();
if let Some(collect_matches) = matches.subcommand_matches("collect") {
let redact_custom_strings = collect_matches
.values_of_lossy("redact")
.unwrap_or_else(Vec::new);
let extra_logs = collect_matches
.values_of_os("extra_logs")
.map(|os_values| os_values.map(Path::new).collect())
.unwrap_or_else(Vec::new);
let output_path = Path::new(collect_matches.value_of_os("output").unwrap());
collect_report(&extra_logs, output_path, redact_custom_strings)?;
let expanded_output_path = output_path
.canonicalize()
.unwrap_or_else(|_| output_path.to_owned());
println!(
"Problem report written to {}",
expanded_output_path.display()
);
println!("");
println!("Send the problem report to support via the send subcommand. See:");
println!(" $ {} send --help", env::args().next().unwrap());
Ok(())
} else if let Some(send_matches) = matches.subcommand_matches("send") {
let report_path = Path::new(send_matches.value_of_os("report").unwrap());
let user_email = send_matches.value_of("email").unwrap_or("");
let user_message = send_matches.value_of("message").unwrap_or("");
let cache_dir = mullvad_paths::get_cache_dir()?;
send_problem_report(user_email, user_message, report_path, &cache_dir)
} else {
unreachable!("No sub command given");
}
}
|