Skip to main content

codeberg_cli/actions/repo/
list.rs

1use crate::render::json::JsonToStdout;
2use crate::render::option::option_display;
3use crate::{actions::GlobalArgs, types::context::BergContext};
4use clap::Parser;
5use clap::ValueEnum;
6use forgejo_api::structs::{
7    Repository, UserCurrentListReposQuery, UserCurrentListReposQueryOrderBy,
8};
9use miette::IntoDiagnostic;
10use strum::{Display, EnumIter, EnumString, IntoStaticStr};
11
12/// List user current active repositories
13#[derive(Debug, Parser, Clone, Copy)]
14pub struct RepoListArgs {
15    /// Order the displayed repositories by different criteria
16    #[arg(short, long, value_enum, name = "ORDER BY", default_value_t = OrderBy::Name)]
17    pub order_by: OrderBy,
18}
19
20#[derive(
21    Debug,
22    Clone,
23    Copy,
24    Default,
25    PartialEq,
26    Eq,
27    Display,
28    EnumString,
29    ValueEnum,
30    EnumIter,
31    IntoStaticStr,
32)]
33pub enum OrderBy {
34    #[default]
35    Name,
36    Id,
37    Newest,
38    Oldest,
39    Recentupdate,
40    Leastupdate,
41    Reversealphabetically,
42    Alphabetically,
43    Reversesize,
44    Size,
45    Reversegitsize,
46    Gitsize,
47    Reverselfssize,
48    Lfssize,
49    Moststars,
50    Feweststars,
51    Mostforks,
52    Fewestforks,
53}
54
55impl From<OrderBy> for UserCurrentListReposQueryOrderBy {
56    fn from(value: OrderBy) -> Self {
57        match value {
58            OrderBy::Name => Self::Name,
59            OrderBy::Id => Self::Id,
60            OrderBy::Newest => Self::Newest,
61            OrderBy::Oldest => Self::Oldest,
62            OrderBy::Recentupdate => Self::Recentupdate,
63            OrderBy::Leastupdate => Self::Leastupdate,
64            OrderBy::Reversealphabetically => Self::Reversealphabetically,
65            OrderBy::Alphabetically => Self::Alphabetically,
66            OrderBy::Reversesize => Self::Reversesize,
67            OrderBy::Size => Self::Size,
68            OrderBy::Reversegitsize => Self::Reversegitsize,
69            OrderBy::Gitsize => Self::Gitsize,
70            OrderBy::Reverselfssize => Self::Reverselfssize,
71            OrderBy::Lfssize => Self::Lfssize,
72            OrderBy::Moststars => Self::Moststars,
73            OrderBy::Feweststars => Self::Feweststars,
74            OrderBy::Mostforks => Self::Mostforks,
75            OrderBy::Fewestforks => Self::Fewestforks,
76        }
77    }
78}
79
80impl RepoListArgs {
81    pub async fn run(self, global_args: GlobalArgs) -> miette::Result<()> {
82        let ctx = BergContext::new(self, global_args).await?;
83
84        let (_, repos) = ctx
85            .client
86            .user_current_list_repos(UserCurrentListReposQuery {
87                order_by: Some(ctx.args.order_by.into()),
88            })
89            .await
90            .into_diagnostic()?;
91
92        match ctx.global_args.output_mode {
93            crate::types::output::OutputMode::Pretty => {
94                present_repos(ctx, repos).await?;
95            }
96            crate::types::output::OutputMode::Json => {
97                repos.print_json()?;
98            }
99        }
100
101        Ok(())
102    }
103}
104
105async fn present_repos(
106    ctx: BergContext<RepoListArgs>,
107    repos: Vec<Repository>,
108) -> miette::Result<()> {
109    let table = ctx
110        .make_table()
111        .set_header(vec!["Name", "Description", "Size", "Visibility", "Updated"])
112        .add_rows(repos.iter().map(|repo| {
113            let Repository {
114                name,
115                description,
116                updated_at,
117                private,
118                archived,
119                fork,
120                size,
121                ..
122            } = repo;
123
124            let repo_visibility = if private.unwrap_or(false) {
125                "Private"
126            } else {
127                "Public"
128            };
129            let is_archived = archived.unwrap_or(false);
130            let is_fork = fork.unwrap_or(false);
131
132            let mut info_arr = vec![repo_visibility];
133
134            if is_archived {
135                info_arr.push("Archived");
136            }
137
138            if is_fork {
139                info_arr.push("Fork");
140            }
141
142            vec![
143                option_display(name),
144                option_display(description),
145                option_display(size),
146                info_arr.join(", "),
147                option_display(updated_at),
148            ]
149        }));
150
151    println!("{tbl}", tbl = table.show());
152
153    Ok(())
154}