2127 lines · 68.1 KB · Rust
RawDownload
// Copyright 2023 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::git; use crate::common::create_commit;use crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir; fn add_commit_to_branch(git_repo: &gix::Repository, branch: &str) -> gix::ObjectId {    git::add_commit(        git_repo,        &format!("refs/heads/{branch}"),        branch,            // filename        branch.as_bytes(), // content        "message",        &[],    )    .commit_id} /// Creates a remote Git repo containing a bookmark with the same namefn init_git_remote(test_env: &TestEnvironment, remote: &str) -> gix::Repository {    let git_repo_path = test_env.env_root().join(remote);    let git_repo = git::init(git_repo_path);    add_commit_to_branch(&git_repo, remote);     git_repo} /// Add a remote containing a bookmark with the same namefn add_git_remote(    test_env: &TestEnvironment,    work_dir: &TestWorkDir,    remote: &str,) -> gix::Repository {    let repo = init_git_remote(test_env, remote);    work_dir        .run_jj(["git", "remote", "add", remote, &format!("../{remote}")])        .success();     repo} #[must_use]fn get_bookmark_output(work_dir: &TestWorkDir) -> CommandOutput {    // --quiet to suppress deleted bookmarks hint    work_dir.run_jj(["bookmark", "list", "--all-remotes", "--quiet"])} #[must_use]fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput {    let template =        r#"commit_id.short() ++ " \"" ++ description.first_line() ++ "\" " ++ bookmarks"#;    work_dir.run_jj(["log", "-T", template, "-r", "all()"])} fn clone_git_remote_into(    test_env: &TestEnvironment,    upstream: &str,    fork: &str,) -> gix::Repository {    let upstream_path = test_env.env_root().join(upstream);    let fork_path = test_env.env_root().join(fork);    let fork_repo = git::clone(&fork_path, upstream_path.to_str().unwrap(), Some(upstream));     // create local branch mirroring the upstream    let upstream_head = fork_repo        .find_reference(&format!("refs/remotes/{upstream}/{upstream}"))        .unwrap()        .peel_to_id_in_place()        .unwrap()        .detach();     fork_repo        .reference(            format!("refs/heads/{upstream}"),            upstream_head,            gix::refs::transaction::PreviousValue::MustNotExist,            "create tracking head",        )        .unwrap();     fork_repo} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_with_default_config(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "origin");     work_dir.run_jj(["git", "fetch"]).success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    origin@origin: qmyrypzk ab8b299e message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_default_remote(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "origin");     work_dir.run_jj(["git", "fetch"]).success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    origin: qmyrypzk ab8b299e message      @origin: qmyrypzk ab8b299e message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_single_remote(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");     let output = work_dir.run_jj(["git", "fetch"]);    insta::allow_duplicates! {    insta::assert_snapshot!(output, @r"    ------- stderr -------    Hint: Fetching from the only existing remote: rem1    bookmark: rem1@rem1 [new] tracked    [EOF]    ");    }    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_single_remote_all_remotes_flag(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");     work_dir.run_jj(["git", "fetch", "--all-remotes"]).success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_single_remote_from_arg(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");     work_dir        .run_jj(["git", "fetch", "--remote", "rem1"])        .success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_single_remote_from_config(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    test_env.add_config(r#"git.fetch = "rem1""#);     work_dir.run_jj(["git", "fetch"]).success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_multiple_remotes(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    add_git_remote(&test_env, &work_dir, "rem2");     work_dir        .run_jj(["git", "fetch", "--remote", "rem1", "--remote", "rem2"])        .success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    rem2: pzqqpnpo 44c57802 message      @rem2: pzqqpnpo 44c57802 message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_with_glob(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    add_git_remote(&test_env, &work_dir, "rem2");     let output = work_dir.run_jj(["git", "fetch", "--remote", "glob:*"]);    insta::allow_duplicates! {    insta::assert_snapshot!(output, @r"    ------- stderr -------    bookmark: rem1@rem1 [new] untracked    bookmark: rem2@rem2 [new] untracked    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_with_glob_and_exact_match(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    add_git_remote(&test_env, &work_dir, "rem2");    add_git_remote(&test_env, &work_dir, "upstream1");    add_git_remote(&test_env, &work_dir, "upstream2");    add_git_remote(&test_env, &work_dir, "origin");     let output = work_dir.run_jj(["git", "fetch", "--remote=glob:rem*", "--remote=origin"]);    insta::allow_duplicates! {    insta::assert_snapshot!(output, @r"    ------- stderr -------    bookmark: origin@origin [new] untracked    bookmark: rem1@rem1     [new] untracked    bookmark: rem2@rem2     [new] untracked    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_with_glob_from_config(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config(r#"git.fetch = "glob:rem*""#);    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    add_git_remote(&test_env, &work_dir, "rem2");    add_git_remote(&test_env, &work_dir, "upstream");     let output = work_dir.run_jj(["git", "fetch"]);    insta::allow_duplicates! {    insta::assert_snapshot!(output, @r"    ------- stderr -------    bookmark: rem1@rem1 [new] untracked    bookmark: rem2@rem2 [new] untracked    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_with_glob_with_no_matching_remotes(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "upstream");     let output = work_dir.run_jj(["git", "fetch", "--remote=glob:rem*"]);    insta::allow_duplicates! {    insta::assert_snapshot!(output, @r"    ------- stderr -------    Error: No matching git remotes for patterns: rem*    [EOF]    [exit status: 1]    ");    }    // No remote should have been fetched as part of the failing transaction    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_all_remotes(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    add_git_remote(&test_env, &work_dir, "rem2");     // add empty [remote "rem3"] section to .git/config, which should be ignored    work_dir        .run_jj(["git", "remote", "add", "rem3", "../unknown"])        .success();    work_dir        .run_jj(["git", "remote", "remove", "rem3"])        .success();     work_dir.run_jj(["git", "fetch", "--all-remotes"]).success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    rem2: pzqqpnpo 44c57802 message      @rem2: pzqqpnpo 44c57802 message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_multiple_remotes_from_config(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    add_git_remote(&test_env, &work_dir, "rem2");    test_env.add_config(r#"git.fetch = ["rem1", "rem2"]"#);     work_dir.run_jj(["git", "fetch"]).success();    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    rem2: pzqqpnpo 44c57802 message      @rem2: pzqqpnpo 44c57802 message    [EOF]    ");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_nonexistent_remote(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");     let output = work_dir.run_jj(["git", "fetch", "--remote", "rem1", "--remote", "rem2"]);    insta::allow_duplicates! {    insta::assert_snapshot!(output, @r"    ------- stderr -------    Error: No git remote named 'rem2'    [EOF]    [exit status: 1]    ");    }    insta::allow_duplicates! {    // No remote should have been fetched as part of the failing transaction    insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_nonexistent_remote_from_config(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");    add_git_remote(&test_env, &work_dir, "rem1");    test_env.add_config(r#"git.fetch = ["rem1", "rem2"]"#);     let output = work_dir.run_jj(["git", "fetch"]);    insta::allow_duplicates! {    insta::assert_snapshot!(output, @r"    ------- stderr -------    Error: No git remote named 'rem2'    [EOF]    [exit status: 1]    ");    }    // No remote should have been fetched as part of the failing transaction    insta::allow_duplicates! {    insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");    }} #[cfg_attr(feature = "git2", test_case(false; "use git2 for remote calls"))]#[test_case(true; "spawn a git subprocess for remote calls")]fn test_git_fetch_from_remote_named_git(subprocess: bool) {    let test_env = TestEnvironment::default();    if !subprocess {        test_env.add_config("git.subprocess = false");    }    test_env.add_config("git.auto-local-bookmark = true");    let work_dir = test_env.work_dir("repo");    init_git_remote(&test_env, "git");     git::init(work_dir.root());    git::add_remote(work_dir.root(), "git", "../git");     // Existing remote named 'git' shouldn't block the repo initialization.    work_dir.run_jj(["git", "init", "--git-repo=."]).success();     // Try fetching from the remote named 'git'.    let output = work_dir.run_jj(["git", "fetch", "--remote=git"]);    insta::allow_duplicates! {

Lines 1–500 of 2127.