mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
@@ -1,12 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
import sys
|
||||
import uuid
|
||||
import argparse
|
||||
import datetime
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
g_indent_unit = "\t"
|
||||
g_version = ""
|
||||
g_build_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||
|
||||
# https://learn.microsoft.com/en-us/windows/win32/msi/property-reference
|
||||
g_arpsystemcomponent = {
|
||||
"Comments": {
|
||||
"msi": "ARPCOMMENTS",
|
||||
"t": "string",
|
||||
"v": "!(loc.AR_Comment)",
|
||||
},
|
||||
"Contact": {
|
||||
"msi": "ARPCONTACT",
|
||||
"v": "https://github.com/rustdesk/rustdesk",
|
||||
},
|
||||
"HelpLink": {
|
||||
"msi": "ARPHELPLINK",
|
||||
"v": "https://github.com/rustdesk/rustdesk/issues/",
|
||||
},
|
||||
"ReadMe": {
|
||||
"msi": "ARPREADME",
|
||||
"v": "https://github.com/fufesou/rustdesk",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def make_parser():
|
||||
@@ -14,6 +40,23 @@ def make_parser():
|
||||
parser.add_argument(
|
||||
"-d", "--debug", action="store_true", help="Is debug", default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
"-ci", "--github-ci", action="store_true", help="Is github ci", default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
"-arp",
|
||||
"--arp",
|
||||
action="store_true",
|
||||
help="Is ARPSYSTEMCOMPONENT",
|
||||
default=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-custom-arp",
|
||||
"--custom-arp",
|
||||
type=str,
|
||||
default="{}",
|
||||
help='Custom arp properties, e.g. \'["Comments": {"msi": "ARPCOMMENTS", "v": "Remote control application."}]\'',
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c", "--custom", action="store_true", help="Is custom client", default=False
|
||||
)
|
||||
@@ -21,13 +64,13 @@ def make_parser():
|
||||
"-an", "--app-name", type=str, default="RustDesk", help="The app name."
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v", "--version", type=str, default="1.2.4", help="The app version."
|
||||
"-v", "--version", type=str, default="", help="The app version."
|
||||
)
|
||||
parser.add_argument(
|
||||
"-m",
|
||||
"--manufacturer",
|
||||
type=str,
|
||||
default="Purslane Ltd",
|
||||
default="RustDesk",
|
||||
help="The app manufacturer.",
|
||||
)
|
||||
return parser
|
||||
@@ -103,7 +146,7 @@ def gen_pre_vars(args, build_dir):
|
||||
|
||||
indent = g_indent_unit * 1
|
||||
to_insert_lines = [
|
||||
f'{indent}<?define Version="{args.version}" ?>\n',
|
||||
f'{indent}<?define Version="{g_version}" ?>\n',
|
||||
f'{indent}<?define Manufacturer="{args.manufacturer}" ?>\n',
|
||||
f'{indent}<?define Product="{args.app_name}" ?>\n',
|
||||
f'{indent}<?define Description="{args.app_name} Installer" ?>\n',
|
||||
@@ -111,6 +154,7 @@ def gen_pre_vars(args, build_dir):
|
||||
f'{indent}<?define RegKeyRoot=".$(var.ProductLower)" ?>\n',
|
||||
f'{indent}<?define RegKeyInstall="$(var.RegKeyRoot)\Install" ?>\n',
|
||||
f'{indent}<?define BuildDir="{build_dir}" ?>\n',
|
||||
f'{indent}<?define BuildDate="{g_build_date}" ?>\n',
|
||||
"\n",
|
||||
f"{indent}<!-- The UpgradeCode must be consistent for each product. ! -->\n"
|
||||
f'{indent}<?define UpgradeCode = "{upgrade_code}" ?>\n',
|
||||
@@ -118,6 +162,7 @@ def gen_pre_vars(args, build_dir):
|
||||
|
||||
for i, line in enumerate(to_insert_lines):
|
||||
lines.insert(index_start + i + 1, line)
|
||||
return lines
|
||||
|
||||
return gen_content_between_tags(
|
||||
"Package/Includes.wxi", "<!--$PreVarsStart$-->", "<!--$PreVarsEnd$-->", func
|
||||
@@ -135,15 +180,15 @@ def replace_app_name_in_lans(app_name):
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def gen_upgrade_info(version):
|
||||
def gen_upgrade_info():
|
||||
def func(lines, index_start):
|
||||
indent = g_indent_unit * 3
|
||||
|
||||
major, _, _ = version.split(".")
|
||||
major, _, _ = g_version.split(".")
|
||||
upgrade_id = uuid.uuid4()
|
||||
to_insert_lines = [
|
||||
f'{indent}<Upgrade Id="{upgrade_id}">\n',
|
||||
f'{indent}{g_indent_unit}<UpgradeVersion Property="OLD_VERSION_FOUND" Minimum="{major}.0.0.0" Maximum="{major}.99.99" IncludeMinimum="yes" IncludeMaximum="yes" OnlyDetect="no" IgnoreRemoveFailure="yes" MigrateFeatures="yes" />\n',
|
||||
f'{indent}{g_indent_unit}<UpgradeVersion Property="OLD_VERSION_FOUND" Minimum="{major}.0.0" Maximum="{major}.99.99" IncludeMinimum="yes" IncludeMaximum="yes" OnlyDetect="no" IgnoreRemoveFailure="yes" MigrateFeatures="yes" />\n',
|
||||
f"{indent}</Upgrade>\n",
|
||||
]
|
||||
|
||||
@@ -159,6 +204,175 @@ def gen_upgrade_info(version):
|
||||
)
|
||||
|
||||
|
||||
def gen_custom_dialog_bitmaps():
|
||||
def func(lines, index_start):
|
||||
indent = g_indent_unit * 2
|
||||
|
||||
# https://wixtoolset.org/docs/tools/wixext/wixui/#customizing-a-dialog-set
|
||||
vars = [
|
||||
"WixUIBannerBmp",
|
||||
"WixUIDialogBmp",
|
||||
"WixUIExclamationIco",
|
||||
"WixUIInfoIco",
|
||||
"WixUINewIco",
|
||||
"WixUIUpIco",
|
||||
]
|
||||
to_insert_lines = []
|
||||
for var in vars:
|
||||
if Path(f"Package/Resources/{var}.bmp").exists():
|
||||
to_insert_lines.append(
|
||||
f'{indent}<WixVariable Id="{var}" Value="Resources\\{var}.bmp" />\n'
|
||||
)
|
||||
|
||||
for i, line in enumerate(to_insert_lines):
|
||||
lines.insert(index_start + i + 1, line)
|
||||
return lines
|
||||
|
||||
return gen_content_between_tags(
|
||||
"Package/Package.wxs",
|
||||
"<!--$CustomBitmapsStart$-->",
|
||||
"<!--$CustomBitmapsEnd$-->",
|
||||
func,
|
||||
)
|
||||
|
||||
|
||||
def gen_custom_ARPSYSTEMCOMPONENT_False(args):
|
||||
def func(lines, index_start):
|
||||
indent = g_indent_unit * 2
|
||||
|
||||
lines_new = []
|
||||
lines_new.append(
|
||||
f"{indent}<!--https://learn.microsoft.com/en-us/windows/win32/msi/arpsystemcomponent?redirectedfrom=MSDN-->\n"
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<!--<Property Id="ARPSYSTEMCOMPONENT" Value="1" />-->\n\n'
|
||||
)
|
||||
|
||||
lines_new.append(
|
||||
f"{indent}<!--https://learn.microsoft.com/en-us/windows/win32/msi/property-reference-->\n"
|
||||
)
|
||||
for _, v in g_arpsystemcomponent.items():
|
||||
if "msi" in v and "v" in v:
|
||||
lines_new.append(f'{indent}<Property Id="{v["msi"]}" Value="{v["v"]}" />\n')
|
||||
|
||||
for i, line in enumerate(lines_new):
|
||||
lines.insert(index_start + i + 1, line)
|
||||
return lines
|
||||
|
||||
return gen_content_between_tags(
|
||||
"Package/Fragments/AddRemoveProperties.wxs",
|
||||
"<!--$ArpStart$-->",
|
||||
"<!--$ArpEnd$-->",
|
||||
func,
|
||||
)
|
||||
|
||||
|
||||
def get_folder_size(folder_path):
|
||||
total_size = 0
|
||||
|
||||
folder = Path(folder_path)
|
||||
for file in folder.glob("**/*"):
|
||||
if file.is_file():
|
||||
total_size += file.stat().st_size
|
||||
|
||||
return total_size
|
||||
|
||||
|
||||
def gen_custom_ARPSYSTEMCOMPONENT_True(args, build_dir):
|
||||
def func(lines, index_start):
|
||||
indent = g_indent_unit * 5
|
||||
|
||||
lines_new = []
|
||||
lines_new.append(
|
||||
f"{indent}<!--https://learn.microsoft.com/en-us/windows/win32/msi/property-reference-->\n"
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="DisplayName" Value="{args.app_name}" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="DisplayIcon" Value="[INSTALLFOLDER]{args.app_name}.exe" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="DisplayVersion" Value="{g_version}" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="Publisher" Value="{args.manufacturer}" />\n'
|
||||
)
|
||||
installDate = datetime.datetime.now().strftime("%Y%m%d")
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="InstallDate" Value="{installDate}" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="InstallLocation" Value="[INSTALLFOLDER]" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="InstallSource" Value="[InstallSource]" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="integer" Name="Language" Value="[ProductLanguage]" />\n'
|
||||
)
|
||||
|
||||
estimated_size = get_folder_size(build_dir)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="integer" Name="EstimatedSize" Value="{estimated_size}" />\n'
|
||||
)
|
||||
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="expandable" Name="ModifyPath" Value="MsiExec.exe /X [ProductCode]" />\n'
|
||||
)
|
||||
lines_new.append(f'{indent}<RegistryValue Type="integer" Id="NoModify" Value="1" />\n')
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="expandable" Name="UninstallString" Value="MsiExec.exe /X [ProductCode]" />\n'
|
||||
)
|
||||
|
||||
major, minor, build = g_version.split(".")
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="string" Name="Version" Value="{g_version}" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="integer" Name="VersionMajor" Value="{major}" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="integer" Name="VersionMinor" Value="{minor}" />\n'
|
||||
)
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="integer" Name="VersionBuild" Value="{build}" />\n'
|
||||
)
|
||||
|
||||
lines_new.append(
|
||||
f'{indent}<RegistryValue Type="integer" Name="WindowsInstaller" Value="1" />\n'
|
||||
)
|
||||
for k, v in g_arpsystemcomponent.items():
|
||||
if 'v' in v:
|
||||
t = v['t'] if 't' in v is None else 'string'
|
||||
lines_new.append(f'{indent}<RegistryValue Type="{t}" Name="{k}" Value="{v["v"]}" />\n')
|
||||
|
||||
for i, line in enumerate(lines_new):
|
||||
lines.insert(index_start + i + 1, line)
|
||||
return lines
|
||||
|
||||
return gen_content_between_tags(
|
||||
"Package/Components/Regs.wxs",
|
||||
"<!--$ArpStart$-->",
|
||||
"<!--$ArpEnd$-->",
|
||||
func,
|
||||
)
|
||||
|
||||
|
||||
def gen_custom_ARPSYSTEMCOMPONENT(args, build_dir):
|
||||
try:
|
||||
custom_arp = json.loads(args.custom_arp)
|
||||
g_arpsystemcomponent.update(custom_arp)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Failed to decode custom arp: {e}")
|
||||
return False
|
||||
|
||||
if args.arp:
|
||||
return gen_custom_ARPSYSTEMCOMPONENT_True(args, build_dir)
|
||||
else:
|
||||
return gen_custom_ARPSYSTEMCOMPONENT_False(args)
|
||||
|
||||
|
||||
def gen_content_between_tags(filename, tag_start, tag_end, func):
|
||||
target_file = Path(sys.argv[0]).parent.joinpath(filename)
|
||||
lines, index_start = read_lines_and_start_index(target_file, tag_start, tag_end)
|
||||
@@ -173,26 +387,69 @@ def gen_content_between_tags(filename, tag_start, tag_end, func):
|
||||
return True
|
||||
|
||||
|
||||
def init_global_vars(args):
|
||||
var_file = "../../src/version.rs"
|
||||
if not Path(var_file).exists():
|
||||
print(f"Error: {var_file} not found")
|
||||
return False
|
||||
|
||||
with open(var_file, "r") as f:
|
||||
content = f.readlines()
|
||||
|
||||
global g_version
|
||||
global g_build_date
|
||||
g_version = args.version.replace("-", ".")
|
||||
if g_version == "":
|
||||
# pub const VERSION: &str = "1.2.4";
|
||||
version_pattern = re.compile(r'.*VERSION: &str = "(.*)";.*')
|
||||
for line in content:
|
||||
match = version_pattern.match(line)
|
||||
if match:
|
||||
g_version = match.group(1)
|
||||
break
|
||||
if g_version == "":
|
||||
print(f"Error: version not found in {var_file}")
|
||||
return False
|
||||
|
||||
# pub const BUILD_DATE: &str = "2024-04-08 23:11";
|
||||
build_date_pattern = re.compile(r'BUILD_DATE: &str = "(.*)";')
|
||||
for line in content:
|
||||
match = build_date_pattern.match(line)
|
||||
if match:
|
||||
g_build_date = match.group(1)
|
||||
break
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = make_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
app_name = args.app_name
|
||||
build_dir = (
|
||||
Path(sys.argv[0])
|
||||
.parent.joinpath(
|
||||
f'../../flutter/build/windows/x64/runner/{"Debug" if args.debug else "Release"}'
|
||||
)
|
||||
.resolve()
|
||||
f'../../flutter/build/windows/x64/runner/{"Debug" if args.debug else "Release"}'
|
||||
)
|
||||
if args.github_ci:
|
||||
build_dir = "../../rustdesk"
|
||||
build_dir = Path(sys.argv[0]).parent.joinpath(build_dir).resolve()
|
||||
|
||||
if not init_global_vars(args):
|
||||
sys.exit(-1)
|
||||
|
||||
if not gen_pre_vars(args, build_dir):
|
||||
sys.exit(-1)
|
||||
|
||||
if not gen_upgrade_info(args.version):
|
||||
if not gen_upgrade_info():
|
||||
sys.exit(-1)
|
||||
|
||||
if not gen_custom_ARPSYSTEMCOMPONENT(args, build_dir):
|
||||
sys.exit(-1)
|
||||
|
||||
if not gen_auto_component(app_name, build_dir):
|
||||
sys.exit(-1)
|
||||
|
||||
if not gen_custom_dialog_bitmaps():
|
||||
sys.exit(-1)
|
||||
|
||||
replace_app_name_in_lans(args.app_name)
|
||||
|
||||
Reference in New Issue
Block a user