use std::slice;
use clap::ArgGroup;
use clap_complete::ArgValueCompleter;
use tracing::instrument;
use crate::cli_util::CommandHelper;
use crate::cli_util::RevisionArg;
use crate::cli_util::print_unmatched_explicit_paths;
use crate::command_error::CommandError;
use crate::complete;
use crate::diff_util::DiffFormatArgs;
use crate::ui::Ui;
#[derive(clap::Args, Clone, Debug)]
#[command(group(ArgGroup::new("to_diff").args(&["from", "to"]).multiple(true).required(true)))]
#[command(mut_arg("ignore_all_space", |a| a.short('w')))]
#[command(mut_arg("ignore_space_change", |a| a.short('b')))]
pub(crate) struct InterdiffArgs {
#[arg(long, short, value_name = "REVSET")]
#[arg(add = ArgValueCompleter::new(complete::revset_expression_all))]
from: Option<RevisionArg>,
#[arg(long, short, value_name = "REVSET")]
#[arg(add = ArgValueCompleter::new(complete::revset_expression_all))]
to: Option<RevisionArg>,
#[arg(value_name = "FILESETS", value_hint = clap::ValueHint::AnyPath)]
#[arg(add = ArgValueCompleter::new(complete::interdiff_files))]
paths: Vec<String>,
#[command(flatten)]
format: DiffFormatArgs,
}
#[instrument(skip_all)]
pub(crate) async fn cmd_interdiff(
ui: &mut Ui,
command: &CommandHelper,
args: &InterdiffArgs,
) -> Result<(), CommandError> {
let workspace_command = command.workspace_helper(ui)?;
let from = workspace_command
.resolve_single_rev(ui, args.from.as_ref().unwrap_or(&RevisionArg::AT))
.await?;
let to = workspace_command
.resolve_single_rev(ui, args.to.as_ref().unwrap_or(&RevisionArg::AT))
.await?;
let repo = workspace_command.repo();
let fileset_expression = workspace_command.parse_file_patterns(ui, &args.paths)?;
let matcher = fileset_expression.to_matcher();
print_unmatched_explicit_paths(
ui,
&workspace_command,
&fileset_expression,
[
&from.parent_tree(repo.as_ref()).await?,
&from.tree(),
&to.parent_tree(repo.as_ref()).await?,
&to.tree(),
],
)?;
let diff_renderer = workspace_command.diff_renderer_for(&args.format)?;
ui.request_pager();
diff_renderer
.show_inter_diff(
ui,
ui.stdout_formatter().as_mut(),
slice::from_ref(&from),
&to,
matcher.as_ref(),
ui.term_width(),
)
.await?;
Ok(())
}