From bebd8e860e48cb7beb1bcbd79bc24ff408a129a0 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Mon, 16 Sep 2019 16:20:52 +0200 Subject: [PATCH] Add packager on Windows --- packager.py | 110 ++++++++++++++++++ packager/win/icon.ico | Bin 0 -> 28522 bytes packager/win/modpath.iss | 219 +++++++++++++++++++++++++++++++++++ packager/win/setupscript.iss | 61 ++++++++++ 4 files changed, 390 insertions(+) create mode 100644 packager.py create mode 100644 packager/win/icon.ico create mode 100644 packager/win/modpath.iss create mode 100644 packager/win/setupscript.iss diff --git a/packager.py b/packager.py new file mode 100644 index 0000000..2fa06ab --- /dev/null +++ b/packager.py @@ -0,0 +1,110 @@ +import subprocess +import sys +import os +import platform +from dataclasses import dataclass + +import click +import glob +import shutil +import toml + +PACKAGER_TARGET_DIR = "target/packager" + +@dataclass +class PackageInfo: + name: str + version: str + description: str + publisher: str + url: str + +@click.group() +def cli(): + pass + +@cli.command() +@click.option('--skipcargo', default=False, is_flag=True, help="Skip cargo release build") +def build(skipcargo): + """Build espanso distribution""" + # Check operating system + TARGET_OS = "macosx" + if platform.system() == "Windows": + TARGET_OS = "windows" + elif platform.system() == "Linux": + TARGET_OS = "linux" + + print("Detected OS:", TARGET_OS) + + print("Loading info from Cargo.toml") + cargo_info = toml.load("Cargo.toml") + package_info = PackageInfo(cargo_info["package"]["name"], + cargo_info["package"]["version"], + cargo_info["package"]["description"], + cargo_info["package"]["authors"][0], + cargo_info["package"]["homepage"]) + print(package_info) + + if not skipcargo: + print("Building release version...") + subprocess.run(["cargo", "build", "--release"]) + else: + print("Skipping build") + + if TARGET_OS == "windows": + build_windows(package_info) + + +def build_windows(package_info): + print("Starting packaging process on windows...") + + # Check javapackager + try: + subprocess.run(["iscc"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except FileNotFoundError: + raise Exception("Could not find Inno Setup compiler. Please install it from here: http://www.jrsoftware.org/isdl.php") + + print("Clearing target dirs") + + # Clearing previous build directory + if os.path.isdir(PACKAGER_TARGET_DIR): + print("Cleaning packager temp directory...") + shutil.rmtree(PACKAGER_TARGET_DIR) + + TARGET_DIR = os.path.join(PACKAGER_TARGET_DIR, "win") + os.makedirs(TARGET_DIR, exist_ok=True) + + INSTALLER_NAME = "espanso-setup" + + # Inno setup + shutil.copy("packager/win/modpath.iss", os.path.join(TARGET_DIR, "modpath.iss")) + + print("Processing inno setup template") + with open("packager/win/setupscript.iss", "r") as iss_script: + content = iss_script.read() + + # Replace variables + content = content.replace("{{{app_name}}}", package_info.name) + content = content.replace("{{{app_version}}}", package_info.version) + content = content.replace("{{{app_publisher}}}", package_info.publisher) + content = content.replace("{{{app_url}}}", package_info.url) + content = content.replace("{{{app_license}}}", os.path.abspath("LICENSE")) + content = content.replace("{{{app_icon}}}", os.path.abspath("packager/win/icon.ico")) + content = content.replace("{{{executable_path}}}", os.path.abspath("target/release/espanso.exe")) + content = content.replace("{{{output_dir}}}", os.path.abspath(TARGET_DIR)) + content = content.replace("{{{output_name}}}", INSTALLER_NAME) + + with open(os.path.join(TARGET_DIR, "setupscript.iss"), "w") as output_script: + output_script.write(content) + + print("Compiling installer with Inno setup") + subprocess.run(["iscc", os.path.abspath(os.path.join(TARGET_DIR, "setupscript.iss"))]) + +if __name__ == '__main__': + print("[[ espanso packager ]]") + + # Check python version 3 + if sys.version_info[0] < 3: + raise Exception("Must be using Python 3") + + cli() \ No newline at end of file diff --git a/packager/win/icon.ico b/packager/win/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1d1c06c7ef5bf408ce91222819c303d8c22201a0 GIT binary patch literal 28522 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 +// Homepage: http://www.legroom.net/software +// License: GNU Lesser General Public License (LGPL), version 3 +// http://www.gnu.org/licenses/lgpl.html +// +// Script Function: +// Allow modification of environmental path directly from Inno Setup installers +// +// Instructions: +// Copy modpath.iss to the same directory as your setup script +// +// Add this statement to your [Setup] section +// ChangesEnvironment=true +// +// Add this statement to your [Tasks] section +// You can change the Description or Flags +// You can change the Name, but it must match the ModPathName setting below +// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked +// +// Add the following to the end of your [Code] section +// ModPathName defines the name of the task defined above +// ModPathType defines whether the 'user' or 'system' path will be modified; +// this will default to user if anything other than system is set +// setArrayLength must specify the total number of dirs to be added +// Result[0] contains first directory, Result[1] contains second, etc. +// const +// ModPathName = 'modifypath'; +// ModPathType = 'user'; +// +// function ModPathDir(): TArrayOfString; +// begin +// setArrayLength(Result, 1); +// Result[0] := ExpandConstant('{app}'); +// end; +// #include "modpath.iss" +// ---------------------------------------------------------------------------- + +procedure ModPath(); +var + oldpath: String; + newpath: String; + updatepath: Boolean; + pathArr: TArrayOfString; + aExecFile: String; + aExecArr: TArrayOfString; + i, d: Integer; + pathdir: TArrayOfString; + regroot: Integer; + regpath: String; + +begin + // Get constants from main script and adjust behavior accordingly + // ModPathType MUST be 'system' or 'user'; force 'user' if invalid + if ModPathType = 'system' then begin + regroot := HKEY_LOCAL_MACHINE; + regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; + end else begin + regroot := HKEY_CURRENT_USER; + regpath := 'Environment'; + end; + + // Get array of new directories and act on each individually + pathdir := ModPathDir(); + for d := 0 to GetArrayLength(pathdir)-1 do begin + updatepath := true; + + // Modify WinNT path + if UsingWinNT() = true then begin + + // Get current path, split into an array + RegQueryStringValue(regroot, regpath, 'Path', oldpath); + oldpath := oldpath + ';'; + i := 0; + + while (Pos(';', oldpath) > 0) do begin + SetArrayLength(pathArr, i+1); + pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1); + oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath)); + i := i + 1; + + // Check if current directory matches app dir + if pathdir[d] = pathArr[i-1] then begin + // if uninstalling, remove dir from path + if IsUninstaller() = true then begin + continue; + // if installing, flag that dir already exists in path + end else begin + updatepath := false; + end; + end; + + // Add current directory to new path + if i = 1 then begin + newpath := pathArr[i-1]; + end else begin + newpath := newpath + ';' + pathArr[i-1]; + end; + end; + + // Append app dir to path if not already included + if (IsUninstaller() = false) AND (updatepath = true) then + newpath := newpath + ';' + pathdir[d]; + + // Write new path + RegWriteStringValue(regroot, regpath, 'Path', newpath); + + // Modify Win9x path + end else begin + + // Convert to shortened dirname + pathdir[d] := GetShortName(pathdir[d]); + + // If autoexec.bat exists, check if app dir already exists in path + aExecFile := 'C:\AUTOEXEC.BAT'; + if FileExists(aExecFile) then begin + LoadStringsFromFile(aExecFile, aExecArr); + for i := 0 to GetArrayLength(aExecArr)-1 do begin + if IsUninstaller() = false then begin + // If app dir already exists while installing, skip add + if (Pos(pathdir[d], aExecArr[i]) > 0) then + updatepath := false; + break; + end else begin + // If app dir exists and = what we originally set, then delete at uninstall + if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then + aExecArr[i] := ''; + end; + end; + end; + + // If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path + if (IsUninstaller() = false) AND (updatepath = true) then begin + SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True); + + // If uninstalling, write the full autoexec out + end else begin + SaveStringsToFile(aExecFile, aExecArr, False); + end; + end; + end; +end; + +// Split a string into an array using passed delimeter +procedure MPExplode(var Dest: TArrayOfString; Text: String; Separator: String); +var + i: Integer; +begin + i := 0; + repeat + SetArrayLength(Dest, i+1); + if Pos(Separator,Text) > 0 then begin + Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1); + Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text)); + i := i + 1; + end else begin + Dest[i] := Text; + Text := ''; + end; + until Length(Text)=0; +end; + + +procedure CurStepChanged(CurStep: TSetupStep); +var + taskname: String; +begin + taskname := ModPathName; + if CurStep = ssPostInstall then + if IsTaskSelected(taskname) then + ModPath(); +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +var + aSelectedTasks: TArrayOfString; + i: Integer; + taskname: String; + regpath: String; + regstring: String; + appid: String; +begin + // only run during actual uninstall + if CurUninstallStep = usUninstall then begin + // get list of selected tasks saved in registry at install time + appid := '{#emit SetupSetting("AppId")}'; + if appid = '' then appid := '{#emit SetupSetting("AppName")}'; + regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1'); + RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring); + if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring); + + // check each task; if matches modpath taskname, trigger patch removal + if regstring <> '' then begin + taskname := ModPathName; + MPExplode(aSelectedTasks, regstring, ','); + if GetArrayLength(aSelectedTasks) > 0 then begin + for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin + if comparetext(aSelectedTasks[i], taskname) = 0 then + ModPath(); + end; + end; + end; + end; +end; + +function NeedRestart(): Boolean; +var + taskname: String; +begin + taskname := ModPathName; + if IsTaskSelected(taskname) and not UsingWinNT() then begin + Result := True; + end else begin + Result := False; + end; +end; diff --git a/packager/win/setupscript.iss b/packager/win/setupscript.iss new file mode 100644 index 0000000..42b5909 --- /dev/null +++ b/packager/win/setupscript.iss @@ -0,0 +1,61 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "{{{app_name}}}" +#define MyAppVersion "{{{app_version}}}" +#define MyAppPublisher "{{{app_publisher}}}" +#define MyAppURL "{{{app_url}}}" +#define MyAppExeName "espanso.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{0E3D83CE-A644-4E0E-8487-657C7ECF6BF9} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={autopf}\{#MyAppName} +DisableProgramGroupPage=yes +LicenseFile="{{{app_license}}}" +; Remove the following line to run in administrative install mode (install for all users.) +PrivilegesRequired=lowest +OutputDir="{{{output_dir}}}" +OutputBaseFilename={{{output_name}}} +SetupIconFile="{{{app_icon}}}" +Compression=lzma +SolidCompression=yes +WizardStyle=modern +ChangesEnvironment=yes + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Files] +Source: "{{{executable_path}}}"; DestDir: "{app}"; Flags: ignoreversion +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Icons] +Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" + +[Tasks] +Name: modifypath; Description: Add espanso to PATH ( recommended ); + +[Code] +const + ModPathName = 'modifypath'; + ModPathType = 'user'; + +function ModPathDir(): TArrayOfString; +begin + setArrayLength(Result, 1) + Result[0] := ExpandConstant('{app}'); +end; +#include "modpath.iss" + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent +