diff --git a/CHANGELOG.md b/CHANGELOG.md index f619df8621..3f3d45befe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). * New command `jj operation diff` that can compare changes made between two operations. +* New command `jj operation show` that can show the changes made in a single + operation. + ### Fixed bugs * `jj diff --git` no longer shows the contents of binary files. diff --git a/cli/src/commands/operation/mod.rs b/cli/src/commands/operation/mod.rs index 8b45df520e..aef1925c7f 100644 --- a/cli/src/commands/operation/mod.rs +++ b/cli/src/commands/operation/mod.rs @@ -16,6 +16,7 @@ mod abandon; mod diff; mod log; mod restore; +mod show; pub mod undo; use abandon::{cmd_op_abandon, OperationAbandonArgs}; @@ -23,6 +24,7 @@ use clap::Subcommand; use diff::{cmd_op_diff, OperationDiffArgs}; use log::{cmd_op_log, OperationLogArgs}; use restore::{cmd_op_restore, OperationRestoreArgs}; +use show::{cmd_op_show, OperationShowArgs}; use undo::{cmd_op_undo, OperationUndoArgs}; use crate::cli_util::CommandHelper; @@ -39,6 +41,7 @@ pub enum OperationCommand { Diff(OperationDiffArgs), Log(OperationLogArgs), Restore(OperationRestoreArgs), + Show(OperationShowArgs), Undo(OperationUndoArgs), } @@ -52,6 +55,7 @@ pub fn cmd_operation( OperationCommand::Diff(args) => cmd_op_diff(ui, command, args), OperationCommand::Log(args) => cmd_op_log(ui, command, args), OperationCommand::Restore(args) => cmd_op_restore(ui, command, args), + OperationCommand::Show(args) => cmd_op_show(ui, command, args), OperationCommand::Undo(args) => cmd_op_undo(ui, command, args), } } diff --git a/cli/src/commands/operation/show.rs b/cli/src/commands/operation/show.rs new file mode 100644 index 0000000000..56ec6eb9af --- /dev/null +++ b/cli/src/commands/operation/show.rs @@ -0,0 +1,123 @@ +// 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 itertools::Itertools; +use jj_lib::op_walk; + +use super::diff::show_op_diff; +use crate::cli_util::{CommandHelper, LogContentFormat}; +use crate::command_error::{user_error, CommandError}; +use crate::diff_util::DiffFormatArgs; +use crate::operation_templater::OperationTemplateLanguage; +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(visible_alias = "op", default_value = "@")] + operation: String, + /// Don't show the graph, show a flat list of modified changes + #[arg(long)] + no_graph: bool, + /// 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, + #[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 repo = workspace_command.repo(); + let repo_loader = &repo.loader(); + let head_op_str = &command.global_args().at_operation; + let head_ops = if head_op_str == "@" { + // If multiple head ops can't be resolved without merging, let the + // current op be empty. Beware that resolve_op_for_load() will eliminate + // redundant heads whereas get_current_head_ops() won't. + let current_op = op_walk::resolve_op_for_load(repo_loader, head_op_str).ok(); + if let Some(op) = current_op { + vec![op] + } else { + op_walk::get_current_head_ops( + repo_loader.op_store(), + repo_loader.op_heads_store().as_ref(), + )? + } + } else { + vec![op_walk::resolve_op_for_load(repo_loader, head_op_str)?] + }; + let current_op_id = match &*head_ops { + [op] => Some(op.id()), + _ => None, + }; + let op = op_walk::resolve_op_for_load(repo_loader, &args.operation)?; + let parents: Vec<_> = op.parents().try_collect()?; + if parents.is_empty() { + return Err(user_error("Cannot show the root operation")); + } + let parent_op = repo_loader.merge_operations(command.settings(), parents, None)?; + let parent_repo = repo_loader.load_at(&parent_op)?; + let repo = repo_loader.load_at(&op)?; + + // Create a new transaction beginning from `repo`. + let mut workspace_command = + command.for_loaded_repo(ui, command.load_workspace()?, repo.clone())?; + let tx = workspace_command.start_transaction(); + + let with_content_format = LogContentFormat::new(ui, command.settings())?; + + // TODO: Should we make this customizable via clap arg? + let template; + { + let language = OperationTemplateLanguage::new( + repo_loader.op_store().root_operation_id(), + current_op_id, + command.operation_template_extensions(), + ); + let text = command.settings().config().get_string("templates.op_log")?; + template = command + .parse_template( + ui, + &language, + &text, + OperationTemplateLanguage::wrap_operation, + )? + .labeled("op_log"); + } + + ui.request_pager(); + template.format(&op, ui.stdout_formatter().as_mut())?; + + show_op_diff( + ui, + command, + tx, + &parent_repo, + &repo, + !args.no_graph, + &with_content_format, + &args.diff_format, + args.patch, + ) +} diff --git a/cli/tests/cli-reference@.md.snap b/cli/tests/cli-reference@.md.snap index ac3cfae54f..cef02c2fcb 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -64,6 +64,7 @@ This document contains the help content for the `jj` command-line program. * [`jj operation diff`↴](#jj-operation-diff) * [`jj operation log`↴](#jj-operation-log) * [`jj operation restore`↴](#jj-operation-restore) +* [`jj operation show`↴](#jj-operation-show) * [`jj operation undo`↴](#jj-operation-undo) * [`jj parallelize`↴](#jj-parallelize) * [`jj prev`↴](#jj-prev) @@ -1242,6 +1243,7 @@ For information about the operation log, see https://github.com/martinvonz/jj/bl * `diff` — Compare changes to the repository between two operations * `log` — Show the operation log * `restore` — Create a new operation that restores the repo to an earlier state +* `show` — Show changes to the repository in an operation * `undo` — Create a new operation that undoes an earlier operation @@ -1341,6 +1343,39 @@ This restores the repo to the state at the specified operation, effectively undo +## `jj operation show` + +Show changes to the repository in an operation + +**Usage:** `jj operation show [OPTIONS] [OPERATION]` + +###### **Arguments:** + +* `` — Show repository changes in this operation, compared to its parent(s) + + Default value: `@` + +###### **Options:** + +* `--no-graph` — Don't show the graph, show a flat list of modified changes +* `-p`, `--patch` — 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. +* `-s`, `--summary` — For each path, show only whether it was modified, added, or deleted +* `--stat` — Show a histogram of the changes +* `--types` — For each path, show only its type before and after + + The diff is shown as two letters. The first letter indicates the type before and the second letter indicates the type after. '-' indicates that the path was not present, 'F' represents a regular file, `L' represents a symlink, 'C' represents a conflict, and 'G' represents a Git submodule. +* `--name-only` — For each path, show only its path + + Typically useful for shell commands like: `jj diff -r @- --name_only | xargs perl -pi -e's/OLD/NEW/g` +* `--git` — Show a Git-format diff +* `--color-words` — Show a word-level diff with changes indicated only by color +* `--tool ` — Generate diff by external command +* `--context ` — Number of lines of context to show + + + ## `jj operation undo` Create a new operation that undoes an earlier operation diff --git a/cli/tests/test_operations.rs b/cli/tests/test_operations.rs index 0f8739b40c..ca0bc7b47a 100644 --- a/cli/tests/test_operations.rs +++ b/cli/tests/test_operations.rs @@ -993,6 +993,383 @@ fn test_op_diff_patch() { "###); } +#[test] +fn test_op_show() { + let test_env = TestEnvironment::default(); + let git_repo_path = test_env.env_root().join("git-repo"); + let git_repo = init_bare_git_repo(&git_repo_path); + test_env.jj_cmd_ok(test_env.env_root(), &["git", "clone", "git-repo", "repo"]); + let repo_path = test_env.env_root().join("repo"); + + // Overview of op log. + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]); + insta::assert_snapshot!(&stdout, @r###" + @ 984d5ceb039f test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 + │ check out git remote's default branch + │ args: jj git clone git-repo repo + ◉ 817baaeefcbb test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 + │ fetch from git remote into empty repo + │ args: jj git clone git-repo repo + ◉ b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 + │ add workspace 'default' + ◉ 9a7d829846af test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 + │ initialize repo + ◉ 000000000000 root() + "###); + + // The root operation is empty. + let stderr = test_env.jj_cmd_failure(&repo_path, &["op", "show", "0000000"]); + insta::assert_snapshot!(&stderr, @r###" + Error: Cannot show the root operation + "###); + + // Showing the latest operation. + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "@"]); + insta::assert_snapshot!(&stdout, @r###" + 984d5ceb039f test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 + check out git remote's default branch + args: jj git clone git-repo repo + + Changed commits: + ○ Change sqpuoqvxutmz + +sqpuoqvx 9708515f (empty) (no description set) + ○ Change qpvuntsmwlqt + -qpvuntsm hidden 230dd059 (empty) (no description set) + + Changed local branches: + branch-1: + + ulyvmwyz 1d843d1f branch-1 | Commit 1 + - (absent) + + Changed remote branches: + branch-1@origin: + + (tracked) ulyvmwyz 1d843d1f branch-1 | Commit 1 + - (untracked) ulyvmwyz 1d843d1f branch-1 | Commit 1 + "###); + // `jj op show @` should behave identically to `jj op show`. + let stdout_without_op_id = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + assert_eq!(stdout, stdout_without_op_id); + + // Showing a given operation. + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "@-"]); + insta::assert_snapshot!(&stdout, @r###" + 817baaeefcbb test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 + fetch from git remote into empty repo + args: jj git clone git-repo repo + + Changed commits: + ○ Change tqyxmsztkvot + +tqyxmszt 3e785984 branch-3@origin | Commit 3 + ○ Change yuvsmzqkmpws + +yuvsmzqk 3d9189bc branch-2@origin | Commit 2 + ○ Change ulyvmwyzwuwt + +ulyvmwyz 1d843d1f branch-1@origin | Commit 1 + + Changed remote branches: + branch-1@origin: + + (untracked) ulyvmwyz 1d843d1f branch-1@origin | Commit 1 + - (untracked) (absent) + branch-2@origin: + + (untracked) yuvsmzqk 3d9189bc branch-2@origin | Commit 2 + - (untracked) (absent) + branch-3@origin: + + (untracked) tqyxmszt 3e785984 branch-3@origin | Commit 3 + - (untracked) (absent) + "###); + + // Create a conflicted branch using a concurrent operation. + test_env.jj_cmd_ok( + &repo_path, + &[ + "branch", + "set", + "branch-1", + "-r", + "branch-2@origin", + "--at-op", + "@-", + ], + ); + let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["log"]); + insta::assert_snapshot!(&stderr, @r###" + Concurrent modification detected, resolving automatically. + "###); + // Showing a merge operation is empty. + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + 6c131cd79314 test-username@host.example.com 2001-02-03 04:05:14.000 +07:00 - 2001-02-03 04:05:14.000 +07:00 + resolve concurrent operations + args: jj log + "###); + + // Test fetching from git remote. + modify_git_repo(git_repo); + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]); + insta::assert_snapshot!(&stdout, @r###" + "###); + insta::assert_snapshot!(&stderr, @r###" + branch: branch-1@origin [updated] tracked + branch: branch-2@origin [updated] untracked + branch: branch-3@origin [deleted] untracked + Abandoned 1 commits that are no longer reachable. + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + 84466f397d80 test-username@host.example.com 2001-02-03 04:05:16.000 +07:00 - 2001-02-03 04:05:16.000 +07:00 + fetch from git remote(s) origin + args: jj git fetch + + Changed commits: + ○ Change qzxslznxxpoz + +qzxslznx d487febd branch-2@origin | Commit 5 + ○ Change slvtnnzxztqy + +slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4 + ○ Change tqyxmsztkvot + -tqyxmszt hidden 3e785984 Commit 3 + + Changed local branches: + branch-1: + + (added) slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4 + + (added) yuvsmzqk 3d9189bc branch-1?? | Commit 2 + - (added) ulyvmwyz 1d843d1f Commit 1 + - (added) yuvsmzqk 3d9189bc branch-1?? | Commit 2 + + Changed remote branches: + branch-1@origin: + + (tracked) slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4 + - (tracked) ulyvmwyz 1d843d1f Commit 1 + branch-2@origin: + + (untracked) qzxslznx d487febd branch-2@origin | Commit 5 + - (untracked) yuvsmzqk 3d9189bc branch-1?? | Commit 2 + branch-3@origin: + + (untracked) (absent) + - (untracked) tqyxmszt hidden 3e785984 Commit 3 + "###); + + // Test creation of branch. + let (stdout, stderr) = test_env.jj_cmd_ok( + &repo_path, + &["branch", "create", "branch-2", "-r", "branch-2@origin"], + ); + insta::assert_snapshot!(&stdout, @r###" + "###); + insta::assert_snapshot!(&stderr, @r###" + Created 1 branches pointing to qzxslznx d487febd branch-2 branch-2@origin | Commit 5 + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + eea894b7c72f test-username@host.example.com 2001-02-03 04:05:18.000 +07:00 - 2001-02-03 04:05:18.000 +07:00 + create branch branch-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409 + args: jj branch create branch-2 -r branch-2@origin + + Changed local branches: + branch-2: + + qzxslznx d487febd branch-2 branch-2@origin | Commit 5 + - (absent) + "###); + + // Test tracking of branch. + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "track", "branch-2@origin"]); + insta::assert_snapshot!(&stdout, @r###" + "###); + insta::assert_snapshot!(&stderr, @r###" + Started tracking 1 remote branches. + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + d2d43732186a test-username@host.example.com 2001-02-03 04:05:20.000 +07:00 - 2001-02-03 04:05:20.000 +07:00 + track remote branch branch-2@origin + args: jj branch track branch-2@origin + + Changed remote branches: + branch-2@origin: + + (tracked) qzxslznx d487febd branch-2 | Commit 5 + - (untracked) qzxslznx d487febd branch-2 | Commit 5 + "###); + + // Test creation of new commit. + let (stdout, stderr) = + test_env.jj_cmd_ok(&repo_path, &["new", "branch-1@origin", "-m", "new commit"]); + insta::assert_snapshot!(&stdout, @r###" + "###); + insta::assert_snapshot!(&stderr, @r###" + Working copy now at: nkmrtpmo 71fe694d (empty) new commit + Parent commit : slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4 + Added 1 files, modified 0 files, removed 1 files + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + f85f06d144b6 test-username@host.example.com 2001-02-03 04:05:22.000 +07:00 - 2001-02-03 04:05:22.000 +07:00 + new empty commit + args: jj new branch-1@origin -m 'new commit' + + Changed commits: + ○ Change nkmrtpmomlro + +nkmrtpmo 71fe694d (empty) new commit + ○ Change sqpuoqvxutmz + -sqpuoqvx hidden 9708515f (empty) (no description set) + "###); + + // Test updating of local branch. + let (stdout, stderr) = + test_env.jj_cmd_ok(&repo_path, &["branch", "set", "branch-1", "-r", "@"]); + insta::assert_snapshot!(&stdout, @r###" + "###); + insta::assert_snapshot!(&stderr, @r###" + Moved 1 branches to nkmrtpmo 71fe694d branch-1* | (empty) new commit + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + b55c8d9fdc63 test-username@host.example.com 2001-02-03 04:05:24.000 +07:00 - 2001-02-03 04:05:24.000 +07:00 + point branch branch-1 to commit 71fe694da7811a184f404fffe35cd62b0adb3d89 + args: jj branch set branch-1 -r @ + + Changed local branches: + branch-1: + + nkmrtpmo 71fe694d branch-1* | (empty) new commit + - (added) slvtnnzx 4f856199 branch-1@origin | Commit 4 + - (added) yuvsmzqk 3d9189bc Commit 2 + "###); + + // Test deletion of local branch. + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "branch-2"]); + insta::assert_snapshot!(&stdout, @r###" + "###); + insta::assert_snapshot!(&stderr, @r###" + Deleted 1 branches. + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + 25dbc902dbf0 test-username@host.example.com 2001-02-03 04:05:26.000 +07:00 - 2001-02-03 04:05:26.000 +07:00 + delete branch branch-2 + args: jj branch delete branch-2 + + Changed local branches: + branch-2: + + (absent) + - qzxslznx d487febd branch-2@origin | Commit 5 + "###); + + // Test pushing to Git remote. + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "push", "--tracked"]); + insta::assert_snapshot!(&stdout, @r###" + "###); + insta::assert_snapshot!(&stderr, @r###" + Branch changes to push to origin: + Move forward branch branch-1 from 4f856199edbf to 71fe694da781 + Delete branch branch-2 from d487febd08e6 + Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it. + Working copy now at: wvuyspvk 6136f89a (empty) (no description set) + Parent commit : nkmrtpmo 71fe694d branch-1 | (empty) new commit + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]); + insta::assert_snapshot!(&stdout, @r###" + d8d2184e1621 test-username@host.example.com 2001-02-03 04:05:28.000 +07:00 - 2001-02-03 04:05:28.000 +07:00 + push all tracked branches to git remote origin + args: jj git push --tracked + + Changed commits: + ○ Change wvuyspvkupzz + +wvuyspvk 6136f89a (empty) (no description set) + + Changed remote branches: + branch-1@origin: + + (tracked) nkmrtpmo 71fe694d branch-1 | (empty) new commit + - (tracked) slvtnnzx 4f856199 Commit 4 + branch-2@origin: + + (untracked) (absent) + - (tracked) qzxslznx d487febd Commit 5 + "###); +} + +#[test] +fn test_op_show_patch() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); + let repo_path = test_env.env_root().join("repo"); + + // Update working copy with a single file and create new commit. + std::fs::write(repo_path.join("file"), "a").unwrap(); + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["new"]); + insta::assert_snapshot!(&stdout, @""); + insta::assert_snapshot!(&stderr, @r###" + Working copy now at: rlvkpnrz 3444613f (empty) (no description set) + Parent commit : qpvuntsm f3220d78 (no description set) + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "@-", "-p"]); + insta::assert_snapshot!(&stdout, @r###" + 816a0ba42aa6 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00 + snapshot working copy + args: jj new + + Changed commits: + ○ Change qpvuntsmwlqt + +qpvuntsm f3220d78 (no description set) + -qpvuntsm hidden 230dd059 (empty) (no description set) + Added regular file file: + 1: a + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "@", "-p"]); + insta::assert_snapshot!(&stdout, @r###" + 64bb2702ac30 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00 + new empty commit + args: jj new + + Changed commits: + ○ Change rlvkpnrzqnoo + +rlvkpnrz 3444613f (empty) (no description set) + "###); + + // Squash the working copy commit. + std::fs::write(repo_path.join("file"), "b").unwrap(); + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["squash"]); + insta::assert_snapshot!(&stdout, @""); + insta::assert_snapshot!(&stderr, @r###" + Working copy now at: mzvwutvl fec3065d (empty) (no description set) + Parent commit : qpvuntsm 8514f5b4 (no description set) + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "-p"]); + insta::assert_snapshot!(&stdout, @r###" + f40519d9c6c3 test-username@host.example.com 2001-02-03 04:05:11.000 +07:00 - 2001-02-03 04:05:11.000 +07:00 + squash commits into f3220d78b25353bd8fd65988018004b962d0894a + args: jj squash + + Changed commits: + ○ Change mzvwutvlkqwt + │ +mzvwutvl fec3065d (empty) (no description set) + │ ○ Change rlvkpnrzqnoo + ├─╯ -rlvkpnrz hidden e358ef7d (no description set) + │ Modified regular file file: + │ 1 1: ab + ○ Change qpvuntsmwlqt + +qpvuntsm 8514f5b4 (no description set) + -qpvuntsm hidden f3220d78 (no description set) + Modified regular file file: + 1 1: ab + "###); + + // Abandon the working copy commit. + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["abandon"]); + insta::assert_snapshot!(&stdout, @""); + insta::assert_snapshot!(&stderr, @r###" + Abandoned commit mzvwutvl fec3065d (empty) (no description set) + Working copy now at: yqosqzyt fa39592f (empty) (no description set) + Parent commit : qpvuntsm 8514f5b4 (no description set) + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "-p"]); + insta::assert_snapshot!(&stdout, @r###" + 318c9022ebc5 test-username@host.example.com 2001-02-03 04:05:13.000 +07:00 - 2001-02-03 04:05:13.000 +07:00 + abandon commit fec3065ddf4c348827a1e8eee6c49db252135023 + args: jj abandon + + Changed commits: + ○ Change yqosqzytrlsw + +yqosqzyt fa39592f (empty) (no description set) + ○ Change mzvwutvlkqwt + -mzvwutvl hidden fec3065d (empty) (no description set) + "###); +} + fn init_bare_git_repo(git_repo_path: &Path) -> git2::Repository { let git_repo = git2::Repository::init_bare(git_repo_path).unwrap(); let git_blob_oid = git_repo.blob(b"some content").unwrap();