summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/third_party_build/restore_patch_stack.py
blob: 6db3a6419217a6b96ad142a8a99b54f757d6064d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import argparse
import os
import re
import shutil

from fetch_github_repo import fetch_repo
from run_operations import run_git, run_shell

# This script restores the mozilla patch stack and no-op commit tracking
# files.  In the case of repo corruption or a mistake made during
# various rebase conflict resolution operations, the patch-stack can be
# restored rather than requiring the user to restart the fast-forward
# process from the beginning.


def get_last_line(file_path):
    # technique from https://stackoverflow.com/questions/46258499/how-to-read-the-last-line-of-a-file-in-python
    with open(file_path, "rb") as f:
        try:  # catch OSError in case of a one line file
            f.seek(-2, os.SEEK_END)
            while f.read(1) != b"\n":
                f.seek(-2, os.SEEK_CUR)
        except OSError:
            f.seek(0)
        return f.readline().decode().strip()


def restore_patch_stack(
    github_path, github_branch, patch_directory, state_directory, tar_name
):
    # first, refetch the repo (hopefully utilizing the tarfile for speed) so
    # the patches apply cleanly
    fetch_repo(github_path, True, os.path.join(state_directory, tar_name))

    # remove any stale no-op-cherry-pick-msg files in state_directory
    run_shell("rm {}/*.no-op-cherry-pick-msg || true".format(state_directory))

    # lookup latest vendored commit from third_party/libwebrtc/README.moz-ff-commit
    file = os.path.abspath("third_party/libwebrtc/README.moz-ff-commit")
    last_vendored_commit = get_last_line(file)

    # checkout the previous vendored commit with proper branch name
    cmd = "git checkout -b {} {}".format(github_branch, last_vendored_commit)
    run_git(cmd, github_path)

    # restore the patches to moz-libwebrtc repo, use run_shell instead of
    # run_hg to allow filepath wildcard
    print("Restoring patch stack")
    run_shell("cd {} && git am {}/*.patch".format(github_path, patch_directory))

    # it is also helpful to restore the no-op-cherry-pick-msg files to
    # the state directory so that if we're restoring a patch-stack we
    # also restore the possibly consumed no-op tracking files.
    no_op_files = [
        path
        for path in os.listdir(patch_directory)
        if re.findall(".*no-op-cherry-pick-msg$", path)
    ]
    for file in no_op_files:
        shutil.copy(os.path.join(patch_directory, file), state_directory)


if __name__ == "__main__":
    default_patch_dir = "third_party/libwebrtc/moz-patch-stack"
    default_state_dir = ".moz-fast-forward"
    default_tar_name = "moz-libwebrtc.tar.gz"

    parser = argparse.ArgumentParser(
        description="Restore moz-libwebrtc github patch stack"
    )
    parser.add_argument(
        "--repo-path",
        required=True,
        help="path to libwebrtc repo",
    )
    parser.add_argument(
        "--branch",
        default="mozpatches",
        help="moz-libwebrtc branch (defaults to mozpatches)",
    )
    parser.add_argument(
        "--patch-path",
        default=default_patch_dir,
        help="path to save patches (defaults to {})".format(default_patch_dir),
    )
    parser.add_argument(
        "--tar-name",
        default=default_tar_name,
        help="name of tar file (defaults to {})".format(default_tar_name),
    )
    parser.add_argument(
        "--state-path",
        default=default_state_dir,
        help="path to state directory (defaults to {})".format(default_state_dir),
    )
    args = parser.parse_args()

    restore_patch_stack(
        args.repo_path,
        args.branch,
        os.path.abspath(args.patch_path),
        args.state_path,
        args.tar_name,
    )