//! `gg` — a command-line client for a GitGud forge.
//!
//! Speaks the same `/api/mobile/v1` surface as the Android app, so the two
//! stay in step: a capability that exists on the phone exists here, and a
//! field that changes shape breaks both at once rather than drifting.
mod api;
mod cli;
mod commands;
mod config;
mod output;
mod tui;
use anyhow::Result;
use clap::Parser;
use cli::{Cli, Command};
use commands::Ctx;
#[tokio::main]
async fn main() {
restore_sigpipe();
if let Err(e) = run().await {
// `{:#}` so the cause chain lands on one line: "couldn't reach
// https://forge…: dns error" says more than either half alone.
eprintln!("{}: {:#}", output::paint("error", output::Tone::Bad), e);
std::process::exit(1);
}
}
/// Die quietly when a pager or `head` closes the pipe.
///
/// Rust masks SIGPIPE at startup, which turns `gg ci logs | head` into
/// a panic on a broken pipe rather than the silent exit every other
/// command-line tool manages.
#[cfg(unix)]
fn restore_sigpipe() {
const SIGPIPE: i32 = 13;
const SIG_DFL: usize = 0;
unsafe extern "C" {
fn signal(signum: i32, handler: usize) -> usize;
}
unsafe {
signal(SIGPIPE, SIG_DFL);
}
}
#[cfg(not(unix))]
fn restore_sigpipe() {}
async fn run() -> Result<()> {
let args = Cli::parse();
// Login and logout are the two commands that can't require credentials
// to already exist.
match &args.command {
Command::Login(login) => {
return commands::auth::login(
login,
args.url.as_deref(),
args.token.as_deref(),
args.json,
)
.await;
}
Command::Logout => return commands::auth::logout(args.json),
_ => {}
}
let cfg = config::Config::load()?;
let creds = config::resolve(args.url.as_deref(), args.token.as_deref(), &cfg)?;
let ctx = Ctx {
api: api::Client::new(&creds)?,
base_url: creds.url.clone(),
cfg,
repo_flag: args.repo.clone(),
json: args.json,
};
match &args.command {
Command::Login(_) | Command::Logout => unreachable!("handled above"),
Command::Whoami => commands::auth::whoami(&ctx).await,
Command::RepoList(list) => commands::repo::list(&ctx, list).await,
Command::Repo(repo) => commands::repo::show(&ctx, repo).await,
Command::Ci(ci) => commands::ci::run(&ctx, &ci.command).await,
Command::Issue(issue) => commands::issue::run(&ctx, &issue.command).await,
Command::Pull(pull) => commands::pull::run(&ctx, &pull.command).await,
Command::Labels(labels) => commands::label::run(&ctx, labels.command.as_ref()).await,
Command::Wiki(wiki) => commands::wiki::run(&ctx, &wiki.command).await,
Command::Package(package) => commands::package::run(&ctx, &package.command).await,
Command::Dashboard(dashboard) => tui::run(&ctx, dashboard).await,
}
}
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
3.0 KiB · text
History
df92b0a