140 lines · 5.1 KB · Rust
RawDownload
// Copyright 2024 The Jujutsu Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License. use clap_complete::ArgValueCandidates;use itertools::Itertools as _;use jj_lib::operation::Operation; use super::diff::show_op_diff;use crate::cli_util::CommandHelper;use crate::cli_util::LogContentFormat;use crate::command_error::CommandError;use crate::complete;use crate::diff_util::DiffFormatArgs;use crate::diff_util::DiffRenderer;use crate::diff_util::diff_formats_for_log;use crate::graphlog::GraphStyle;use crate::templater::TemplateRenderer;use crate::ui::Ui; /// Show changes to the repository in an operation#[derive(clap::Args, Clone, Debug)]pub struct OperationShowArgs {    /// Show repository changes in this operation, compared to its parent(s)    #[arg(default_value = "@", add = ArgValueCandidates::new(complete::operations))]    operation: String,    /// Don't show the graph, show a flat list of modified changes    #[arg(long, short = 'G')]    no_graph: bool,    /// Render the operation using the given template    ///    /// You can specify arbitrary template expressions using the    /// [built-in keywords]. See [`jj help -k templates`] for more    /// information.    ///    /// [built-in keywords]:    ///     https://jj-vcs.github.io/jj/latest/templates/#operation-keywords    ///    /// [`jj help -k templates`]:    ///     https://jj-vcs.github.io/jj/latest/templates/    #[arg(long, short = 'T', add = ArgValueCandidates::new(complete::template_aliases))]    template: Option<String>,    /// Show patch of modifications to changes    ///    /// If the previous version has different parents, it will be temporarily    /// rebased to the parents of the new version, so the diff is not    /// contaminated by unrelated changes.    #[arg(long, short = 'p')]    patch: bool,    /// Do not show operation diff    #[arg(long, conflicts_with_all = ["patch", "DiffFormatArgs"])]    no_op_diff: bool,    #[command(flatten)]    diff_format: DiffFormatArgs,} pub fn cmd_op_show(    ui: &mut Ui,    command: &CommandHelper,    args: &OperationShowArgs,) -> Result<(), CommandError> {    let workspace_command = command.workspace_helper(ui)?;    let workspace_env = workspace_command.env();    let repo_loader = workspace_command.workspace().repo_loader();    let settings = workspace_command.settings();    let op = workspace_command.resolve_single_op(&args.operation)?;    let parent_ops: Vec<_> = op.parents().try_collect()?;    let merged_parent_op = repo_loader.merge_operations(parent_ops.clone(), None)?;    let parent_repo = repo_loader.load_at(&merged_parent_op)?;    let repo = repo_loader.load_at(&op)?;     let id_prefix_context = workspace_env.new_id_prefix_context();    let commit_summary_template = {        let language = workspace_env.commit_template_language(repo.as_ref(), &id_prefix_context);        let text = settings.get_string("templates.commit_summary")?;        workspace_env            .parse_template(ui, &language, &text)?            .labeled(["op_show", "commit"])    };     let graph_style = GraphStyle::from_settings(settings)?;    let with_content_format = LogContentFormat::new(ui, settings)?;    let diff_renderer = {        let formats = diff_formats_for_log(settings, &args.diff_format, args.patch)?;        let path_converter = workspace_env.path_converter();        let conflict_marker_style = workspace_env.conflict_marker_style();        (!formats.is_empty()).then(|| {            DiffRenderer::new(                repo.as_ref(),                path_converter,                conflict_marker_style,                formats,            )        })    };     let template: TemplateRenderer<Operation> = {        let text = match &args.template {            Some(value) => value.to_owned(),            None => settings.get_string("templates.op_show")?,        };        workspace_command            .parse_operation_template(ui, &text)?            .labeled(["op_show", "operation"])    };     ui.request_pager();    let mut formatter = ui.stdout_formatter();    template.format(&op, formatter.as_mut())?;     if !args.no_op_diff {        // TODO: Merged repo may have newly rebased commits, which wouldn't exist in        // the index. (#4465)        if parent_ops.len() > 1 {            return Ok(());        }        show_op_diff(            ui,            formatter.as_mut(),            repo.as_ref(),            &parent_repo,            &repo,            &commit_summary_template,            (!args.no_graph).then_some(graph_style),            &with_content_format,            diff_renderer.as_ref(),        )?;    }    Ok(())}