diff --git a/cli/src/commands/bookmark/create.rs b/cli/src/commands/bookmark/create.rs index cd52bb889b7..06a6cc4409b 100644 --- a/cli/src/commands/bookmark/create.rs +++ b/cli/src/commands/bookmark/create.rs @@ -53,7 +53,9 @@ pub fn cmd_bookmark_create( let mut workspace_command = command.workspace_helper(ui)?; let target_commit = workspace_command .resolve_single_rev(ui, args.revision.as_ref().unwrap_or(&RevisionArg::AT))?; + let repo = workspace_command.repo(); let view = workspace_command.repo().view(); + let is_hidden = target_commit.is_hidden(repo.as_ref())?; let bookmark_names = &args.names; for name in bookmark_names { if view.get_local_bookmark(name).is_present() { @@ -94,6 +96,11 @@ pub fn cmd_bookmark_create( writeln!(ui.hint_default(), "Use -r to specify the target revision.")?; } + // The commit was hidden, so make it visible again. + if is_hidden { + tx.repo_mut().add_head(&target_commit)?; + } + tx.finish( ui, format!( diff --git a/cli/src/commands/bookmark/move.rs b/cli/src/commands/bookmark/move.rs index c6a229f51d0..943235b3e8a 100644 --- a/cli/src/commands/bookmark/move.rs +++ b/cli/src/commands/bookmark/move.rs @@ -91,6 +91,7 @@ pub fn cmd_bookmark_move( let repo = workspace_command.repo().clone(); let target_commit = workspace_command.resolve_single_rev(ui, &args.to)?; + let is_hidden = target_commit.is_hidden(repo.as_ref())?; let matched_bookmarks = { let is_source_ref: Box _> = if !args.from.is_empty() { let is_source_commit = workspace_command @@ -168,6 +169,11 @@ pub fn cmd_bookmark_move( )?; } + // The commit was hidden, unhide it. + if is_hidden { + tx.repo_mut().add_head(&target_commit)?; + } + tx.finish( ui, format!( diff --git a/cli/src/commands/bookmark/set.rs b/cli/src/commands/bookmark/set.rs index cb1af9cbdf4..f00e3ecc9d4 100644 --- a/cli/src/commands/bookmark/set.rs +++ b/cli/src/commands/bookmark/set.rs @@ -61,6 +61,7 @@ pub fn cmd_bookmark_set( .resolve_single_rev(ui, args.revision.as_ref().unwrap_or(&RevisionArg::AT))?; let repo = workspace_command.repo().as_ref(); let bookmark_names = &args.names; + let is_hidden = target_commit.is_hidden(repo)?; let mut new_bookmark_count = 0; let mut moved_bookmark_count = 0; for name in bookmark_names { @@ -106,6 +107,12 @@ pub fn cmd_bookmark_set( if bookmark_names.len() > 1 && args.revision.is_none() { writeln!(ui.hint_default(), "Use -r to specify the target revision.")?; } + + // The commit is hidden, so unhide it. + if is_hidden { + tx.repo_mut().add_head(&target_commit)?; + } + if new_bookmark_count > 0 { // TODO: delete this hint in jj 0.25+ writeln!( diff --git a/cli/tests/test_bookmark_command.rs b/cli/tests/test_bookmark_command.rs index 6d893382586..48c5b30453e 100644 --- a/cli/tests/test_bookmark_command.rs +++ b/cli/tests/test_bookmark_command.rs @@ -1898,6 +1898,73 @@ fn test_bookmark_list_conflicted() { "###); } +#[test] +fn test_bookmark_create_onto_hidden_unhides() { + 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"); + + std::fs::write(repo_path.join("a.txt"), "AA").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "A"]); + // Emulate a simple commit change, where we want to recover the initial version. + std::fs::write(repo_path.join("b.txt"), "BB").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["debug", "snapshot"]); + std::fs::write(repo_path.join("b.txt"), "Art").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "B"]); + // Create our bookmark onto the hidden commit. + let (stdout, _) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "back"]); + insta::assert_snapshot!(stdout, r#""#); +} + +#[test] +fn test_bookmark_move_onto_hidden_unhides() { + 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"); + + std::fs::write(repo_path.join("a.txt"), "AA").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "A"]); + // Create our bookmark on the first commit. It will be moved to a predecessor of the second + // one. + test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "back"]); + // Emulate a simple commit change, where we want to recover the initial version. + std::fs::write(repo_path.join("b.txt"), "BB").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["debug", "snapshot"]); + std::fs::write(repo_path.join("b.txt"), "Art").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "B"]); + + insta::assert_snapshot!(get_evolog_output(&test_env, &repo_path), r#""#); + + let (stdout, _) = + test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "back", "-r", ""]); + insta::assert_snapshot!(stdout, r#""#); +} + +#[test] +fn test_bookmark_set_onto_hidden_unhides() { + // TODO: write + 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"); + + std::fs::write(repo_path.join("a.txt"), "AA").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "A"]); + // Emulate a simple commit change, where we want to recover the initial version. + std::fs::write(repo_path.join("b.txt"), "BB").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["debug", "snapshot"]); + std::fs::write(repo_path.join("b.txt"), "Art").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "B"]); + insta::assert_snapshot!(get_evolog_output(&test_env, &repo_path), r#""#); + let (stdout, _) = + test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "back", "-r", ""]); + insta::assert_snapshot!(stdout, r#""#); +} + +fn get_evolog_output(test_env: &TestEnvironment, cwd: &Path) -> String { + let template = r#"change_id ++ " " ++ commit_id"#; + test_env.jj_cmd_success(cwd, &["evolog", "-T", &template]) +} + fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String { let template = r#"bookmarks ++ " " ++ commit_id.short()"#; test_env.jj_cmd_success(cwd, &["log", "-T", template])