// Copyright 2022 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 test_case::test_case;use testutils::TestResult;use testutils::git; use crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir; #[test]fn test_workspaces_invalid_name() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let main_dir = test_env.work_dir("repo"); // refuse to create, directory not created let output = main_dir.run_jj(["workspace", "add", "--name", "", "../secondary"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: New workspace name cannot be empty [EOF] [exit status: 1] "); assert!(!test_env.env_root().join("secondary").exists()); // refuse to rename let output = main_dir.run_jj(["workspace", "rename", ""]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: New workspace name cannot be empty [EOF] [exit status: 1] ");} /// Test adding a second and a third workspace#[test]fn test_workspaces_add_second_and_third_workspace() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); let secondary_dir = test_env.work_dir("secondary"); main_dir.write_file("file", "contents"); main_dir.run_jj(["commit", "-m", "initial"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: rlvkpnrz 504e3d8c (empty) (no description set) [EOF] "); let output = main_dir.run_jj(["workspace", "add", "--name", "second", "../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: rzvqmyuk bcc858e1 (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Can see the working-copy commit in each workspace in the log output. The "@" // node in the graph indicates the current workspace's working-copy commit. insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 504e3d8c1bcd default@ │ ○ bcc858e1d93f second@ ├─╯ ○ 7b22a8cbe888 "initial" ◆ 000000000000 [EOF] "#); insta::assert_snapshot!(get_log_output(&secondary_dir), @r#" @ bcc858e1d93f second@ │ ○ 504e3d8c1bcd default@ ├─╯ ○ 7b22a8cbe888 "initial" ◆ 000000000000 [EOF] "#); // Both workspaces show up when we list them let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: rlvkpnrz 504e3d8c (empty) (no description set) second: rzvqmyuk bcc858e1 (empty) (no description set) [EOF] "); // Check that a workspace can be created in an existing empty directory main_dir.create_dir("../third"); let output = main_dir.run_jj(["workspace", "add", "--name", "third", "../third"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../third" Working copy (@) now at: nuwvvtmy d55e769c (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Duplicate names are not allowed, directory not created let output = main_dir.run_jj(["workspace", "add", "--name", "third", "../tertiary"]); insta::assert_snapshot!(output.normalize_backslash(), @" ------- stderr ------- Error: Workspace named 'third' already exists [EOF] [exit status: 1] "); assert!(!test_env.env_root().join("tertiary").exists());} #[test]fn test_workspaces_add_with_message() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.write_file("file", "contents"); main_dir.run_jj(["commit", "-m", "initial"]).success(); let output = main_dir.run_jj([ "workspace", "add", "--name", "second", "-m", "add second workspace", "../secondary", ]); // Check that the newly created workspace has a description for the commit insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: pmmvwywv 47a2d9a1 (empty) add second workspace Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); main_dir .run_jj([ "workspace", "add", "--name", "third", "-m", "first message", "-m", "second message", "../tertiary", ]) .success(); // Check that multiple messages work as expected like with the "new" command let output = main_dir.run_jj(["log", "-r", "third@", "-Tdescription", "--no-graph"]); insta::assert_snapshot!(output.normalize_backslash(), @" first message second message [EOF] "); // Test that adding workspace with no message has no trailers test_env.add_config( r#"[templates] commit_trailers = '"Signed-off-by: " ++ committer.email()' "#, ); let output = main_dir.run_jj(["workspace", "add", "--name", "fourth", "../quaternary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../quaternary" Working copy (@) now at: nppvrztz 0bfa7004 (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#);} /// Test how sparse patterns are inherited#[test]fn test_workspaces_sparse_patterns() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "ws1"]).success(); let ws1_dir = test_env.work_dir("ws1"); let ws2_dir = test_env.work_dir("ws2"); let ws3_dir = test_env.work_dir("ws3"); let ws4_dir = test_env.work_dir("ws4"); let ws5_dir = test_env.work_dir("ws5"); let ws6_dir = test_env.work_dir("ws6"); ws1_dir .run_jj(["sparse", "set", "--clear", "--add=foo"]) .success(); ws1_dir.run_jj(["workspace", "add", "../ws2"]).success(); let output = ws2_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" foo [EOF] "); ws2_dir.run_jj(["sparse", "set", "--add=bar"]).success(); ws2_dir.run_jj(["workspace", "add", "../ws3"]).success(); let output = ws3_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" bar foo [EOF] "); // --sparse-patterns behavior ws3_dir .run_jj(["workspace", "add", "--sparse-patterns=copy", "../ws4"]) .success(); let output = ws4_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" bar foo [EOF] "); ws3_dir .run_jj(["workspace", "add", "--sparse-patterns=full", "../ws5"]) .success(); let output = ws5_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" . [EOF] "); ws3_dir .run_jj(["workspace", "add", "--sparse-patterns=empty", "../ws6"]) .success(); let output = ws6_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @"");} /// Test adding a second workspace while the current workspace is editing a/// merge#[test]fn test_workspaces_add_second_workspace_on_merge() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.run_jj(["describe", "-m=left"]).success(); main_dir.run_jj(["new", "@-", "-m=right"]).success(); main_dir.run_jj(["new", "@-+", "-m=merge"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: zsuskuln 46ed31b6 (empty) merge [EOF] "); main_dir .run_jj(["workspace", "add", "--name", "second", "../secondary"]) .success(); // The new workspace's working-copy commit shares all parents with the old one. insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 46ed31b61ce9 default@ "merge" ├─╮ │ │ ○ d23b2d4ff55c second@ ╭─┬─╯ │ ○ 3c52528f5893 "left" ○ │ a3155ab1bf5a "right" ├─╯ ◆ 000000000000 [EOF] "#);} /// Test that --ignore-working-copy is respected#[test]fn test_workspaces_add_ignore_working_copy() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); // TODO: maybe better to error out early? let output = main_dir.run_jj(["workspace", "add", "--ignore-working-copy", "../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Error: This command must be able to update the working copy. Hint: Don't use --ignore-working-copy. [EOF] [exit status: 1] "#);} /// Test that --no-integrate-operation is respected#[test]fn test_workspaces_add_no_integrate_operation() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); // TODO: maybe better to error out early? let output = main_dir.run_jj([ "workspace", "add", "--no-integrate-operation", "../secondary", ]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Error: This command must be able to update the working copy. Hint: Don't use --no-integrate-operation. [EOF] [exit status: 1] "#);} /// Test that --at-op is respected#[test]fn test_workspaces_add_at_operation() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.write_file("file1", ""); let output = main_dir.run_jj(["commit", "-m1"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: rlvkpnrz 59e07459 (empty) (no description set) Parent commit (@-) : qpvuntsm 9e4b0b91 1 [EOF] "); main_dir.write_file("file2", ""); let output = main_dir.run_jj(["commit", "-m2"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: kkmpptxz 6e9610ac (empty) (no description set) Parent commit (@-) : rlvkpnrz 8b7259b9 2 [EOF] "); // --at-op should disable snapshot in the main workspace, but the newly // created workspace should still be writable. main_dir.write_file("file3", ""); let output = main_dir.run_jj(["workspace", "add", "--at-op=@-", "../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: rzvqmyuk b8772476 (empty) (no description set) Parent commit (@-) : qpvuntsm 9e4b0b91 1 Added 1 files, modified 0 files, removed 0 files [EOF] "#); let secondary_dir = test_env.work_dir("secondary"); // New snapshot can be taken in the secondary workspace. secondary_dir.write_file("file4", ""); let output = secondary_dir.run_jj(["status"]); insta::assert_snapshot!(output, @" Working copy changes: A file4 Working copy (@) : rzvqmyuk f2ff8257 (no description set) Parent commit (@-): qpvuntsm 9e4b0b91 1 [EOF] ------- stderr ------- Concurrent modification detected, resolving automatically. [EOF] "); let output = secondary_dir.run_jj(["op", "log", "-Tdescription"]); insta::assert_snapshot!(output, @" @ snapshot working copy ○ reconcile divergent operations ├─╮ ○ │ commit 9152e822279787a168ddf4cede6440a21faa00d7 │ ○ create initial working-copy commit in workspace secondary │ ○ add workspace 'secondary' ├─╯ ○ snapshot working copy ○ commit 093c3c9624b6cfe22b310586f5638792aa80e6d7 ○ snapshot working copy ○ add workspace 'default' ○ [EOF] ");} /// Test adding a workspace, but at a specific revision using '-r'#[test]fn test_workspaces_add_workspace_at_revision() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); let secondary_dir = test_env.work_dir("secondary"); main_dir.write_file("file-1", "contents"); main_dir.run_jj(["commit", "-m", "first"]).success(); main_dir.write_file("file-2", "contents"); main_dir.run_jj(["commit", "-m", "second"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: kkmpptxz 5ac9178d (empty) (no description set) [EOF] "); let output = main_dir.run_jj([ "workspace", "add", "--name", "second", "../secondary", "-r", "@--", ]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: zxsnswpr ea5860fb (empty) (no description set) Parent commit (@-) : qpvuntsm 27473635 first Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Can see the working-copy commit in each workspace in the log output. The "@" // node in the graph indicates the current workspace's working-copy commit. insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 5ac9178da8b2 default@ ○ a47d8a593529 "second" │ ○ ea5860fbd622 second@ ├─╯ ○ 27473635a942 "first" ◆ 000000000000 [EOF] "#); insta::assert_snapshot!(get_log_output(&secondary_dir), @r#" @ ea5860fbd622 second@ │ ○ 5ac9178da8b2 default@ │ ○ a47d8a593529 "second" ├─╯ ○ 27473635a942 "first" ◆ 000000000000 [EOF] "#);} /// Test multiple `-r` flags to `workspace add` to create a workspace/// working-copy commit with multiple parents.#[test]fn test_workspaces_add_workspace_multiple_revisions() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.write_file("file-1", "contents"); main_dir.run_jj(["commit", "-m", "first"]).success(); main_dir.run_jj(["new", "-r", "root()"]).success(); main_dir.write_file("file-2", "contents"); main_dir.run_jj(["commit", "-m", "second"]).success(); main_dir.run_jj(["new", "-r", "root()"]).success(); main_dir.write_file("file-3", "contents"); main_dir.run_jj(["commit", "-m", "third"]).success(); main_dir.run_jj(["new", "-r", "root()"]).success(); insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 8d23abddc924 │ ○ eba7f49e2358 "third" ├─╯ │ ○ 62444a45efcf "second" ├─╯ │ ○ 27473635a942 "first" ├─╯ ◆ 000000000000 [EOF] "#); let output = main_dir.run_jj([ "workspace", "add", "--name=merge", "../merged", "-r=subject(third)", "-r=subject(second)", "-r=subject(first)",Lines 1–500 of 1987. Load more
// Copyright 2022 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 test_case::test_case; use testutils::TestResult; use testutils::git; use crate::common::CommandOutput; use crate::common::TestEnvironment; use crate::common::TestWorkDir; #[test] fn test_workspaces_invalid_name() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let main_dir = test_env.work_dir("repo"); // refuse to create, directory not created let output = main_dir.run_jj(["workspace", "add", "--name", "", "../secondary"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: New workspace name cannot be empty [EOF] [exit status: 1] "); assert!(!test_env.env_root().join("secondary").exists()); // refuse to rename let output = main_dir.run_jj(["workspace", "rename", ""]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: New workspace name cannot be empty [EOF] [exit status: 1] "); } /// Test adding a second and a third workspace #[test] fn test_workspaces_add_second_and_third_workspace() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); let secondary_dir = test_env.work_dir("secondary"); main_dir.write_file("file", "contents"); main_dir.run_jj(["commit", "-m", "initial"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: rlvkpnrz 504e3d8c (empty) (no description set) [EOF] "); let output = main_dir.run_jj(["workspace", "add", "--name", "second", "../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: rzvqmyuk bcc858e1 (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Can see the working-copy commit in each workspace in the log output. The "@" // node in the graph indicates the current workspace's working-copy commit. insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 504e3d8c1bcd default@ │ ○ bcc858e1d93f second@ ├─╯ ○ 7b22a8cbe888 "initial" ◆ 000000000000 [EOF] "#); insta::assert_snapshot!(get_log_output(&secondary_dir), @r#" @ bcc858e1d93f second@ │ ○ 504e3d8c1bcd default@ ├─╯ ○ 7b22a8cbe888 "initial" ◆ 000000000000 [EOF] "#); // Both workspaces show up when we list them let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: rlvkpnrz 504e3d8c (empty) (no description set) second: rzvqmyuk bcc858e1 (empty) (no description set) [EOF] "); // Check that a workspace can be created in an existing empty directory main_dir.create_dir("../third"); let output = main_dir.run_jj(["workspace", "add", "--name", "third", "../third"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../third" Working copy (@) now at: nuwvvtmy d55e769c (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Duplicate names are not allowed, directory not created let output = main_dir.run_jj(["workspace", "add", "--name", "third", "../tertiary"]); insta::assert_snapshot!(output.normalize_backslash(), @" ------- stderr ------- Error: Workspace named 'third' already exists [EOF] [exit status: 1] "); assert!(!test_env.env_root().join("tertiary").exists()); } #[test] fn test_workspaces_add_with_message() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.write_file("file", "contents"); main_dir.run_jj(["commit", "-m", "initial"]).success(); let output = main_dir.run_jj([ "workspace", "add", "--name", "second", "-m", "add second workspace", "../secondary", ]); // Check that the newly created workspace has a description for the commit insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: pmmvwywv 47a2d9a1 (empty) add second workspace Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); main_dir .run_jj([ "workspace", "add", "--name", "third", "-m", "first message", "-m", "second message", "../tertiary", ]) .success(); // Check that multiple messages work as expected like with the "new" command let output = main_dir.run_jj(["log", "-r", "third@", "-Tdescription", "--no-graph"]); insta::assert_snapshot!(output.normalize_backslash(), @" first message second message [EOF] "); // Test that adding workspace with no message has no trailers test_env.add_config( r#"[templates] commit_trailers = '"Signed-off-by: " ++ committer.email()' "#, ); let output = main_dir.run_jj(["workspace", "add", "--name", "fourth", "../quaternary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../quaternary" Working copy (@) now at: nppvrztz 0bfa7004 (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); } /// Test how sparse patterns are inherited #[test] fn test_workspaces_sparse_patterns() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "ws1"]).success(); let ws1_dir = test_env.work_dir("ws1"); let ws2_dir = test_env.work_dir("ws2"); let ws3_dir = test_env.work_dir("ws3"); let ws4_dir = test_env.work_dir("ws4"); let ws5_dir = test_env.work_dir("ws5"); let ws6_dir = test_env.work_dir("ws6"); ws1_dir .run_jj(["sparse", "set", "--clear", "--add=foo"]) .success(); ws1_dir.run_jj(["workspace", "add", "../ws2"]).success(); let output = ws2_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" foo [EOF] "); ws2_dir.run_jj(["sparse", "set", "--add=bar"]).success(); ws2_dir.run_jj(["workspace", "add", "../ws3"]).success(); let output = ws3_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" bar foo [EOF] "); // --sparse-patterns behavior ws3_dir .run_jj(["workspace", "add", "--sparse-patterns=copy", "../ws4"]) .success(); let output = ws4_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" bar foo [EOF] "); ws3_dir .run_jj(["workspace", "add", "--sparse-patterns=full", "../ws5"]) .success(); let output = ws5_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @" . [EOF] "); ws3_dir .run_jj(["workspace", "add", "--sparse-patterns=empty", "../ws6"]) .success(); let output = ws6_dir.run_jj(["sparse", "list"]); insta::assert_snapshot!(output, @""); } /// Test adding a second workspace while the current workspace is editing a /// merge #[test] fn test_workspaces_add_second_workspace_on_merge() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.run_jj(["describe", "-m=left"]).success(); main_dir.run_jj(["new", "@-", "-m=right"]).success(); main_dir.run_jj(["new", "@-+", "-m=merge"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: zsuskuln 46ed31b6 (empty) merge [EOF] "); main_dir .run_jj(["workspace", "add", "--name", "second", "../secondary"]) .success(); // The new workspace's working-copy commit shares all parents with the old one. insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 46ed31b61ce9 default@ "merge" ├─╮ │ │ ○ d23b2d4ff55c second@ ╭─┬─╯ │ ○ 3c52528f5893 "left" ○ │ a3155ab1bf5a "right" ├─╯ ◆ 000000000000 [EOF] "#); } /// Test that --ignore-working-copy is respected #[test] fn test_workspaces_add_ignore_working_copy() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); // TODO: maybe better to error out early? let output = main_dir.run_jj(["workspace", "add", "--ignore-working-copy", "../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Error: This command must be able to update the working copy. Hint: Don't use --ignore-working-copy. [EOF] [exit status: 1] "#); } /// Test that --no-integrate-operation is respected #[test] fn test_workspaces_add_no_integrate_operation() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); // TODO: maybe better to error out early? let output = main_dir.run_jj([ "workspace", "add", "--no-integrate-operation", "../secondary", ]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Error: This command must be able to update the working copy. Hint: Don't use --no-integrate-operation. [EOF] [exit status: 1] "#); } /// Test that --at-op is respected #[test] fn test_workspaces_add_at_operation() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.write_file("file1", ""); let output = main_dir.run_jj(["commit", "-m1"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: rlvkpnrz 59e07459 (empty) (no description set) Parent commit (@-) : qpvuntsm 9e4b0b91 1 [EOF] "); main_dir.write_file("file2", ""); let output = main_dir.run_jj(["commit", "-m2"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: kkmpptxz 6e9610ac (empty) (no description set) Parent commit (@-) : rlvkpnrz 8b7259b9 2 [EOF] "); // --at-op should disable snapshot in the main workspace, but the newly // created workspace should still be writable. main_dir.write_file("file3", ""); let output = main_dir.run_jj(["workspace", "add", "--at-op=@-", "../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: rzvqmyuk b8772476 (empty) (no description set) Parent commit (@-) : qpvuntsm 9e4b0b91 1 Added 1 files, modified 0 files, removed 0 files [EOF] "#); let secondary_dir = test_env.work_dir("secondary"); // New snapshot can be taken in the secondary workspace. secondary_dir.write_file("file4", ""); let output = secondary_dir.run_jj(["status"]); insta::assert_snapshot!(output, @" Working copy changes: A file4 Working copy (@) : rzvqmyuk f2ff8257 (no description set) Parent commit (@-): qpvuntsm 9e4b0b91 1 [EOF] ------- stderr ------- Concurrent modification detected, resolving automatically. [EOF] "); let output = secondary_dir.run_jj(["op", "log", "-Tdescription"]); insta::assert_snapshot!(output, @" @ snapshot working copy ○ reconcile divergent operations ├─╮ ○ │ commit 9152e822279787a168ddf4cede6440a21faa00d7 │ ○ create initial working-copy commit in workspace secondary │ ○ add workspace 'secondary' ├─╯ ○ snapshot working copy ○ commit 093c3c9624b6cfe22b310586f5638792aa80e6d7 ○ snapshot working copy ○ add workspace 'default' ○ [EOF] "); } /// Test adding a workspace, but at a specific revision using '-r' #[test] fn test_workspaces_add_workspace_at_revision() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); let secondary_dir = test_env.work_dir("secondary"); main_dir.write_file("file-1", "contents"); main_dir.run_jj(["commit", "-m", "first"]).success(); main_dir.write_file("file-2", "contents"); main_dir.run_jj(["commit", "-m", "second"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @" default: kkmpptxz 5ac9178d (empty) (no description set) [EOF] "); let output = main_dir.run_jj([ "workspace", "add", "--name", "second", "../secondary", "-r", "@--", ]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../secondary" Working copy (@) now at: zxsnswpr ea5860fb (empty) (no description set) Parent commit (@-) : qpvuntsm 27473635 first Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Can see the working-copy commit in each workspace in the log output. The "@" // node in the graph indicates the current workspace's working-copy commit. insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 5ac9178da8b2 default@ ○ a47d8a593529 "second" │ ○ ea5860fbd622 second@ ├─╯ ○ 27473635a942 "first" ◆ 000000000000 [EOF] "#); insta::assert_snapshot!(get_log_output(&secondary_dir), @r#" @ ea5860fbd622 second@ │ ○ 5ac9178da8b2 default@ │ ○ a47d8a593529 "second" ├─╯ ○ 27473635a942 "first" ◆ 000000000000 [EOF] "#); } /// Test multiple `-r` flags to `workspace add` to create a workspace /// working-copy commit with multiple parents. #[test] fn test_workspaces_add_workspace_multiple_revisions() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "main"]).success(); let main_dir = test_env.work_dir("main"); main_dir.write_file("file-1", "contents"); main_dir.run_jj(["commit", "-m", "first"]).success(); main_dir.run_jj(["new", "-r", "root()"]).success(); main_dir.write_file("file-2", "contents"); main_dir.run_jj(["commit", "-m", "second"]).success(); main_dir.run_jj(["new", "-r", "root()"]).success(); main_dir.write_file("file-3", "contents"); main_dir.run_jj(["commit", "-m", "third"]).success(); main_dir.run_jj(["new", "-r", "root()"]).success(); insta::assert_snapshot!(get_log_output(&main_dir), @r#" @ 8d23abddc924 │ ○ eba7f49e2358 "third" ├─╯ │ ○ 62444a45efcf "second" ├─╯ │ ○ 27473635a942 "first" ├─╯ ◆ 000000000000 [EOF] "#); let output = main_dir.run_jj([ "workspace", "add", "--name=merge", "../merged", "-r=subject(third)", "-r=subject(second)", "-r=subject(first)",