cargo/ops/cargo_report/
sessions.rs1use annotate_snippets::Level;
4
5use crate::CargoResult;
6use crate::GlobalContext;
7use crate::core::Workspace;
8use crate::ops::cargo_report::util::list_log_files;
9use crate::util::BuildLogger;
10
11pub struct ReportSessionsOptions {
12 pub limit: usize,
13}
14
15pub fn report_sessions(
16 gctx: &GlobalContext,
17 ws: Option<&Workspace<'_>>,
18 opts: ReportSessionsOptions,
19) -> CargoResult<()> {
20 let ws_run_id = ws.map(BuildLogger::generate_run_id);
21
22 let sessions: Vec<_> = list_log_files(gctx, None)?
24 .filter(|(_, id)| {
25 ws_run_id
26 .as_ref()
27 .map(|ws_run_id| ws_run_id.same_workspace(id))
28 .unwrap_or(true)
29 })
30 .take(opts.limit + 1)
31 .collect();
32
33 if sessions.is_empty() {
34 let context = if let Some(ws) = ws {
35 format!(" for workspace at `{}`", ws.root().display())
36 } else {
37 String::new()
38 };
39 let title = format!("no sessions found{context}");
40 let note = "run build commands with `-Z build-analysis` to generate log files";
41
42 let report = [Level::ERROR
43 .primary_title(title)
44 .element(Level::NOTE.message(note))];
45 gctx.shell().print_report(&report, false)?;
46 return Err(crate::AlreadyPrintedError::new(anyhow::anyhow!("")).into());
47 }
48
49 let truncated = sessions.len() > opts.limit;
50 let display_count = opts.limit.min(sessions.len());
51
52 let mut shell = gctx.shell();
53 let stderr = shell.err();
54
55 if let Some(ws) = ws {
56 writeln!(
57 stderr,
58 "Session IDs for `{}` (most recent first):",
59 ws.root().display(),
60 )?;
61 } else {
62 writeln!(stderr, "Session IDs (most recent first):",)?
63 };
64 writeln!(stderr)?;
65
66 for (_path, run_id) in sessions.iter().take(display_count) {
67 writeln!(stderr, " - {run_id}")?;
68 }
69
70 if truncated {
71 writeln!(stderr)?;
72 writeln!(stderr, "... and more (use --limit N to see more)")?;
73 }
74
75 Ok(())
76}