1934 lines · 69.6 KB · Rust
RawDownload
// 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 std::fmt::Write as _;use std::path::Path; use testutils::TestResult;use testutils::git; use crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir; #[test]fn test_git_colocated() -> TestResult {    let test_env = TestEnvironment::default();    let work_dir = test_env.work_dir("repo");    let git_repo = git::init(work_dir.root());     // Create an initial commit in Git    let tree_id = git::add_commit(        &git_repo,        "refs/heads/master",        "file",        b"contents",        "initial",        &[],    )    .tree_id;    git::checkout_tree_index(&git_repo, tree_id);    assert_eq!(work_dir.read_file("file"), b"contents");    insta::assert_snapshot!(        git_repo.head_id()?.to_string(),        @"97358f54806c7cd005ed5ade68a779595efbae7e"    );     // Import the repo    work_dir        .run_jj(["git", "init", "--git-repo", "."])        .success();    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  524826059adc6f74de30f6be8f8eb86715d75b62    ○  97358f54806c7cd005ed5ade68a779595efbae7e master initial    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(        git_repo.head_id()?.to_string(),        @"97358f54806c7cd005ed5ade68a779595efbae7e"    );    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: 97358f54806c7cd005ed5ade68a779595efbae7e    [EOF]    ");     // Modify the working copy. The working-copy commit should changed, but the Git    // HEAD commit should not    work_dir.write_file("file", "modified");    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  9dfe8c7005c8dff6078ecdfd953c6bfddc633c90    ○  97358f54806c7cd005ed5ade68a779595efbae7e master initial    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(        git_repo.head_id()?.to_string(),        @"97358f54806c7cd005ed5ade68a779595efbae7e"    );    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: 97358f54806c7cd005ed5ade68a779595efbae7e    [EOF]    ");     // Create a new change from jj and check that it's reflected in Git    work_dir.run_jj(["new"]).success();    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  4ddddef596e9d68f729f1be9e1b2cdaaf45bef08    ○  9dfe8c7005c8dff6078ecdfd953c6bfddc633c90    ○  97358f54806c7cd005ed5ade68a779595efbae7e master initial    ◆  0000000000000000000000000000000000000000    [EOF]    ");    assert!(git_repo.head()?.is_detached());    insta::assert_snapshot!(        git_repo.head_id()?.to_string(),        @"9dfe8c7005c8dff6078ecdfd953c6bfddc633c90"    );    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: 9dfe8c7005c8dff6078ecdfd953c6bfddc633c90    [EOF]    ");     Ok(())} #[test]fn test_git_colocated_intent_to_add() -> TestResult {    let test_env = TestEnvironment::default();    test_env        .run_jj_in(".", ["git", "init", "--colocate", "repo"])        .success();    let work_dir = test_env.work_dir("repo");     // A file added directly on top of the root commit should be marked as    // intent-to-add    work_dir.write_file("file1.txt", "contents");    work_dir.run_jj(["status"]).success();    insta::assert_snapshot!(get_index_state(work_dir.root()), @"Unconflicted Mode(FILE) e69de29bb2d1 ctime=0:0 mtime=0:0 size=0 flags=20004000 file1.txt");     // Previously, this would fail due to the empty blob not being written to the    // store when marking files as intent-to-add.    work_dir.run_jj(["util", "gc"]).success();     // Another new file should be marked as intent-to-add    work_dir.run_jj(["new"]).success();    work_dir.write_file("file2.txt", "contents");    work_dir.run_jj(["status"]).success();    insta::assert_snapshot!(get_index_state(work_dir.root()), @"    Unconflicted Mode(FILE) 0839b2e9412b ctime=0:0 mtime=0:0 size=0 flags=0 file1.txt    Unconflicted Mode(FILE) e69de29bb2d1 ctime=0:0 mtime=0:0 size=0 flags=20004000 file2.txt    ");     let op_id_new_file = work_dir.current_operation_id();     // After creating a new commit, it should not longer be marked as intent-to-add    work_dir.run_jj(["new"]).success();    work_dir.write_file("file2.txt", "contents");    work_dir.run_jj(["status"]).success();    insta::assert_snapshot!(get_index_state(work_dir.root()), @"    Unconflicted Mode(FILE) 0839b2e9412b ctime=0:0 mtime=0:0 size=0 flags=0 file1.txt    Unconflicted Mode(FILE) 0839b2e9412b ctime=0:0 mtime=0:0 size=0 flags=0 file2.txt    ");     // If we edit an existing commit, new files are marked as intent-to-add    work_dir.run_jj(["edit", "@-"]).success();    work_dir.run_jj(["status"]).success();    insta::assert_snapshot!(get_index_state(work_dir.root()), @"    Unconflicted Mode(FILE) 0839b2e9412b ctime=0:0 mtime=0:0 size=0 flags=0 file1.txt    Unconflicted Mode(FILE) e69de29bb2d1 ctime=0:0 mtime=0:0 size=0 flags=20004000 file2.txt    ");     // If we remove the added file, it's removed from the index    work_dir.remove_file("file2.txt");    work_dir.run_jj(["status"]).success();    insta::assert_snapshot!(get_index_state(work_dir.root()), @"Unconflicted Mode(FILE) 0839b2e9412b ctime=0:0 mtime=0:0 size=0 flags=0 file1.txt");     // If we untrack the file, it's removed from the index    work_dir        .run_jj(["op", "restore", op_id_new_file.as_str()])        .success();    work_dir.write_file(".gitignore", "file2.txt");    work_dir.run_jj(["file", "untrack", "file2.txt"]).success();    insta::assert_snapshot!(get_index_state(work_dir.root()), @"    Unconflicted Mode(FILE) e69de29bb2d1 ctime=0:0 mtime=0:0 size=0 flags=20004000 .gitignore    Unconflicted Mode(FILE) 0839b2e9412b ctime=0:0 mtime=0:0 size=0 flags=0 file1.txt    ");     Ok(())} #[test]fn test_git_colocated_new_wc_commit_when_wc_immutable() {    let test_env = TestEnvironment::default();    test_env        .run_jj_in(".", ["git", "init", "--colocate", "repo"])        .success();    let work_dir = test_env.work_dir("repo");     // Create Git HEAD commit    work_dir.write_file("file1", "a\n");    work_dir.run_jj(["new"]).success();     // Prepare working copy that will become immutable    work_dir.write_file("file2", "b\n");    work_dir        .run_jj(["bookmark", "create", "-r@", "main"])        .success();    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: eb7b8a1f02b8d0915290e1163a3526bfa4e417fa    [EOF]    ");    insta::assert_snapshot!(get_index_state(work_dir.root()), @"    Unconflicted Mode(FILE) 78981922613b ctime=0:0 mtime=0:0 size=0 flags=0 file1    Unconflicted Mode(FILE) e69de29bb2d1 ctime=0:0 mtime=0:0 size=0 flags=20004000 file2    ");     // Make the working copy immutable and snapshot changes    test_env.add_config(r#"revset-aliases."immutable_heads()" = "main""#);    work_dir.write_file("file2", "b\nc\n");    work_dir.write_file("file3", "d\n");    let output = work_dir.run_jj(["status"]);    insta::assert_snapshot!(output, @"    Working copy changes:    M file2    A file3    Working copy  (@) : mzvwutvl d1b1d7e9 (no description set)    Parent commit (@-): rlvkpnrz 1d3e40a3 main | (no description set)    [EOF]    ------- stderr -------    Warning: The working-copy commit is immutable; a new commit has been created on top of it.    [EOF]    ");    // New working-copy commit is created, and the Git HEAD should be updated    let output = work_dir.run_jj(["log", "-r..", "--summary"]);    insta::assert_snapshot!(output, @"    @  mzvwutvl test.user@example.com 2001-02-03 08:05:11 d1b1d7e9    │  (no description set)    │  M file2    │  A file3    ◆  rlvkpnrz test.user@example.com 2001-02-03 08:05:09 main 1d3e40a3    │  (no description set)    │  A file2    ◆  qpvuntsm test.user@example.com 2001-02-03 08:05:08 eb7b8a1f    │  (no description set)    ~  A file1    [EOF]    ");    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: 1d3e40a35156c275f7a535fdaa50cb5882d500eb    [EOF]    ");    // file3 should be marked as "intent-to-add"    insta::assert_snapshot!(get_index_state(work_dir.root()), @"    Unconflicted Mode(FILE) 78981922613b ctime=0:0 mtime=0:0 size=0 flags=0 file1    Unconflicted Mode(FILE) 61780798228d ctime=0:0 mtime=0:0 size=0 flags=0 file2    Unconflicted Mode(FILE) e69de29bb2d1 ctime=0:0 mtime=0:0 size=0 flags=20004000 file3    ");} #[test]fn test_git_colocated_unborn_bookmark() -> TestResult {    let test_env = TestEnvironment::default();    let work_dir = test_env.work_dir("repo");    let git_repo = git::init(work_dir.root());     // add a file to an (in memory) index    let add_file_to_index = |name: &str, data: &str| {        let mut index_manager = git::IndexManager::new(&git_repo);        index_manager.add_file(name, data.as_bytes());        index_manager.sync_index();    };     // checkout index (i.e., drop the in-memory changes)    let checkout_index = || {        let mut index = git_repo.open_index().unwrap();        let objects = git_repo.objects.clone();        gix::worktree::state::checkout(            &mut index,            git_repo.workdir().unwrap(),            objects,            &gix::progress::Discard,            &gix::progress::Discard,            &gix::interrupt::IS_INTERRUPTED,            gix::worktree::state::checkout::Options::default(),        )        .unwrap();    };     // Initially, HEAD isn't set.    work_dir        .run_jj(["git", "init", "--git-repo", "."])        .success();    assert!(git_repo.head()?.is_unborn());    assert_eq!(        git_repo.head_name()?.unwrap().as_bstr(),        b"refs/heads/master"    );    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  e8849ae12c709f2321908879bc724fdb2ab8a781    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: (none)    [EOF]    ");     // Stage some change, and check out root. This shouldn't clobber the HEAD.    add_file_to_index("file0", "");    let output = work_dir.run_jj(["new", "root()"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Working copy  (@) now at: zsuskuln c2934cfb (empty) (no description set)    Parent commit (@-)      : zzzzzzzz 00000000 (empty) (no description set)    Added 0 files, modified 0 files, removed 1 files    [EOF]    ");    assert!(git_repo.head()?.is_unborn());    assert_eq!(        git_repo.head_name()?.unwrap().as_bstr(),        b"refs/heads/master"    );    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  c2934cfbfb196d2c473959667beffcc19e71e5e8    │ ○  e6669bb3438ef218fa618e1047a1911d2b3410dd    ├─╯    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: (none)    [EOF]    ");    // Staged change shouldn't persist.    checkout_index();    insta::assert_snapshot!(work_dir.run_jj(["status"]), @"    The working copy has no changes.    Working copy  (@) : zsuskuln c2934cfb (empty) (no description set)    Parent commit (@-): zzzzzzzz 00000000 (empty) (no description set)    [EOF]    ");     // Stage some change, and create new HEAD. This shouldn't move the default    // bookmark.    add_file_to_index("file1", "");    let output = work_dir.run_jj(["new"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Working copy  (@) now at: vruxwmqv 2d7a8abb (empty) (no description set)    Parent commit (@-)      : zsuskuln ff536684 (no description set)    [EOF]    ");    assert!(git_repo.head()?.is_detached());    insta::assert_snapshot!(        git_repo.head_id()?.to_string(),        @"ff5366846b039b25c6c4998fa74dca821c246243"    );    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  2d7a8abb601ebf559df4037279e9f2e851a75e63    ○  ff5366846b039b25c6c4998fa74dca821c246243    │ ○  e6669bb3438ef218fa618e1047a1911d2b3410dd    ├─╯    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: ff5366846b039b25c6c4998fa74dca821c246243    [EOF]    ");    // Staged change shouldn't persist.    checkout_index();    insta::assert_snapshot!(work_dir.run_jj(["status"]), @"    The working copy has no changes.    Working copy  (@) : vruxwmqv 2d7a8abb (empty) (no description set)    Parent commit (@-): zsuskuln ff536684 (no description set)    [EOF]    ");     // Assign the default bookmark. The bookmark is no longer "unborn".    work_dir        .run_jj(["bookmark", "create", "-r@-", "master"])        .success();     // Stage some change, and check out root again. This should unset the HEAD.    // https://github.com/jj-vcs/jj/issues/1495    add_file_to_index("file2", "");    let output = work_dir.run_jj(["new", "root()"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Working copy  (@) now at: wqnwkozp 88e8407a (empty) (no description set)    Parent commit (@-)      : zzzzzzzz 00000000 (empty) (no description set)    Added 0 files, modified 0 files, removed 2 files    [EOF]    ");    assert!(git_repo.head()?.is_unborn());    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  88e8407a4f0a5e6f40a7c6c494106764adc00fed    │ ○  2dd7385602e703388fd266b939bba6f57a1439d3    │ ○  ff5366846b039b25c6c4998fa74dca821c246243 master    ├─╯    │ ○  e6669bb3438ef218fa618e1047a1911d2b3410dd    ├─╯    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: (none)    [EOF]    ");    // Staged change shouldn't persist.    checkout_index();    insta::assert_snapshot!(work_dir.run_jj(["status"]), @"    The working copy has no changes.    Working copy  (@) : wqnwkozp 88e8407a (empty) (no description set)    Parent commit (@-): zzzzzzzz 00000000 (empty) (no description set)    [EOF]    ");     // New snapshot and commit can be created after the HEAD got unset.    work_dir.write_file("file3", "");    let output = work_dir.run_jj(["new"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Working copy  (@) now at: uyznsvlq 2fb16499 (empty) (no description set)    Parent commit (@-)      : wqnwkozp bb21bc2d (no description set)    [EOF]    ");    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  2fb16499a987e632407402e38976ed250c939c42    ○  bb21bc2dce2af92973fdd6d42686d77bd16bc466    │ ○  2dd7385602e703388fd266b939bba6f57a1439d3    │ ○  ff5366846b039b25c6c4998fa74dca821c246243 master    ├─╯    │ ○  e6669bb3438ef218fa618e1047a1911d2b3410dd    ├─╯    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(get_colocation_status(&work_dir), @"    Workspace is currently colocated with Git.    Last imported/exported Git HEAD: bb21bc2dce2af92973fdd6d42686d77bd16bc466    [EOF]    ");     Ok(())} #[test]fn test_git_colocated_export_bookmarks_on_snapshot() -> TestResult {    let test_env = TestEnvironment::default();    let work_dir = test_env.work_dir("repo");    let git_repo = git::init(work_dir.root());    work_dir        .run_jj(["git", "init", "--git-repo", "."])        .success();     // Create bookmark pointing to the initial commit    work_dir.write_file("file", "initial");    work_dir        .run_jj(["bookmark", "create", "-r@", "foo"])        .success();    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  82a10a4d9ef783fd68b661f40ce10dd80d599d9e foo    ◆  0000000000000000000000000000000000000000    [EOF]    ");     // The bookmark gets updated when we modify the working copy, and it should get    // exported to Git without requiring any other changes    work_dir.write_file("file", "modified");    insta::assert_snapshot!(get_log_output(&work_dir), @"    @  00fc09f48ccf5c8b025a0f93b0ec3b0e4294a598 foo    ◆  0000000000000000000000000000000000000000    [EOF]    ");    insta::assert_snapshot!(git_repo        .find_reference("refs/heads/foo")?        .id()        .to_string(), @"00fc09f48ccf5c8b025a0f93b0ec3b0e4294a598");     Ok(())} #[test]fn test_git_colocated_rebase_on_import() -> TestResult {    let test_env = TestEnvironment::default();    let work_dir = test_env.work_dir("repo");    let git_repo = git::init(work_dir.root());    work_dir        .run_jj(["git", "init", "--git-repo", "."])        .success();     // Make some changes in jj and check that they're reflected in git    work_dir.write_file("file", "contents");    work_dir.run_jj(["commit", "-m", "add a file"]).success();    work_dir.write_file("file", "modified");    work_dir        .run_jj(["bookmark", "create", "-r@", "master"])        .success();    work_dir.run_jj(["commit", "-m", "modify a file"]).success();    // TODO: We shouldn't need this command here to trigger an import of the    // refs/heads/master we just exported    work_dir.run_jj(["st"]).success();     // Move `master` backwards, which should result in commit2 getting hidden,    // and the working-copy commit rebased.    let parent_commit = git_repo        .find_reference("refs/heads/master")?        .peel_to_commit()?        .parent_ids()

Lines 1–500 of 1934.