codeberg_cli/actions/auth/
list.rs1use crate::actions::GlobalArgs;
2use crate::paths::berg_data_dir;
3use crate::render::json::JsonToStdout;
4use crate::types::context::BergContext;
5use crate::types::output::OutputMode;
6use miette::IntoDiagnostic;
7
8use clap::Parser;
9
10#[derive(Parser, Debug)]
12pub struct ListArgs {}
13
14impl ListArgs {
15 pub async fn run(self, global_args: GlobalArgs) -> miette::Result<()> {
16 let ctx = BergContext::new(self, global_args).await?;
17 let data_dir = berg_data_dir()?;
18
19 let instances = data_dir
20 .read_dir()
21 .into_diagnostic()?
22 .filter_map(|dir| {
23 let entry = dir.ok()?;
24
25 let logged_in = entry.metadata().is_ok_and(|metadata| metadata.is_dir())
26 && entry
27 .path()
28 .read_dir()
29 .into_iter()
30 .flatten()
31 .any(|content| content.is_ok_and(|content| content.file_name() == "TOKEN"));
32
33 Some(Instance {
34 base_url: entry.file_name().display().to_string(),
35 logged_in,
36 })
37 })
38 .collect::<Vec<_>>();
39
40 match ctx.global_args.output_mode {
41 OutputMode::Pretty => {
42 present_instance_list(ctx, instances);
43 }
44 OutputMode::Json => {
45 instances.print_json()?;
46 }
47 }
48
49 Ok(())
50 }
51}
52
53#[derive(Debug, Clone, serde::Serialize)]
54struct Instance {
55 base_url: String,
56 logged_in: bool,
57}
58
59fn present_instance_list(ctx: BergContext<ListArgs>, instances: Vec<Instance>) {
60 let issues_empty = instances.is_empty();
61
62 let table = ctx
63 .make_table()
64 .set_header(vec!["Base URL", "Logged In"])
65 .add_rows(instances.into_iter().map(|instance| {
66 let Instance {
67 base_url,
68 logged_in,
69 } = instance;
70 vec![base_url, String::from(if logged_in { "Yes" } else { "No" })]
71 }));
72
73 let header = format!(
74 "Instances{}",
75 if issues_empty {
76 " (empty)"
77 } else {
78 Default::default()
79 }
80 );
81
82 let underscore = "=".repeat(header.len());
83 let out = [header, underscore, table.show()].join("\n");
84
85 println!("{out}");
86}