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;
14use crate::measurement_storage::{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 command,
36 measurement,
37 } => measure(
38 &measurement.name,
39 repetitions,
40 &command,
41 &measurement.key_value,
42 ),
43 Commands::Add { value, measurement } => {
44 add(&measurement.name, value, &measurement.key_value)
45 }
46 Commands::Import {
47 format,
48 file,
49 prefix,
50 metadata,
51 filter,
52 dry_run,
53 verbose,
54 } => handle_import(format, file, prefix, metadata, filter, dry_run, verbose),
55 Commands::Push { remote } => push(None, remote.as_deref()),
56 Commands::Pull {} => pull(None),
57 Commands::Report {
58 output,
59 separate_by,
60 report_history,
61 measurement,
62 key_value,
63 aggregate_by,
64 filter,
65 } => {
66 let combined_patterns =
68 crate::filter::combine_measurements_and_filters(&measurement, &filter);
69
70 report(
71 output,
72 separate_by,
73 report_history.max_count,
74 &key_value,
75 aggregate_by.map(ReductionFunc::from),
76 &combined_patterns,
77 )
78 }
79 Commands::Audit {
80 measurement,
81 report_history,
82 selectors,
83 min_measurements,
84 aggregate_by,
85 sigma,
86 dispersion_method,
87 filter,
88 } => {
89 if measurement.is_empty() && filter.is_empty() {
92 Cli::command()
93 .error(
94 clap::error::ErrorKind::MissingRequiredArgument,
95 "At least one of --measurement or --filter must be provided",
96 )
97 .exit()
98 }
99
100 if let Some(min_count) = min_measurements {
102 if report_history.max_count < min_count.into() {
103 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()
104 }
105 }
106
107 let combined_patterns =
109 crate::filter::combine_measurements_and_filters(&measurement, &filter);
110
111 audit::audit_multiple(
112 report_history.max_count,
113 min_measurements,
114 &selectors,
115 aggregate_by.map(ReductionFunc::from),
116 sigma,
117 dispersion_method.map(crate::stats::DispersionMethod::from),
118 &combined_patterns,
119 )
120 }
121 Commands::BumpEpoch { measurements } => {
122 for measurement in measurements {
123 bump_epoch(&measurement)?;
124 }
125 Ok(())
126 }
127 Commands::Prune {} => prune(),
128 Commands::Remove {
129 older_than,
130 no_prune,
131 } => remove_measurements_from_commits(older_than, !no_prune),
132 Commands::ListCommits {} => {
133 let commits = list_commits_with_measurements()?;
134 for commit in commits {
135 println!("{}", commit);
136 }
137 Ok(())
138 }
139 Commands::Size {
140 detailed,
141 format,
142 disk_size,
143 include_objects,
144 } => size::calculate_measurement_size(detailed, format, disk_size, include_objects),
145 Commands::Config {
146 list,
147 detailed,
148 format,
149 validate,
150 measurement,
151 } => {
152 if list {
153 config_cmd::list_config(detailed, format, validate, measurement)
154 } else {
155 anyhow::bail!("config command requires --list flag (try: git perf config --list)");
158 }
159 }
160 }
161}