1757 lines · 56.5 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 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} #[test]fn test_git_fetch_with_default_config() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(get_bookmark_output(&work_dir), @r"    origin@origin: qmyrypzk ab8b299e message    [EOF]    ");} #[test]fn test_git_fetch_default_remote() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(get_bookmark_output(&work_dir), @r"    origin: qmyrypzk ab8b299e message      @origin: qmyrypzk ab8b299e message    [EOF]    ");} #[test]fn test_git_fetch_single_remote() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    Hint: Fetching from the only existing remote: rem1    bookmark: rem1@rem1 [new] tracked    [EOF]    ");    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");} #[test]fn test_git_fetch_single_remote_all_remotes_flag() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");} #[test]fn test_git_fetch_single_remote_from_arg() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");} #[test]fn test_git_fetch_single_remote_from_config() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1: ppspxspk 4acd0343 message      @rem1: ppspxspk 4acd0343 message    [EOF]    ");} #[test]fn test_git_fetch_multiple_remotes() {    let test_env = TestEnvironment::default();    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::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]    ");} #[test]fn test_git_fetch_with_glob() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    bookmark: rem1@rem1 [new] untracked    bookmark: rem2@rem2 [new] untracked    [EOF]    ");} #[test]fn test_git_fetch_with_glob_and_exact_match() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    bookmark: origin@origin [new] untracked    bookmark: rem1@rem1     [new] untracked    bookmark: rem2@rem2     [new] untracked    [EOF]    ");} #[test]fn test_git_fetch_with_glob_from_config() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    bookmark: rem1@rem1 [new] untracked    bookmark: rem2@rem2 [new] untracked    [EOF]    ");} #[test]fn test_git_fetch_with_glob_with_no_matching_remotes() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    Warning: No git remotes matching 'rem*'    Error: No git remotes to fetch from    [EOF]    [exit status: 1]    ");    // No remote should have been fetched as part of the failing transaction    insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");} #[test]fn test_git_fetch_all_remotes() {    let test_env = TestEnvironment::default();    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::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]    ");} #[test]fn test_git_fetch_multiple_remotes_from_config() {    let test_env = TestEnvironment::default();    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::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]    ");} #[test]fn test_git_fetch_no_matching_remote() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");     let output = work_dir.run_jj(["git", "fetch", "--remote", "rem1"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Warning: No git remotes matching 'rem1'    Error: No git remotes to fetch from    [EOF]    [exit status: 1]    ");    insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");} #[test]fn test_git_fetch_nonexistent_remote() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    Warning: No git remotes matching 'rem2'    bookmark: rem1@rem1 [new] untracked    [EOF]    ");    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1@rem1: ppspxspk 4acd0343 message    [EOF]    ");} #[test]fn test_git_fetch_nonexistent_remote_from_config() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    Warning: No git remotes matching 'rem2'    bookmark: rem1@rem1 [new] untracked    [EOF]    ");    insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"    rem1@rem1: ppspxspk 4acd0343 message    [EOF]    ");} #[test]fn test_git_fetch_from_remote_named_git() {    let test_env = TestEnvironment::default();    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::assert_snapshot!(output, @r"    ------- stderr -------    Error: Git remote named 'git' is reserved for local Git repository    Hint: Run `jj git remote rename` to give a different name.    [EOF]    [exit status: 1]    ");     // Fetch remote refs by using the git CLI.    git::fetch(work_dir.root(), "git");     // Implicit import shouldn't fail because of the remote ref.    let output = work_dir.run_jj(["bookmark", "list", "--all-remotes"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Warning: Failed to import some Git refs:      refs/remotes/git/git    Hint: Git remote named 'git' is reserved for local Git repository.    Use `jj git remote rename` to give a different name.    [EOF]    ");     // Explicit import also works. Warnings are printed twice because this is a    // colocated repo. That should be fine since "jj git import" wouldn't be    // used in colocated environment.    insta::assert_snapshot!(work_dir.run_jj(["git", "import"]), @r"    ------- stderr -------    Warning: Failed to import some Git refs:      refs/remotes/git/git    Hint: Git remote named 'git' is reserved for local Git repository.    Use `jj git remote rename` to give a different name.    Warning: Failed to import some Git refs:      refs/remotes/git/git    Hint: Git remote named 'git' is reserved for local Git repository.    Use `jj git remote rename` to give a different name.    Nothing changed.    [EOF]    ");     // The remote can be renamed, and the ref can be imported.    work_dir        .run_jj(["git", "remote", "rename", "git", "bar"])        .success();    let output = work_dir.run_jj(["bookmark", "list", "--all-remotes"]);    insta::assert_snapshot!(output, @r"    git: vkponlun 400c483d message      @bar: vkponlun 400c483d message      @git: vkponlun 400c483d message    [EOF]    ------- stderr -------    Done importing changes from the underlying Git repo.    [EOF]    ");} #[test]fn test_git_fetch_from_remote_with_slashes() {    let test_env = TestEnvironment::default();    test_env.add_config("git.auto-local-bookmark = true");    let work_dir = test_env.work_dir("repo");    init_git_remote(&test_env, "source");     git::init(work_dir.root());    git::add_remote(work_dir.root(), "slash/origin", "../source");     // Existing remote with slash 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=slash/origin"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Error: Git remotes with slashes are incompatible with jj: slash/origin    Hint: Run `jj git remote rename` to give a different name.    [EOF]    [exit status: 1]    ");} #[test]fn test_git_fetch_prune_before_updating_tips() {    let test_env = TestEnvironment::default();

Lines 1–500 of 1757.