diff --git a/src/commands/mod.rs b/src/commands/mod.rs index af7cd9998f..1a71b23072 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -944,6 +944,7 @@ enum DebugCommands { Index(DebugIndexArgs), #[command(name = "reindex")] ReIndex(DebugReIndexArgs), + #[command(visible_alias = "view")] Operation(DebugOperationArgs), } @@ -976,6 +977,18 @@ struct DebugReIndexArgs {} struct DebugOperationArgs { #[arg(default_value = "@")] operation: String, + #[arg(long, value_enum, default_value = "all")] + display: DebugOperationDisplay, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)] +enum DebugOperationDisplay { + /// Show only the operation details. + Operation, + /// Show only the view details + View, + /// Show both the view and the operation + All, } fn add_to_git_exclude(ui: &mut Ui, git_repo: &git2::Repository) -> Result<(), CommandError> { @@ -3200,8 +3213,12 @@ fn cmd_debug( DebugCommands::Operation(operation_args) => { let workspace_command = command.workspace_helper(ui)?; let op = workspace_command.resolve_single_op(&operation_args.operation)?; - writeln!(ui, "{:#?}", op.store_operation())?; - writeln!(ui, "{:#?}", op.view().store_view())?; + if operation_args.display != DebugOperationDisplay::View { + writeln!(ui, "{:#?}", op.store_operation())?; + } + if operation_args.display != DebugOperationDisplay::Operation { + writeln!(ui, "{:#?}", op.view().store_view())?; + } } } Ok(()) diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 9b0c1444ac..1402fef3f3 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -28,6 +28,24 @@ pub struct TestEnvironment { env_vars: HashMap, config_file_number: RefCell, command_number: RefCell, + /// If true, `jj_cmd_success` does not abort when `jj` exits with nonempty + /// stderr and outputs it instead. This is meant only for debugging. + /// + /// This allows debugging the execution of an integration test by inserting + /// `eprintln!` or `dgb!` statements in relevant parts of jj source code. + /// + /// You can change the value of this parameter directly, or you can set the + /// `JJ_DEBUG_ALLOW_STDERR` environment variable. + /// + /// To see the output, you can run `cargo test` with the --show-output + /// argument, like so: + /// + /// RUST_BACKTRACE=1 JJ_DEBUG_ALLOW_STDERR=1 cargo test \ + /// --test test_git_colocated -- --show-output fetch_del + /// + /// This would run all the tests that contain `fetch_del` in their name in a + /// file that contains `test_git_colocated` and show the output. + pub debug_allow_stderr: bool, } impl Default for TestEnvironment { @@ -49,6 +67,7 @@ impl Default for TestEnvironment { env_vars, config_file_number: RefCell::new(0), command_number: RefCell::new(0), + debug_allow_stderr: std::env::var("JJ_DEBUG_ALLOW_STDERR").is_ok(), }; // Use absolute timestamps in the operation log to make tests independent of the // current time. @@ -118,7 +137,19 @@ impl TestEnvironment { /// Run a `jj` command, check that it was successful, and return its stdout pub fn jj_cmd_success(&self, current_dir: &Path, args: &[&str]) -> String { - let assert = self.jj_cmd(current_dir, args).assert().success().stderr(""); + let assert = if self.debug_allow_stderr { + let a = self.jj_cmd(current_dir, args).assert().success(); + let stderr = self.normalize_output(&get_stderr_string(&a)); + if !stderr.is_empty() { + eprintln!( + "==== STDERR from running jj with {args:?} args in {current_dir:?} \ + ====\n{stderr}==== END STDERR ====" + ); + } + a + } else { + self.jj_cmd(current_dir, args).assert().success().stderr("") + }; self.normalize_output(&get_stdout_string(&assert)) }