Esempio n. 1
0
def test_merge_conflicts(
    data,
    output_format,
    dry_run,
    data_archive,
    cli_runner,
):
    with data_archive(f"conflicts/{data.ARCHIVE}.tgz") as repo_path:
        repo = KartRepo(repo_path)
        ancestor = CommitWithReference.resolve(repo, "ancestor_branch")
        ours = CommitWithReference.resolve(repo, "ours_branch")
        theirs = CommitWithReference.resolve(repo, "theirs_branch")

        cmd = ["merge", "theirs_branch", f"--output-format={output_format}"]
        if dry_run:
            cmd += ["--dry-run"]

        r = cli_runner.invoke(cmd)
        assert r.exit_code == 0, r

        if output_format == "text":
            merging_state_message = ([
                "(Not actually merging due to --dry-run)", ""
            ] if dry_run else [
                'Repository is now in "merging" state.',
                "View conflicts with `kart conflicts` and resolve them with `kart resolve`.",
                "Once no conflicts remain, complete this merge with `kart merge --continue`.",
                "Or use `kart merge --abort` to return to the previous state.",
                "",
            ])

            assert (r.stdout.split("\n") == [
                'Merging branch "theirs_branch" into ours_branch',
                "Conflicts found:",
                "",
                f"{data.LAYER}:",
                f"    {data.LAYER}:feature: 4 conflicts",
                "",
            ] + merging_state_message)

        else:
            jdict = json.loads(r.stdout)
            assert jdict == {
                "kart.merge/v1": {
                    "branch": "ours_branch",
                    "commit": ours.id.hex,
                    "merging": {
                        "ancestor": {
                            "commit": ancestor.id.hex,
                            "abbrevCommit": ancestor.short_id,
                        },
                        "ours": {
                            "branch": "ours_branch",
                            "commit": ours.id.hex,
                            "abbrevCommit": ours.short_id,
                        },
                        "theirs": {
                            "branch": "theirs_branch",
                            "commit": theirs.id.hex,
                            "abbrevCommit": theirs.short_id,
                        },
                    },
                    "dryRun": dry_run,
                    "message": 'Merge branch "theirs_branch" into ours_branch',
                    "conflicts": {
                        data.LAYER: {
                            "feature": 4
                        }
                    },
                    "state": "merging",
                },
            }

        if not dry_run:
            assert repo.read_gitdir_file(MERGE_HEAD).strip() == theirs.id.hex
            assert repo.read_gitdir_file(
                MERGE_BRANCH).strip() == "theirs_branch"
            assert (repo.read_gitdir_file(MERGE_MSG) ==
                    'Merge branch "theirs_branch" into ours_branch\n')

            merge_index = MergeIndex.read_from_repo(repo)
            assert len(merge_index.conflicts) == 4
            cli_runner.invoke(["merge", "--abort"])

        for filename in ALL_MERGE_FILES:
            assert not repo.gitdir_file(filename).exists()
Esempio n. 2
0
def test_commit_message(
    data_working_copy, cli_runner, monkeypatch, tmp_path, edit_points
):
    """ commit message handling """
    editor_in = None
    editor_out = None
    editor_cmd = None

    def monkey_editor(cmdline):
        nonlocal editor_cmd, editor_in
        editor_cmd = cmdline
        print("EDITOR", cmdline)
        editmsg_file = shlex.split(cmdline)[-1]
        with open(editmsg_file, "r+", encoding="utf-8") as ef:
            editor_in = ef.read()
            if editor_out:
                ef.seek(0)
                ef.truncate()
                ef.write(editor_out)
                return 0
            else:
                assert False, "Didn't expect editor to launch"

    monkeypatch.setattr(kart.commit, "run_editor_cmd", monkey_editor)
    monkeypatch.delenv("EDITOR", raising=False)
    monkeypatch.delenv("VISUAL", raising=False)
    monkeypatch.delenv("GIT_EDITOR", raising=False)

    with data_working_copy("points") as (repo_dir, wc_path):
        repo = KartRepo(repo_dir)

        def last_message():
            return repo.head_commit.message

        # normal
        r = cli_runner.invoke(
            ["commit", "--allow-empty", "-m", "the messagen\n\n\n\n\n"]
        )
        assert r.exit_code == 0, r
        assert last_message() == "the messagen"

        # E: empty
        r = cli_runner.invoke(["commit", "--allow-empty", "-m", ""])
        assert r.exit_code == INVALID_ARGUMENT, r

        # file
        f_commit_message = str(tmp_path / "commit-message.txt")
        with open(f_commit_message, mode="w", encoding="utf8") as f:
            f.write("\ni am a message\n\n\n")
            f.flush()

        r = cli_runner.invoke(
            ["commit", "--allow-empty", f"--message=@{f_commit_message}"]
        )
        assert r.exit_code == 0, r
        assert last_message() == "i am a message"

        # E: conflict
        r = cli_runner.invoke(
            ["commit", "--allow-empty", f"--message=@{f_commit_message}", "-m", "foo"]
        )
        assert r.exit_code == 0, r
        assert last_message() == "i am a message\n\nfoo"

        # multiple
        r = cli_runner.invoke(
            [
                "commit",
                "--allow-empty",
                "-m",
                "one",
                "-m",
                "two\nthree\n",
                "-m",
                "four\n\n",
            ]
        )
        assert r.exit_code == 0, r
        assert last_message() == "one\n\ntwo\nthree\n\nfour"

        # default editor

        # make some changes
        repo = KartRepo(repo_dir)
        with repo.working_copy.session() as sess:
            edit_points(sess)

        editor_out = "I am a message\n#of hope, and\nof warning\n\t\n"
        r = cli_runner.invoke(["commit"])
        assert r.exit_code == 0, r
        editmsg_path = str(repo.gitdir_file("COMMIT_EDITMSG"))
        assert re.match(
            rf'{fallback_editor()} "?{re.escape(editmsg_path)}"?$', editor_cmd
        )
        assert editor_in.splitlines() == [
            "",
            "# Please enter the commit message for your changes. Lines starting",
            "# with '#' will be ignored, and an empty message aborts the commit.",
            "#",
            "# On branch main",
            "#",
            "# Changes to be committed:",
            "#",
            "#   nz_pa_points_topo_150k:",
            "#     feature:",
            "#       1 inserts",
            "#       2 updates",
            "#       5 deletes",
            "#",
        ]

        print(last_message())
        assert last_message() == "I am a message\nof warning"

        monkeypatch.setenv("EDITOR", "/path/to/some/editor -abc")
        editor_out = "sqwark 🐧\n"
        r = cli_runner.invoke(["commit", "--allow-empty"])
        assert r.exit_code == 0, r
        editmsg_path = str(repo.gitdir_file("COMMIT_EDITMSG"))
        assert re.match(
            rf'/path/to/some/editor -abc "?{re.escape(editmsg_path)}"?$', editor_cmd
        )
        assert editor_in == (
            "\n"
            "# Please enter the commit message for your changes. Lines starting\n"
            "# with '#' will be ignored, and an empty message aborts the commit.\n"
            "#\n"
            "# On branch main\n"
            "#\n"
            "# Changes to be committed:\n"
            "#\n"
            "#   No changes (empty commit)\n"
            "#\n"
        )
        print(last_message())
        assert last_message() == "sqwark 🐧"