File: protoc_wrapper.py

package info (click to toggle)
firefox 144.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,637,504 kB
  • sloc: cpp: 7,576,692; javascript: 6,430,831; ansic: 3,748,119; python: 1,398,978; xml: 628,810; asm: 438,679; java: 186,194; sh: 63,212; makefile: 19,159; objc: 13,086; perl: 12,986; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (121 lines) | stat: -rwxr-xr-x 3,421 bytes parent folder | download | duplicates (2)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python

import os
import sys
import platform
import subprocess
from pathlib import Path

import buildconfig
from mach.util import get_state_dir
from mozbuild.util import memoize
from mozbuild.vendor.moz_yaml import load_moz_yaml


TOPSRCDIR = Path(buildconfig.topsrcdir)
COMPONENT_DIR = Path(__file__).parent.parent


def protoc_binary(revision: None | str = None) -> Path:
    if not revision:
        revision = _get_protobuf_revision_from_moz_yaml()

    if not _get_protoc_dir(revision).exists():
        _download_protoc_binary(revision)

    return (
        _get_protoc_dir(revision)
        / "bin"
        / (f"protoc{'.exe' if platform.system() == 'Windows' else ''}")
    )


@memoize
def _get_protobuf_revision_from_moz_yaml():
    return load_moz_yaml(COMPONENT_DIR / "moz.yaml", verify=False, require_license_file=False)[
        "origin"
    ]["revision"]


def _get_protoc_dir(revision):
    return Path(get_state_dir()) / "protobuf" / f"protoc-{revision}"


def _download_protoc_binary(revision):
    import requests

    from tempfile import TemporaryFile
    from zipfile import ZipFile, ZipInfo

    with TemporaryFile() as temp:
        with requests.get(
            "https://github.com/protocolbuffers/protobuf/releases/download/"
            f"{revision}/protoc-{revision[1:]}-{_get_protoc_platform_ident()}.zip",
            stream=True,
        ) as r:
            r.raise_for_status()
            for chunk in r.iter_content(chunk_size=8192):
                temp.write(chunk)

        class ZipFileWithPermissions(ZipFile):
            """Custom ZipFile class handling file permissions."""

            def _extract_member(self, member, targetpath, pwd):
                if not isinstance(member, ZipInfo):
                    member = self.getinfo(member)

                targetpath = super(ZipFile, self)._extract_member(member, targetpath, pwd)

                attr = member.external_attr >> 16
                if attr != 0:
                    os.chmod(targetpath, attr)
                return targetpath

        with ZipFileWithPermissions(temp) as protoc_bin_release:
            protoc_bin_release.extractall(_get_protoc_dir(revision))


def _get_protoc_platform_ident():
    system = platform.system()
    machine = platform.machine()
    if system == "Darwin":
        return "osx-universal_binary"
    elif system == "Linux":
        if machine == "x86_64":
            return "linux-x86_64"
        elif machine == "i686":
            return "linux-x86_32"
    elif system == "Windows":
        if machine == "AMD64":
            return "win64"
        elif machine == "i686":
            return "win32"
    raise Exception("Unsupported system")


if __name__ == "__main__":
    args = sys.argv[1:]

    # The protoc compiler has support to generate rust files but it's currently
    # highly experimental.
    #
    # This is a workaround for now
    if "--rust_out" in args:
        env = os.environ.copy()
        env["PROTOC"] = protoc_binary()
        env["TOPSRCDIR"] = buildconfig.topsrcdir
        subprocess.run(
            [
                "cargo",
                "run",
                "--locked",
                "--quiet",
                "--",
                *args,
            ],
            cwd=Path(__file__).parent,
            env=env,
            check=True,
        )
    else:
        subprocess.run([protoc_binary(), *args], check=True)