1use anyhow::Result;
2use clap::CommandFactory;
3use clap::{error::ErrorKind::ArgumentConflict, Parser};
4use env_logger::Env;
5use log::Level;
6
7use crate::audit;
8use crate::basic_measure::measure;
9use crate::config::bump_epoch;
10use crate::config_cmd;
11use crate::git::git_interop::check_git_version;
12use crate::git::git_interop::{list_commits_with_measurements, prune, pull, push};
13use crate::import::{handle_import, ImportOptions};
14use crate::measurement_storage::{add_to_commit as add, remove_measurements_from_commits};
15use crate::reporting::report;
16use crate::reset;
17use crate::size;
18use crate::stats::ReductionFunc;
19use crate::status;
20use git_perf_cli_types::{Cli, Commands};
21
22pub fn handle_calls() -> Result<()> {
23 let cli = Cli::parse();
24 let logger_level = match cli.verbose {
25 0 => Level::Warn,
26 1 => Level::Info,
27 2 => Level::Debug,
28 _ => Level::Trace,
29 };
30 env_logger::Builder::from_env(Env::default().default_filter_or(logger_level.as_str())).init();
31
32 check_git_version()?;
33
34 match cli.command {
35 Commands::Measure {
36 repetitions,
37 measurement,
38 commit,
39 command,
40 } => {
41 let commit = commit.as_deref().unwrap_or("HEAD");
42 measure(
43 commit,
44 &measurement.name,
45 repetitions,
46 &command,
47 &measurement.key_value,
48 )
49 }
50 Commands::Add {
51 value,
52 measurement,
53 commit,
54 } => {
55 let commit = commit.as_deref().unwrap_or("HEAD");
56 add(commit, &measurement.name, value, &measurement.key_value)
57 }
58 Commands::Import {
59 format,
60 file,
61 commit,
62 prefix,
63 metadata,
64 filter,
65 dry_run,
66 verbose,
67 } => {
68 let commit = commit.as_deref().unwrap_or("HEAD").to_string();
69 handle_import(ImportOptions {
70 commit,
71 format,
72 file,
73 prefix,
74 metadata,
75 filter,
76 dry_run,
77 verbose,
78 })
79 }
80 Commands::Push { remote } => push(None, remote.as_deref()),
81 Commands::Pull {} => pull(None),
82 Commands::Report {
83 commit,
84 output,
85 separate_by,
86 report_history,
87 measurement,
88 key_value,
89 aggregate_by,
90 filter,
91 template,
92 custom_css,
93 title,
94 show_epochs,
95 show_changes,
96 } => {
97 let commit = commit.as_deref().unwrap_or("HEAD");
98
99 let combined_patterns =
101 crate::filter::combine_measurements_and_filters(&measurement, &filter);
102
103 let template_config = crate::reporting::ReportTemplateConfig {
104 template_path: template,
105 custom_css_path: custom_css,
106 title,
107 };
108
109 report(
110 commit,
111 output,
112 separate_by,
113 report_history.max_count,
114 &key_value,
115 aggregate_by.map(ReductionFunc::from),
116 &combined_patterns,
117 template_config,
118 show_epochs,
119 show_changes,
120 )
121 }
122 Commands::Audit {
123 commit,
124 measurement,
125 report_history,
126 selectors,
127 min_measurements,
128 aggregate_by,
129 sigma,
130 dispersion_method,
131 filter,
132 no_change_point_warning,
133 } => {
134 let commit = commit.as_deref().unwrap_or("HEAD");
135 if measurement.is_empty() && filter.is_empty() {
138 Cli::command()
139 .error(
140 clap::error::ErrorKind::MissingRequiredArgument,
141 "At least one of --measurement or --filter must be provided",
142 )
143 .exit()
144 }
145
146 if let Some(min_count) = min_measurements {
148 if report_history.max_count < min_count.into() {
149 Cli::command().error(ArgumentConflict, format!("The minimal number of measurements ({}) cannot be more than the maximum number of measurements ({})", min_count, report_history.max_count)).exit()
150 }
151 }
152
153 let combined_patterns =
155 crate::filter::combine_measurements_and_filters(&measurement, &filter);
156
157 audit::audit_multiple(
158 commit,
159 report_history.max_count,
160 min_measurements,
161 &selectors,
162 aggregate_by.map(ReductionFunc::from),
163 sigma,
164 dispersion_method.map(crate::stats::DispersionMethod::from),
165 &combined_patterns,
166 no_change_point_warning,
167 )
168 }
169 Commands::BumpEpoch { measurements } => {
170 for measurement in measurements {
171 bump_epoch(&measurement)?;
172 }
173 Ok(())
174 }
175 Commands::Prune {} => prune(),
176 Commands::Status { detailed } => status::show_status(detailed),
177 Commands::Reset { dry_run, force } => reset::reset_measurements(dry_run, force),
178 Commands::Remove {
179 older_than,
180 no_prune,
181 dry_run,
182 } => remove_measurements_from_commits(older_than, !no_prune, dry_run),
183 Commands::ListCommits {} => {
184 let commits = list_commits_with_measurements()?;
185 for commit in commits {
186 println!("{}", commit);
187 }
188 Ok(())
189 }
190 Commands::Size {
191 detailed,
192 format,
193 disk_size,
194 include_objects,
195 } => size::calculate_measurement_size(detailed, format, disk_size, include_objects),
196 Commands::Config {
197 list,
198 detailed,
199 format,
200 validate,
201 measurement,
202 } => {
203 if list {
204 config_cmd::list_config(detailed, format, validate, measurement)
205 } else {
206 anyhow::bail!("config command requires --list flag (try: git perf config --list)");
209 }
210 }
211 }
212}