use crate::render::json::JsonToStdout;
use crate::render::option::option_display;
use crate::{actions::GlobalArgs, types::context::BergContext};
use clap::Parser;
use clap::ValueEnum;
use forgejo_api::structs::{
Repository, UserCurrentListReposQuery, UserCurrentListReposQueryOrderBy,
};
use miette::IntoDiagnostic;
use strum::{Display, EnumIter, EnumString, IntoStaticStr};
#[derive(Debug, Parser, Clone, Copy)]
pub struct RepoListArgs {
#[arg(short, long, value_enum, name = "ORDER BY", default_value_t = OrderBy::Name)]
pub order_by: OrderBy,
}
#[derive(
Debug,
Clone,
Copy,
Default,
PartialEq,
Eq,
Display,
EnumString,
ValueEnum,
EnumIter,
IntoStaticStr,
)]
pub enum OrderBy {
#[default]
Name,
Id,
Newest,
Oldest,
Recentupdate,
Leastupdate,
Reversealphabetically,
Alphabetically,
Reversesize,
Size,
Reversegitsize,
Gitsize,
Reverselfssize,
Lfssize,
Moststars,
Feweststars,
Mostforks,
Fewestforks,
}
impl From<OrderBy> for UserCurrentListReposQueryOrderBy {
fn from(value: OrderBy) -> Self {
match value {
OrderBy::Name => Self::Name,
OrderBy::Id => Self::Id,
OrderBy::Newest => Self::Newest,
OrderBy::Oldest => Self::Oldest,
OrderBy::Recentupdate => Self::Recentupdate,
OrderBy::Leastupdate => Self::Leastupdate,
OrderBy::Reversealphabetically => Self::Reversealphabetically,
OrderBy::Alphabetically => Self::Alphabetically,
OrderBy::Reversesize => Self::Reversesize,
OrderBy::Size => Self::Size,
OrderBy::Reversegitsize => Self::Reversegitsize,
OrderBy::Gitsize => Self::Gitsize,
OrderBy::Reverselfssize => Self::Reverselfssize,
OrderBy::Lfssize => Self::Lfssize,
OrderBy::Moststars => Self::Moststars,
OrderBy::Feweststars => Self::Feweststars,
OrderBy::Mostforks => Self::Mostforks,
OrderBy::Fewestforks => Self::Fewestforks,
}
}
}
impl RepoListArgs {
pub async fn run(self, global_args: GlobalArgs) -> miette::Result<()> {
let ctx = BergContext::new(self, global_args).await?;
let (_, repos) = ctx
.client
.user_current_list_repos(UserCurrentListReposQuery {
order_by: Some(ctx.args.order_by.into()),
})
.await
.into_diagnostic()?;
match ctx.global_args.output_mode {
crate::types::output::OutputMode::Pretty => {
present_repos(ctx, repos).await?;
}
crate::types::output::OutputMode::Json => {
repos.print_json()?;
}
}
Ok(())
}
}
async fn present_repos(
ctx: BergContext<RepoListArgs>,
repos: Vec<Repository>,
) -> miette::Result<()> {
let table = ctx
.make_table()
.set_header(vec!["Name", "Description", "Size", "Visibility", "Updated"])
.add_rows(repos.iter().map(|repo| {
let Repository {
name,
description,
updated_at,
private,
archived,
fork,
size,
..
} = repo;
let repo_visibility = if private.unwrap_or(false) {
"Private"
} else {
"Public"
};
let is_archived = archived.unwrap_or(false);
let is_fork = fork.unwrap_or(false);
let mut info_arr = vec![repo_visibility];
if is_archived {
info_arr.push("Archived");
}
if is_fork {
info_arr.push("Fork");
}
vec![
option_display(name),
option_display(description),
option_display(size),
info_arr.join(", "),
option_display(updated_at),
]
}));
println!("{tbl}", tbl = table.show());
Ok(())
}