use std::io::Write;
use std::path::PathBuf;
use clap::{Args, ValueEnum};
use pointbreak::documents::revision_list_document;
use pointbreak::session::{OrphanVisibility, RefFilterMode, RevisionListOptions, list_revisions};
use crate::cli::output;
#[derive(Debug, Args)]
pub(super) struct RevisionListArgs {
#[arg(long, default_value = ".")]
repo: PathBuf,
#[arg(long)]
object: Option<String>,
#[arg(long = "ref", alias = "branch")]
ref_name: Option<String>,
#[arg(long, value_enum, default_value = "label")]
by: RefFilterByArg,
#[arg(long)]
all: bool,
#[arg(long)]
orphans: bool,
#[arg(long = "integration-ref")]
integration_ref: Option<String>,
#[arg(long)]
worktree: Option<PathBuf>,
#[arg(long, conflicts_with = "compact")]
pretty: bool,
#[arg(long)]
compact: bool,
#[command(flatten)]
format_args: output::FormatArgs,
}
#[derive(Clone, Copy, Debug, Default, ValueEnum)]
#[value(rename_all = "kebab-case")]
enum RefFilterByArg {
#[default]
Label,
Liveness,
}
impl From<RefFilterByArg> for RefFilterMode {
fn from(by: RefFilterByArg) -> Self {
match by {
RefFilterByArg::Label => RefFilterMode::Label,
RefFilterByArg::Liveness => RefFilterMode::Liveness,
}
}
}
pub(super) fn run(
args: RevisionListArgs,
stdout: &mut dyn Write,
) -> Result<(), Box<dyn std::error::Error>> {
let span = tracing::info_span!("shore.revision.list");
let _entered = span.enter();
tracing::debug!(command = "revision.list", "command_start");
let ids = crate::cli::id_resolver::IdResolver::new(&args.repo);
let object = match &args.object {
Some(object) => Some(ids.object(object)?),
None => None,
};
let pretty = args.pretty;
let mut options = RevisionListOptions::new(&args.repo).with_read_for_display(true);
if let Some(ref_name) = args.ref_name {
options = options.with_ref_filter(ref_name, args.by.into());
}
let visibility = if args.orphans {
OrphanVisibility::OrphansOnly
} else if args.all {
OrphanVisibility::All
} else {
OrphanVisibility::HideOrphans
};
options = options.with_orphan_visibility(visibility);
if let Some(integration_ref) = args.integration_ref {
options = options.with_integration_ref(integration_ref);
}
if let Some(worktree) = args.worktree {
options = options.with_worktree_scope(worktree);
}
let mut result = list_revisions(options)?;
if let Some(object) = object.as_deref() {
result
.entries
.retain(|entry| entry.object_id.as_str() == object);
result.revision_count = result.entries.len();
}
let document = revision_list_document(result);
let format = output::resolve_format(
args.format_args.explicit(pretty),
output::OutputFormat::Json,
)?;
output::write_document_json_fallback(stdout, format, &document)
}