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