2795 lines · 88.8 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::path::Path; use crate::common::TestEnvironment; fn create_commit(test_env: &TestEnvironment, repo_path: &Path, name: &str, parents: &[&str]) {    if parents.is_empty() {        test_env.jj_cmd_ok(repo_path, &["new", "root()", "-m", name]);    } else {        let mut args = vec!["new", "-m", name];        args.extend(parents);        test_env.jj_cmd_ok(repo_path, &args);    }    std::fs::write(repo_path.join(name), format!("{name}\n")).unwrap();    test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);} #[test]fn test_rebase_invalid() {    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");     create_commit(&test_env, &repo_path, "a", &[]);    create_commit(&test_env, &repo_path, "b", &["a"]);     // Missing destination    let stderr = test_env.jj_cmd_cli_error(&repo_path, &["rebase"]);    insta::assert_snapshot!(stderr, @r###"    error: the following required arguments were not provided:      <--destination <DESTINATION>|--insert-after <INSERT_AFTER>|--insert-before <INSERT_BEFORE>>     Usage: jj rebase <--destination <DESTINATION>|--insert-after <INSERT_AFTER>|--insert-before <INSERT_BEFORE>>     For more information, try '--help'.    "###);     // Both -r and -s    let stderr =        test_env.jj_cmd_cli_error(&repo_path, &["rebase", "-r", "a", "-s", "a", "-d", "b"]);    insta::assert_snapshot!(stderr, @r###"    error: the argument '--revisions <REVISIONS>' cannot be used with '--source <SOURCE>'     Usage: jj rebase --revisions <REVISIONS> <--destination <DESTINATION>|--insert-after <INSERT_AFTER>|--insert-before <INSERT_BEFORE>>     For more information, try '--help'.    "###);     // Both -b and -s    let stderr =        test_env.jj_cmd_cli_error(&repo_path, &["rebase", "-b", "a", "-s", "a", "-d", "b"]);    insta::assert_snapshot!(stderr, @r###"    error: the argument '--branch <BRANCH>' cannot be used with '--source <SOURCE>'     Usage: jj rebase --branch <BRANCH> <--destination <DESTINATION>|--insert-after <INSERT_AFTER>|--insert-before <INSERT_BEFORE>>     For more information, try '--help'.    "###);     // Both -d and --after    let stderr = test_env.jj_cmd_cli_error(        &repo_path,        &["rebase", "-r", "a", "-d", "b", "--after", "b"],    );    insta::assert_snapshot!(stderr, @r###"    error: the argument '--destination <DESTINATION>' cannot be used with '--insert-after <INSERT_AFTER>'     Usage: jj rebase --revisions <REVISIONS> <--destination <DESTINATION>|--insert-after <INSERT_AFTER>|--insert-before <INSERT_BEFORE>>     For more information, try '--help'.    "###);     // Both -d and --before    let stderr = test_env.jj_cmd_cli_error(        &repo_path,        &["rebase", "-r", "a", "-d", "b", "--before", "b"],    );    insta::assert_snapshot!(stderr, @r###"    error: the argument '--destination <DESTINATION>' cannot be used with '--insert-before <INSERT_BEFORE>'     Usage: jj rebase --revisions <REVISIONS> <--destination <DESTINATION>|--insert-after <INSERT_AFTER>|--insert-before <INSERT_BEFORE>>     For more information, try '--help'.    "###);     // Rebase onto self with -r    let stderr = test_env.jj_cmd_failure(&repo_path, &["rebase", "-r", "a", "-d", "a"]);    insta::assert_snapshot!(stderr, @r###"    Error: Cannot rebase 2443ea76b0b1 onto itself    "###);     // Rebase root with -r    let stderr = test_env.jj_cmd_failure(&repo_path, &["rebase", "-r", "root()", "-d", "a"]);    insta::assert_snapshot!(stderr, @r###"    Error: The root commit 000000000000 is immutable    "###);     // Rebase onto descendant with -s    let stderr = test_env.jj_cmd_failure(&repo_path, &["rebase", "-s", "a", "-d", "b"]);    insta::assert_snapshot!(stderr, @r###"    Error: Cannot rebase 2443ea76b0b1 onto descendant 1394f625cbbd    "###);} #[test]fn test_rebase_bookmark() {    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");     create_commit(&test_env, &repo_path, "a", &[]);    create_commit(&test_env, &repo_path, "b", &["a"]);    create_commit(&test_env, &repo_path, "c", &["b"]);    create_commit(&test_env, &repo_path, "d", &["b"]);    create_commit(&test_env, &repo_path, "e", &["a"]);    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  e: a    │ ○  d: b    │ │ ○  c: b    │ ├─╯    │ ○  b: a    ├─╯    ○  a    ◆    "###);     let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-b", "c", "-d", "e"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @"Rebased 3 commits onto destination");    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    ○  d: b    │ ○  c: b    ├─╯    ○  b: e    @  e: a    ○  a    ◆    "###);     // Test rebasing multiple bookmarks at once    test_env.jj_cmd_ok(&repo_path, &["undo"]);    let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-b=e", "-b=d", "-d=b"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r#"    Skipped rebase of 1 commits that were already in place    Rebased 1 commits onto destination    Working copy now at: znkkpsqq 9ca2a154 e | e    Parent commit      : zsuskuln 1394f625 b | b    Added 1 files, modified 0 files, removed 0 files    "#);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  e: b    │ ○  d: b    ├─╯    │ ○  c: b    ├─╯    ○  b: a    ○  a    ◆    "###);     // Same test but with more than one revision per argument    test_env.jj_cmd_ok(&repo_path, &["undo"]);    let stderr = test_env.jj_cmd_failure(&repo_path, &["rebase", "-b=e|d", "-d=b"]);    insta::assert_snapshot!(stderr, @r###"    Error: Revset "e|d" resolved to more than one revision    Hint: The revset "e|d" resolved to these revisions:      znkkpsqq e52756c8 e | e      vruxwmqv 514fa6b2 d | d    Hint: Prefix the expression with 'all:' to allow any number of revisions (i.e. 'all:e|d').    "###);    let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-b=all:e|d", "-d=b"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r#"    Skipped rebase of 1 commits that were already in place    Rebased 1 commits onto destination    Working copy now at: znkkpsqq 817e3fb0 e | e    Parent commit      : zsuskuln 1394f625 b | b    Added 1 files, modified 0 files, removed 0 files    "#);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  e: b    │ ○  d: b    ├─╯    │ ○  c: b    ├─╯    ○  b: a    ○  a    ◆    "###);} #[test]fn test_rebase_bookmark_with_merge() {    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");     create_commit(&test_env, &repo_path, "a", &[]);    create_commit(&test_env, &repo_path, "b", &["a"]);    create_commit(&test_env, &repo_path, "c", &[]);    create_commit(&test_env, &repo_path, "d", &["c"]);    create_commit(&test_env, &repo_path, "e", &["a", "d"]);    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @    e: a d    ├─╮    │ ○  d: c    │ ○  c    │ │ ○  b: a    ├───╯    ○ │  a    ├─╯    ◆    "###);     let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-b", "d", "-d", "b"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r#"    Rebased 3 commits onto destination    Working copy now at: znkkpsqq 5f8a3db2 e | e    Parent commit      : rlvkpnrz 2443ea76 a | a    Parent commit      : vruxwmqv 1677f795 d | d    Added 1 files, modified 0 files, removed 0 files    "#);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @    e: a d    ├─╮    │ ○  d: c    │ ○  c: b    │ ○  b: a    ├─╯    ○  a    ◆    "###);     test_env.jj_cmd_ok(&repo_path, &["undo"]);    let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-d", "b"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r#"    Rebased 3 commits onto destination    Working copy now at: znkkpsqq a331ac11 e | e    Parent commit      : rlvkpnrz 2443ea76 a | a    Parent commit      : vruxwmqv 3d0f3644 d | d    Added 1 files, modified 0 files, removed 0 files    "#);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @    e: a d    ├─╮    │ ○  d: c    │ ○  c: b    │ ○  b: a    ├─╯    ○  a    ◆    "###);} #[test]fn test_rebase_single_revision() {    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");     create_commit(&test_env, &repo_path, "a", &[]);    create_commit(&test_env, &repo_path, "b", &["a"]);    create_commit(&test_env, &repo_path, "c", &["a"]);    create_commit(&test_env, &repo_path, "d", &["b", "c"]);    create_commit(&test_env, &repo_path, "e", &["d"]);    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  e: d    ○    d: b c    ├─╮    │ ○  c: a    ○ │  b: a    ├─╯    ○  a    ◆    "###);     // Descendants of the rebased commit "c" should be rebased onto parents. First    // we test with a non-merge commit.    let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "c", "-d", "b"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r###"    Rebased 1 commits onto destination    Rebased 2 descendant commits    Working copy now at: znkkpsqq 2668ffbe e | e    Parent commit      : vruxwmqv 7b370c85 d | d    Added 0 files, modified 0 files, removed 1 files    "###);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  e: d    ○    d: b a    ├─╮    │ │ ○  c: b    ├───╯    ○ │  b: a    ├─╯    ○  a    ◆    "###);    test_env.jj_cmd_ok(&repo_path, &["undo"]);     // Now, let's try moving the merge commit. After, both parents of "d" ("b" and    // "c") should become parents of "e".    let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "d", "-d", "a"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r###"    Rebased 1 commits onto destination    Rebased 1 descendant commits    Working copy now at: znkkpsqq ed210c15 e | e    Parent commit      : zsuskuln 1394f625 b | b    Parent commit      : royxmykx c0cb3a0b c | c    Added 0 files, modified 0 files, removed 1 files    "###);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @    e: b c    ├─╮    │ ○  c: a    ○ │  b: a    ├─╯    │ ○  d: a    ├─╯    ○  a    ◆    "###);} #[test]fn test_rebase_single_revision_merge_parent() {    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");     create_commit(&test_env, &repo_path, "a", &[]);    create_commit(&test_env, &repo_path, "b", &[]);    create_commit(&test_env, &repo_path, "c", &["b"]);    create_commit(&test_env, &repo_path, "d", &["a", "c"]);    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @    d: a c    ├─╮    │ ○  c: b    │ ○  b    ○ │  a    ├─╯    ◆    "###);     // Descendants of the rebased commit should be rebased onto parents, and if    // the descendant is a merge commit, it shouldn't forget its other parents.    let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "c", "-d", "a"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r###"    Rebased 1 commits onto destination    Rebased 1 descendant commits    Working copy now at: vruxwmqv a37531e8 d | d    Parent commit      : rlvkpnrz 2443ea76 a | a    Parent commit      : zsuskuln d370aee1 b | b    Added 0 files, modified 0 files, removed 1 files    "###);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @    d: a b    ├─╮    │ ○  b    │ │ ○  c: a    ├───╯    ○ │  a    ├─╯    ◆    "###);} #[test]fn test_rebase_multiple_revisions() {    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");     create_commit(&test_env, &repo_path, "a", &[]);    create_commit(&test_env, &repo_path, "b", &["a"]);    create_commit(&test_env, &repo_path, "c", &["b"]);    create_commit(&test_env, &repo_path, "d", &["a"]);    create_commit(&test_env, &repo_path, "e", &["d"]);    create_commit(&test_env, &repo_path, "f", &["c", "e"]);    create_commit(&test_env, &repo_path, "g", &["f"]);    create_commit(&test_env, &repo_path, "h", &["g"]);    create_commit(&test_env, &repo_path, "i", &["f"]);    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  i: f    │ ○  h: g    │ ○  g: f    ├─╯    ○    f: c e    ├─╮    │ ○  e: d    │ ○  d: a    ○ │  c: b    ○ │  b: a    ├─╯    ○  a    ◆    "###);     // Test with two non-related non-merge commits.    let (stdout, stderr) =        test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "c", "-r", "e", "-d", "a"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r###"    Rebased 2 commits onto destination    Rebased 4 descendant commits    Working copy now at: xznxytkn 016685dc i | i    Parent commit      : kmkuslsw e04d3932 f | f    Added 0 files, modified 0 files, removed 2 files    "###);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  i: f    │ ○  h: g    │ ○  g: f    ├─╯    ○    f: b d    ├─╮    │ ○  d: a    ○ │  b: a    ├─╯    │ ○  e: a    ├─╯    │ ○  c: a    ├─╯    ○  a    ◆    "###);    test_env.jj_cmd_ok(&repo_path, &["undo"]);     // Test with two related non-merge commits. Since "b" is a parent of "c", when    // rebasing commits "b" and "c", their ancestry relationship should be    // preserved.    let (stdout, stderr) =        test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "b", "-r", "c", "-d", "e"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r###"    Rebased 2 commits onto destination    Rebased 4 descendant commits    Working copy now at: xznxytkn 94538385 i | i    Parent commit      : kmkuslsw dae8d293 f | f    Added 0 files, modified 0 files, removed 2 files    "###);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @  i: f    │ ○  h: g    │ ○  g: f    ├─╯    ○    f: a e    ├─╮    │ │ ○  c: b    │ │ ○  b: e    │ ├─╯    │ ○  e: d    │ ○  d: a    ├─╯    ○  a    ◆    "###);    test_env.jj_cmd_ok(&repo_path, &["undo"]);     // Test with a subgraph containing a merge commit. Since the merge commit "f"    // was extracted, its descendants which are not part of the subgraph will    // inherit its descendants which are not in the subtree ("c" and "d").    // "f" will retain its parent "c" since "c" is outside the target set, and not    // a descendant of any new children.    let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "e::g", "-d", "a"]);    insta::assert_snapshot!(stdout, @"");    insta::assert_snapshot!(stderr, @r###"    Rebased 3 commits onto destination    Rebased 2 descendant commits    Working copy now at: xznxytkn 1868ded4 i | i    Parent commit      : royxmykx 7e4fbf4f c | c    Parent commit      : vruxwmqv 4cc44fbf d | d    Added 0 files, modified 0 files, removed 2 files    "###);    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"    @    i: c d    ├─╮

Lines 1–500 of 2795.