11use std:: { collections:: HashSet , convert:: TryFrom , io:: Write } ;
22
33use anyhow:: { Context , Result } ;
4+ use chrono:: SecondsFormat ;
45use clap:: Parser ;
56
67use lintrunner:: {
@@ -9,7 +10,8 @@ use lintrunner::{
910 lint_config:: { get_linters_from_config, LintRunnerConfig } ,
1011 log_utils:: setup_logger,
1112 path:: AbsPath ,
12- persistent_data:: { PersistentDataStore } ,
13+ persistent_data:: { ExitInfo , PersistentDataStore , RunInfo } ,
14+ rage:: do_rage,
1315 render:: print_error,
1416 PathsOpt , RenderOpt , RevisionOpt ,
1517} ;
@@ -102,6 +104,13 @@ enum SubCommand {
102104
103105 /// Run linters. This is the default if no subcommand is provided.
104106 Lint ,
107+
108+ /// Create a bug report for a past invocation of lintrunner.
109+ Rage {
110+ /// Choose a specific invocation to report on. 0 is the most recent run.
111+ #[ clap( long, short) ]
112+ invocation : Option < usize > ,
113+ } ,
105114}
106115
107116fn do_main ( ) -> Result < i32 > {
@@ -128,9 +137,17 @@ fn do_main() -> Result<i32> {
128137 ( _, _) => log:: LevelFilter :: Trace ,
129138 } ;
130139
131- let persistent_data_store = PersistentDataStore :: new ( & config_path) ?;
140+ let run_info = RunInfo {
141+ args : std:: env:: args ( ) . collect ( ) ,
142+ timestamp : chrono:: Local :: now ( ) . to_rfc3339_opts ( SecondsFormat :: Secs , true ) ,
143+ } ;
144+ let persistent_data_store = PersistentDataStore :: new ( & config_path, run_info) ?;
132145
133- setup_logger ( log_level, args. force_color ) ?;
146+ setup_logger (
147+ log_level,
148+ & persistent_data_store. log_file ( ) ,
149+ args. force_color ,
150+ ) ?;
134151
135152 let cmd = args. cmd . unwrap_or ( SubCommand :: Lint ) ;
136153 let lint_runner_config = LintRunnerConfig :: new ( & config_path) ?;
@@ -194,7 +211,7 @@ fn do_main() -> Result<i32> {
194211 PathsOpt :: Auto
195212 } ;
196213
197- match cmd {
214+ let res = match cmd {
198215 SubCommand :: Init { dry_run } => {
199216 // Just run initialization commands, don't actually lint.
200217 do_init ( linters, dry_run, & persistent_data_store, & config_path)
@@ -222,7 +239,24 @@ fn do_main() -> Result<i32> {
222239 revision_opt,
223240 )
224241 }
225- }
242+ SubCommand :: Rage { invocation } => do_rage ( & persistent_data_store, invocation) ,
243+ } ;
244+
245+ let exit_info = match & res {
246+ Ok ( code) => ExitInfo {
247+ code : * code,
248+ err : None ,
249+ } ,
250+ Err ( err) => ExitInfo {
251+ code : 1 ,
252+ err : Some ( err. to_string ( ) ) ,
253+ } ,
254+ } ;
255+
256+ // Write data related to this run out to the persistent data store.
257+ persistent_data_store. write_run_info ( exit_info) ?;
258+
259+ res
226260}
227261
228262fn main ( ) {
0 commit comments