Welcome to mirror list, hosted at ThFree Co, Russian Federation.

create_msix_package.py « msix « windows « release - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3e41484eef5d8835b941e196b15aedbacfceb838 (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/usr/bin/env python3

import argparse
import os
import pathlib
import requests
import shutil
import subprocess
import zipfile

parser = argparse.ArgumentParser()
parser.add_argument(
    "--version",
    required=True,
    help="Version string in the form of 2.83.3.0",
)
parser.add_argument(
    "--url",
    required=True,
    help="Location of the release ZIP archive to download",
)
parser.add_argument(
    "--publisher",
    required=True,
    help="A string in the form of 'CN=PUBLISHER'",
)
parser.add_argument(
    "--pfx",
    required=False,
    help="Absolute path to the PFX file used for signing the resulting MSIX package",
)
parser.add_argument(
    "--password",
    required=False,
    default="blender",
    help="Password for the PFX file",
)
parser.add_argument(
    "--lts",
    required=False,
    help="If set this MSIX is for an LTS release",
    action='store_const',
    const=1,
)
parser.add_argument(
    "--skipdl",
    required=False,
    help="If set skip downloading of the specified URL as blender.zip. The tool assumes blender.zip exists",
    action='store_const',
    const=1,
)
parser.add_argument(
    "--leavezip",
    required=False,
    help="If set don't clean up the downloaded blender.zip",
    action='store_const',
    const=1,
)
parser.add_argument(
    "--overwrite",
    required=False,
    help="If set remove Content folder if it already exists",
    action='store_const',
    const=1,
)
args = parser.parse_args()


def execute_command(cmd: list, name: str, errcode: int):
    """
    Execute given command in cmd. Output is captured. If an error
    occurs name is used to print ERROR message, along with stderr and
    stdout of the process if either was captured.
    """
    cmd_process = subprocess.run(cmd, capture_output=True, encoding="UTF-8")
    if cmd_process.returncode != 0:
        print(f"ERROR: {name} failed.")
        if cmd_process.stdout:
            print(cmd_process.stdout)
        if cmd_process.stderr:
            print(cmd_process.stderr)
        exit(errcode)


LTSORNOT = ""
PACKAGETYPE = ""
if args.lts:
    versionparts = args.version.split(".")
    LTSORNOT = f" {versionparts[0]}.{versionparts[1]} LTS"
    PACKAGETYPE = f"{versionparts[0]}.{versionparts[1]}LTS"

blender_package_msix = pathlib.Path(".", f"blender-{args.version}-windows64.msix").absolute()
content_folder = pathlib.Path(".", "Content")
content_blender_folder = pathlib.Path(content_folder, "Blender").absolute()
content_assets_folder = pathlib.Path(content_folder, "Assets")
assets_original_folder = pathlib.Path(".", "Assets")

pri_config_file = pathlib.Path(".", "priconfig.xml")
pri_resources_file = pathlib.Path(content_folder, "resources.pri")

local_blender_zip = pathlib.Path(".", "blender.zip")

if args.pfx:
    pfx_path = pathlib.Path(args.pfx)
    if not pfx_path.exists():
        print("ERROR: PFX file not found. Please ensure you give the correct path to the PFX file on the command-line.")
        exit(1)
    print(f"Creating MSIX package with signing using PFX file at {pfx_path}")
else:
    pfx_path = None
    print("Creating MSIX package without signing.")

pri_command = ["makepri",
                   "new",
                   "/pr", f"{content_folder.absolute()}",
                   "/cf", f"{pri_config_file.absolute()}",
                   "/of", f"{pri_resources_file.absolute()}"
                   ]

msix_command = ["makeappx",
                "pack",
                "/h", "SHA256",
                "/d", f"{content_folder.absolute()}",
                "/p", f"{blender_package_msix}"
                ]
if pfx_path:
    sign_command = ["signtool",
                    "sign",
                    "/fd", "sha256",
                    "/a", "/f", f"{pfx_path.absolute()}",
                    "/p", f"{args.password}",
                    f"{blender_package_msix}"
                    ]

if args.overwrite:
    if content_folder.joinpath("Assets").exists():
        shutil.rmtree(content_folder)
content_folder.mkdir(exist_ok=True)
shutil.copytree(assets_original_folder, content_assets_folder)

manifest_text = pathlib.Path("AppxManifest.xml.template").read_text()
manifest_text = manifest_text.replace("[VERSION]", args.version)
manifest_text = manifest_text.replace("[PUBLISHER]", args.publisher)
manifest_text = manifest_text.replace("[LTSORNOT]", LTSORNOT)
manifest_text = manifest_text.replace("[PACKAGETYPE]", PACKAGETYPE)
pathlib.Path(content_folder, "AppxManifest.xml").write_text(manifest_text)

if not args.skipdl:
    print(f"Downloading blender archive {args.url} to {local_blender_zip}...")

    with open(local_blender_zip, "wb") as download_zip:
        response = requests.get(args.url)
        download_zip.write(response.content)

    print("... download complete.")
else:
    print("Skipping download")

print(f"Extracting files from ZIP to {content_blender_folder}...")

# Extract the files from the ZIP archive, but skip the leading part of paths
# in the ZIP. We want to write the files to the content_blender_folder where
# blender.exe ends up as ./Content/Blender/blender.exe, and not
# ./Content/Blender/blender-2.83.3-windows64/blender.exe
with zipfile.ZipFile(local_blender_zip, "r") as blender_zip:
    for entry in blender_zip.infolist():
        if entry.is_dir():
            continue
        entry_location = pathlib.Path(entry.filename)
        target_location = content_blender_folder.joinpath(*entry_location.parts[1:])
        pathlib.Path(target_location.parent).mkdir(parents=True, exist_ok=True)
        extracted_entry = blender_zip.read(entry)
        target_location.write_bytes(extracted_entry)

print("... extraction complete.")


print(f"Generating Package Resource Index (PRI) file using command: {' '.join(pri_command)}")
execute_command(pri_command, "MakePri", 4)

print(f"Creating MSIX package using command: {' '.join(msix_command)}")

# Remove MSIX file if it already exists. Otherwise the MakeAppX tool
# will hang.
if blender_package_msix.exists():
    os.remove(blender_package_msix)
execute_command(msix_command, "MakeAppX", 2)

if args.pfx:
    print(f"Signing MSIX package using command: {' '.join(sign_command)}")
    execute_command(sign_command, "SignTool", 3)

if not args.leavezip:
    os.remove(local_blender_zip)
shutil.rmtree(content_folder)

print("Done.")