// 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 crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir; /// Test adding a second workspace#[test]fn test_workspaces_add_second_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, @r" 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 ◆ 000000000000 [EOF] "); insta::assert_snapshot!(get_log_output(&secondary_dir), @r" @ bcc858e1d93f second@ │ ○ 504e3d8c1bcd default@ ├─╯ ○ 7b22a8cbe888 ◆ 000000000000 [EOF] "); // Both workspaces show up when we list them let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz 504e3d8c (empty) (no description set) second: rzvqmyuk bcc858e1 (empty) (no description set) [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, @r" 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, @r" 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, @r" 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, @r" . [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", "all:@-+", "-m=merge"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" 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@ ├─╮ │ │ ○ d23b2d4ff55c second@ ╭─┬─╯ │ ○ 3c52528f5893 ○ │ a3155ab1bf5a ├─╯ ◆ 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 --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, @r" ------- 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, @r" ------- 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, @r" 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, @r" @ 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, @r" 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 │ ○ ea5860fbd622 second@ ├─╯ ○ 27473635a942 ◆ 000000000000 [EOF] "); insta::assert_snapshot!(get_log_output(&secondary_dir), @r" @ ea5860fbd622 second@ │ ○ 5ac9178da8b2 default@ │ ○ a47d8a593529 ├─╯ ○ 27473635a942 ◆ 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 ├─╯ │ ○ 62444a45efcf ├─╯ │ ○ 27473635a942 ├─╯ ◆ 000000000000 [EOF] "); let output = main_dir.run_jj([ "workspace", "add", "--name=merge", "../merged", "-r=description(third)", "-r=description(second)", "-r=description(first)", ]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../merged" Working copy (@) now at: wmwvqwsz 2d7c9a2d (empty) (no description set) Parent commit (@-) : mzvwutvl eba7f49e third Parent commit (@-) : kkmpptxz 62444a45 second Parent commit (@-) : qpvuntsm 27473635 first Added 3 files, modified 0 files, removed 0 files [EOF] "#); insta::assert_snapshot!(get_log_output(&main_dir), @r" @ 8d23abddc924 default@ │ ○ 2d7c9a2d41dc merge@ │ ├─┬─╮ │ │ │ ○ 27473635a942 ├─────╯ │ │ ○ 62444a45efcf ├───╯ │ ○ eba7f49e2358 ├─╯ ◆ 000000000000 [EOF] ");} #[test]fn test_workspaces_add_workspace_from_subdir() { 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"); let subdir_dir = main_dir.create_dir("subdir"); subdir_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, @r" default: rlvkpnrz 0ba0ff35 (empty) (no description set) [EOF] "); // Create workspace while in sub-directory of current workspace let output = subdir_dir.run_jj(["workspace", "add", "../../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../../secondary" Working copy (@) now at: rzvqmyuk dea1be10 (empty) (no description set) Parent commit (@-) : qpvuntsm 80b67806 initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Both workspaces show up when we list them let output = secondary_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz 0ba0ff35 (empty) (no description set) secondary: rzvqmyuk dea1be10 (empty) (no description set) [EOF] ");} #[test]fn test_workspaces_add_workspace_in_current_workspace() { 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(); // Try to create workspace using name instead of path let output = main_dir.run_jj(["workspace", "add", "secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "secondary" Warning: Workspace created inside current directory. If this was unintentional, delete the "secondary" directory and run `jj workspace forget secondary` to remove it. Working copy (@) now at: pmmvwywv 058f604d (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Workspace created despite warning let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz af2d0cd5 (no description set) secondary: pmmvwywv 058f604d (empty) (no description set) [EOF] "); // Use explicit path instead (no warning) let output = main_dir.run_jj(["workspace", "add", "./third"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "third" Working copy (@) now at: zxsnswpr 1c1effec (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Both workspaces created let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz b2288847 (no description set) secondary: pmmvwywv 058f604d (empty) (no description set) third: zxsnswpr 1c1effec (empty) (no description set) [EOF] "); // Can see files from the other workspaces in main workspace, since they are // child directories and will therefore be snapshotted let output = main_dir.run_jj(["file", "list"]); insta::assert_snapshot!(output.normalize_backslash(), @r" file secondary/file third/file [EOF] ");} /// Test making changes to the working copy in a workspace as it gets rewritten/// from another workspace#[test]fn test_workspaces_conflicting_edits() { 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\n"); main_dir.run_jj(["new"]).success(); main_dir .run_jj(["workspace", "add", "../secondary"]) .success(); insta::assert_snapshot!(get_log_output(&main_dir), @r" @ 393250c59e39 default@ │ ○ 547036666102 secondary@ ├─╯ ○ 9a462e35578aLines 1–500 of 1393. 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 crate::common::CommandOutput; use crate::common::TestEnvironment; use crate::common::TestWorkDir; /// Test adding a second workspace #[test] fn test_workspaces_add_second_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, @r" 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 ◆ 000000000000 [EOF] "); insta::assert_snapshot!(get_log_output(&secondary_dir), @r" @ bcc858e1d93f second@ │ ○ 504e3d8c1bcd default@ ├─╯ ○ 7b22a8cbe888 ◆ 000000000000 [EOF] "); // Both workspaces show up when we list them let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz 504e3d8c (empty) (no description set) second: rzvqmyuk bcc858e1 (empty) (no description set) [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, @r" 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, @r" 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, @r" 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, @r" . [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", "all:@-+", "-m=merge"]).success(); let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" 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@ ├─╮ │ │ ○ d23b2d4ff55c second@ ╭─┬─╯ │ ○ 3c52528f5893 ○ │ a3155ab1bf5a ├─╯ ◆ 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 --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, @r" ------- 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, @r" ------- 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, @r" 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, @r" @ 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, @r" 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 │ ○ ea5860fbd622 second@ ├─╯ ○ 27473635a942 ◆ 000000000000 [EOF] "); insta::assert_snapshot!(get_log_output(&secondary_dir), @r" @ ea5860fbd622 second@ │ ○ 5ac9178da8b2 default@ │ ○ a47d8a593529 ├─╯ ○ 27473635a942 ◆ 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 ├─╯ │ ○ 62444a45efcf ├─╯ │ ○ 27473635a942 ├─╯ ◆ 000000000000 [EOF] "); let output = main_dir.run_jj([ "workspace", "add", "--name=merge", "../merged", "-r=description(third)", "-r=description(second)", "-r=description(first)", ]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../merged" Working copy (@) now at: wmwvqwsz 2d7c9a2d (empty) (no description set) Parent commit (@-) : mzvwutvl eba7f49e third Parent commit (@-) : kkmpptxz 62444a45 second Parent commit (@-) : qpvuntsm 27473635 first Added 3 files, modified 0 files, removed 0 files [EOF] "#); insta::assert_snapshot!(get_log_output(&main_dir), @r" @ 8d23abddc924 default@ │ ○ 2d7c9a2d41dc merge@ │ ├─┬─╮ │ │ │ ○ 27473635a942 ├─────╯ │ │ ○ 62444a45efcf ├───╯ │ ○ eba7f49e2358 ├─╯ ◆ 000000000000 [EOF] "); } #[test] fn test_workspaces_add_workspace_from_subdir() { 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"); let subdir_dir = main_dir.create_dir("subdir"); subdir_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, @r" default: rlvkpnrz 0ba0ff35 (empty) (no description set) [EOF] "); // Create workspace while in sub-directory of current workspace let output = subdir_dir.run_jj(["workspace", "add", "../../secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "../../secondary" Working copy (@) now at: rzvqmyuk dea1be10 (empty) (no description set) Parent commit (@-) : qpvuntsm 80b67806 initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Both workspaces show up when we list them let output = secondary_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz 0ba0ff35 (empty) (no description set) secondary: rzvqmyuk dea1be10 (empty) (no description set) [EOF] "); } #[test] fn test_workspaces_add_workspace_in_current_workspace() { 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(); // Try to create workspace using name instead of path let output = main_dir.run_jj(["workspace", "add", "secondary"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "secondary" Warning: Workspace created inside current directory. If this was unintentional, delete the "secondary" directory and run `jj workspace forget secondary` to remove it. Working copy (@) now at: pmmvwywv 058f604d (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Workspace created despite warning let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz af2d0cd5 (no description set) secondary: pmmvwywv 058f604d (empty) (no description set) [EOF] "); // Use explicit path instead (no warning) let output = main_dir.run_jj(["workspace", "add", "./third"]); insta::assert_snapshot!(output.normalize_backslash(), @r#" ------- stderr ------- Created workspace in "third" Working copy (@) now at: zxsnswpr 1c1effec (empty) (no description set) Parent commit (@-) : qpvuntsm 7b22a8cb initial Added 1 files, modified 0 files, removed 0 files [EOF] "#); // Both workspaces created let output = main_dir.run_jj(["workspace", "list"]); insta::assert_snapshot!(output, @r" default: rlvkpnrz b2288847 (no description set) secondary: pmmvwywv 058f604d (empty) (no description set) third: zxsnswpr 1c1effec (empty) (no description set) [EOF] "); // Can see files from the other workspaces in main workspace, since they are // child directories and will therefore be snapshotted let output = main_dir.run_jj(["file", "list"]); insta::assert_snapshot!(output.normalize_backslash(), @r" file secondary/file third/file [EOF] "); } /// Test making changes to the working copy in a workspace as it gets rewritten /// from another workspace #[test] fn test_workspaces_conflicting_edits() { 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\n"); main_dir.run_jj(["new"]).success(); main_dir .run_jj(["workspace", "add", "../secondary"]) .success(); insta::assert_snapshot!(get_log_output(&main_dir), @r" @ 393250c59e39 default@ │ ○ 547036666102 secondary@ ├─╯ ○ 9a462e35578a