//! Published packages, and the forge's own instructions for consuming them.
//!
//! Format labels and summaries come from the server rather than a table
//! here: a new registry format lands server-side and this client lists it
//! correctly without being rebuilt, which is the opposite of how a
//! hardcoded format list ages.
use anyhow::Result;
use crate::cli::PackageCommand;
use crate::commands::Ctx;
use crate::output::{Table, Tone, ago, bold, bytes, heading, note, paint, truncate};
pub async fn run(ctx: &Ctx, command: &PackageCommand) -> Result<()> {
let repo = ctx.repo()?;
match command {
PackageCommand::List => {
let res = ctx.api.packages(&repo).await?;
if ctx.emitted(&res.raw)? {
return Ok(());
}
let populated: Vec<_> = res
.formats
.iter()
.filter(|f| !f.packages.is_empty())
.collect();
if populated.is_empty() {
note(&format!("{repo} has published no packages."));
if !res.available_formats.is_empty() {
note(&format!(
"This forge can host: {}. See `gg package usage <format>`.",
res.available_formats.join(", ")
));
}
return Ok(());
}
for format in populated {
println!("{}", bold(&format.label));
if let Some(summary) = format.summary.as_deref().filter(|s| !s.is_empty()) {
note(summary);
}
let mut table = Table::new(["NAME", "LATEST", "KIND", "UPDATED", "INSTALL"]);
for pkg in &format.packages {
table.row([
pkg.name.clone(),
pkg.latest_version.clone().unwrap_or_else(|| "—".into()),
pkg.kind.clone().unwrap_or_default(),
ago(pkg.updated_at.as_deref()),
truncate(pkg.install_line.as_deref().unwrap_or(""), 44),
]);
}
table.print();
println!();
}
Ok(())
}
PackageCommand::Show { format, name } => {
let res = ctx.api.package(&repo, format, name).await?;
if ctx.emitted(&res.raw)? {
return Ok(());
}
heading(&format!("{} ({})", res.name, res.format));
if let Some(kind) = res.kind.as_deref() {
println!("kind {kind}");
}
println!("latest {}", res.latest_version.as_deref().unwrap_or("—"));
for version in &res.versions {
println!();
let yanked = if version.yanked {
paint(
&format!(
" yanked{}",
version
.yanked_reason
.as_deref()
.map(|r| format!(": {r}"))
.unwrap_or_default()
),
Tone::Bad,
)
} else {
String::new()
};
println!(
"{}{} {} {}",
bold(&version.version),
yanked,
bytes(version.size),
ago(version.pushed_at.as_deref())
);
if let Some(line) = version.install_line.as_deref().filter(|l| !l.is_empty()) {
println!(" {line}");
}
for file in &version.files {
println!(
" {} {} {}",
file.filename,
bytes(file.size),
file.content_type.as_deref().unwrap_or("")
);
}
}
Ok(())
}
PackageCommand::Usage { format } => {
let res = ctx.api.package_usage(&repo, format).await?;
if ctx.emitted(&res.raw)? {
return Ok(());
}
heading(&res.label);
if let Some(summary) = res.summary.as_deref().filter(|s| !s.is_empty()) {
println!("{summary}");
}
for url in [&res.repository_url, &res.namespace_url, &res.key_url]
.into_iter()
.flatten()
{
note(url);
}
for section in &res.sections {
println!("\n{}", bold(§ion.title));
for step in §ion.steps {
println!("\n {}", step.label);
// Printed verbatim: every URL in here is one only the
// server can know, so the client formats and never builds.
for line in step.code.lines() {
println!(" {line}");
}
}
}
Ok(())
}
}
}
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
5.1 KiB · text
History
b868907