Beispiel #1
0
def test_patchhelper_diff_injection_start_line():
    patch = PatchHelper(
        io.BytesIO(
            b"""
# HG changeset patch
# User byron jones <*****@*****.**>
# Date 1523427125 -28800
#      Wed Apr 11 14:12:05 2018 +0800
# Node ID 3379ea3cea34ecebdcb2cf7fb9f7845861ea8f07
# Parent  46c36c18528fe2cc780d5206ed80ae8e37d3545d
# Diff Start Line 14
WIP transplant and diff-start-line

diff --git a/bad b/bad
@@ -0,0 +0,0 @@
blah

diff --git a/autoland/autoland/transplant.py b/autoland/autoland/transplant.py
--- a/autoland/autoland/transplant.py
+++ b/autoland/autoland/transplant.py
@@ -318,24 +318,58 @@ class PatchTransplant(Transplant):
# instead of passing the url to 'hg import' to make
...
""".strip()
        )
    )
    assert patch.commit_description() == (
        b"WIP transplant and diff-start-line\n"
        b"\n"
        b"diff --git a/bad b/bad\n"
        b"@@ -0,0 +0,0 @@\n"
        b"blah"
    )
Beispiel #2
0
def test_patchhelper_no_header():
    patch = PatchHelper(
        io.BytesIO(
            b"""
WIP transplant and diff-start-line

diff --git a/autoland/autoland/transplant.py b/autoland/autoland/transplant.py
--- a/autoland/autoland/transplant.py
+++ b/autoland/autoland/transplant.py
@@ -318,24 +318,58 @@ class PatchTransplant(Transplant):
# instead of passing the url to 'hg import' to make
...
""".strip()
        )
    )
    assert patch.header("User") is None
    assert patch.commit_description() == b"WIP transplant and diff-start-line"
Beispiel #3
0
def test_patchhelper_vanilla_export():
    patch = PatchHelper(
        io.BytesIO(
            b"""
# HG changeset patch
# User byron jones <*****@*****.**>
# Date 1523427125 -28800
#      Wed Apr 11 14:12:05 2018 +0800
# Node ID 3379ea3cea34ecebdcb2cf7fb9f7845861ea8f07
# Parent  46c36c18528fe2cc780d5206ed80ae8e37d3545d
WIP transplant and diff-start-line

diff --git a/autoland/autoland/transplant.py b/autoland/autoland/transplant.py
--- a/autoland/autoland/transplant.py
+++ b/autoland/autoland/transplant.py
@@ -318,24 +318,58 @@ class PatchTransplant(Transplant):
# instead of passing the url to 'hg import' to make
...
""".strip()
        )
    )
    assert patch.header("Date") == b"1523427125 -28800"
    assert patch.header("Node ID") == b"3379ea3cea34ecebdcb2cf7fb9f7845861ea8f07"
    assert patch.header("User") == b"byron jones <*****@*****.**>"
    assert patch.header("Parent") == b"46c36c18528fe2cc780d5206ed80ae8e37d3545d"
    assert patch.commit_description() == b"WIP transplant and diff-start-line"
Beispiel #4
0
def test_patchhelper_write_no_start_line():
    header = b"""
# HG changeset patch
# User byron jones <*****@*****.**>
# Date 1523427125 -28800
#      Wed Apr 11 14:12:05 2018 +0800
# Node ID 3379ea3cea34ecebdcb2cf7fb9f7845861ea8f07
# Parent  46c36c18528fe2cc780d5206ed80ae8e37d3545d
""".strip()
    commit_desc = b"""
WIP transplant and diff-start-line
""".strip()
    diff = b"""
diff --git a/autoland/autoland/transplant.py b/autoland/autoland/transplant.py
--- a/autoland/autoland/transplant.py
+++ b/autoland/autoland/transplant.py
@@ -318,24 +318,58 @@ class PatchTransplant(Transplant):
# instead of passing the url to 'hg import' to make
...
""".strip()
    patch = PatchHelper(io.BytesIO(b"%s\n%s\n\n%s" % (header, commit_desc, diff)))

    buf = io.BytesIO(b"")
    patch.write_commit_description(buf)
    assert buf.getvalue() == commit_desc

    buf = io.BytesIO(b"")
    patch.write_diff(buf)
    assert buf.getvalue() == diff
Beispiel #5
0
def test_patchhelper_is_diff_line(line, expected):
    assert bool(PatchHelper._is_diff_line(line)) is expected
Beispiel #6
0
    def apply_patch(self, patch_io_buf):
        patch_helper = PatchHelper(patch_io_buf)
        if not patch_helper.diff_start_line:
            raise NoDiffStartLine()

        # Import the diff to apply the changes then commit separately to
        # ensure correct parsing of the commit message.
        f_msg = tempfile.NamedTemporaryFile()
        f_diff = tempfile.NamedTemporaryFile()
        with f_msg, f_diff:
            patch_helper.write_commit_description(f_msg)
            f_msg.flush()
            patch_helper.write_diff(f_diff)
            f_diff.flush()

            similarity_args = ["-s", "95"]

            # TODO: Using `hg import` here is less than ideal because
            # it does not use a 3-way merge. It would be better
            # to use `hg import --exact` then `hg rebase`, however we
            # aren't guaranteed to have the patche's parent changeset
            # in the local repo.
            # Also, Apply the patch, with file rename detection (similarity).
            # Using 95 as the similarity to match automv's default.
            import_cmd = ["import", "--no-commit"] + similarity_args

            try:
                if patch_helper.header("Fail HG Import") == b"FAIL":
                    # For testing, force a PatchConflict exception if this header is
                    # defined.
                    raise hglib.error.CommandError(
                        (),
                        1,
                        b"",
                        b"forced fail: hunk FAILED -- saving rejects to file",
                    )
                self.run_hg(import_cmd + [f_diff.name])
            except hglib.error.CommandError as exc:
                if isinstance(HgException.from_hglib_error(exc),
                              PatchConflict):
                    # Try again using 'patch' instead of hg's internal patch utility.
                    # But first reset to a clean working directory as hg's attempt
                    # might have partially applied the patch.
                    logger.info("import failed, retrying with 'patch'",
                                exc_info=exc)
                    import_cmd += ["--config", "ui.patch=patch"]
                    self.clean_repo(strip_non_public_commits=False)

                    try:
                        # When using an external patch util mercurial won't
                        # automatically handle add/remove/renames.
                        self.run_hg(import_cmd + [f_diff.name])
                        self.run_hg(["addremove"] + similarity_args)
                    except hglib.error.CommandError:
                        # Use the original exception from import with the built-in
                        # patcher since both attempts failed.
                        raise HgException.from_hglib_error(exc) from exc

            # Commit using the extracted date, user, and commit desc.
            # --landing_system is provided by the set_landing_system hgext.
            self.run_hg(["commit"] +
                        ["--date", patch_helper.header("Date")] +
                        ["--user", patch_helper.header("User")] +
                        ["--landing_system", "lando"] +
                        ["--logfile", f_msg.name])