Parcourir la source

feat(nsis-gen): support nsis7z compression

evshiron il y a 8 ans
Parent
commit
13b0529d80

+ 1 - 1
assets/project/package.json

@@ -13,7 +13,7 @@
     "nwVersion": "lts",
     "targets": [
       "zip",
-      "nsis"
+      "nsis7z"
     ],
     "win": {
       "versionStrings": {

+ 72 - 5
src/lib/Builder.ts

@@ -14,7 +14,7 @@ import { Downloader } from './Downloader';
 import { FFmpegDownloader } from './FFmpegDownloader';
 import { BuildConfig } from './config';
 import { NsisVersionInfo } from './common';
-import { NsisComposer, NsisDiffer, nsisBuild } from './nsis-gen';
+import { NsisComposer, NsisDiffer, Nsis7Zipper, nsisBuild } from './nsis-gen';
 import { mergeOptions, findExecutable, findFFmpeg, findRuntimeRoot, findExcludableDependencies, tmpName, tmpFile, tmpDir, fixWindowsVersion, copyFileAsync, extractGeneric, compress } from './util';
 
 interface IBuilderOptions {
@@ -482,17 +482,17 @@ export class Builder {
 
     protected async buildArchiveTarget(type: string, targetDir: string) {
 
-        const targetZip = join(dirname(targetDir), `${ basename(targetDir) }.${ type }`);
+        const targetArchive = join(dirname(targetDir), `${ basename(targetDir) }.${ type }`);
 
-        await removeAsync(targetZip);
+        await removeAsync(targetArchive);
 
         const files = await globby([ '**/*' ], {
             cwd: targetDir,
         });
 
-        await compress(targetDir, files, type, targetZip);
+        await compress(targetDir, files, type, targetArchive);
 
-        return targetZip;
+        return targetArchive;
 
     }
 
@@ -555,6 +555,67 @@ export class Builder {
 
     }
 
+    protected async buildNsis7zTarget(platform: string, arch: string, targetDir: string, pkg: any, config: BuildConfig) {
+
+        if(platform != 'win') {
+            if(!this.options.mute) {
+                console.info(`Skip building nsis7z target for ${ platform }.`);
+            }
+            return;
+        }
+
+        const sourceArchive = await this.buildArchiveTarget('7z', targetDir);
+
+        const versionInfo = new NsisVersionInfo(resolve(this.dir, config.output, 'versions.nsis.json'));
+
+        const targetNsis = resolve(dirname(targetDir), `${ basename(targetDir) }-Setup.exe`);
+
+        const data = await (new Nsis7Zipper(sourceArchive, {
+
+            // Basic.
+            appName: config.win.versionStrings.ProductName,
+            companyName: config.win.versionStrings.CompanyName,
+            description: config.win.versionStrings.FileDescription,
+            version: fixWindowsVersion(config.win.productVersion),
+            copyright: config.win.versionStrings.LegalCopyright,
+
+            // Compression.
+            compression: 'lzma',
+            solid: true,
+
+            languages: config.nsis.languages,
+
+            // Output.
+            output: targetNsis,
+
+        })).make();
+
+        const script = await tmpName();
+        await writeFileAsync(script, data);
+
+        await nsisBuild(targetDir, script, {
+            mute: this.options.mute,
+        });
+
+        await removeAsync(script);
+
+        await versionInfo.addVersion(pkg.version, '', targetDir);
+        await versionInfo.addInstaller(pkg.version, arch, targetNsis);
+
+        if(config.nsis.diffUpdaters) {
+
+            for(const version of await versionInfo.getVersions()) {
+                if(semver.gt(pkg.version, version)) {
+                    await this.buildNsisDiffUpdater(platform, arch, versionInfo, version, pkg.version, pkg, config);
+                }
+            }
+
+        }
+
+        await versionInfo.save();
+
+    }
+
     protected async buildTask(platform: string, arch: string, pkg: any, config: BuildConfig) {
 
         const downloader = new Downloader({
@@ -608,6 +669,12 @@ export class Builder {
                     console.info(`Building nsis target ends within ${ this.getTimeDiff(started) }ms.`);
                 }
                 break;
+            case 'nsis7z':
+                await this.buildNsis7zTarget(platform, arch, targetDir, pkg, config);
+                if(!this.options.mute) {
+                    console.info(`Building nsis7z target ends within ${ this.getTimeDiff(started) }ms.`);
+                }
+                break;
             default:
                 throw new Error('ERROR_UNKNOWN_TARGET');
             }

+ 23 - 0
src/lib/nsis-gen/Nsis7Zipper.ts

@@ -0,0 +1,23 @@
+
+import { dirname, basename, join, relative, resolve, win32 } from 'path';
+
+import { NsisComposer, INsisComposerOptions } from './NsisComposer';
+
+export class Nsis7Zipper extends NsisComposer {
+
+    constructor(protected path: string, options: INsisComposerOptions) {
+        super(options);
+
+    }
+
+    protected async makeInstallerFiles(): Promise<string> {
+        return `SetOutPath "$INSTDIR"
+SetCompress off
+DetailPrint "Extracting archive..."
+File "${ win32.normalize(resolve(this.path)) }"
+DetailPrint "Installing archive..."
+Nsis7z::ExtractWithDetails "$OUTDIR\\${ basename(this.path) }" "Installing %s..."
+Delete "$OUTDIR\\${ basename(this.path) }"`;
+    }
+
+}

+ 40 - 17
src/lib/nsis-gen/NsisComposer.ts

@@ -70,7 +70,23 @@ ${ NsisComposer.DIVIDER }
 #
 ${ NsisComposer.DIVIDER }
 
-${ NsisComposer.DIVIDER }
+${ await this.makeGeneralSection() }
+
+${ await this.makeModernUISection() }
+
+${ await this.makeVersionSection() }
+
+${ await this.makeHookSection() }
+
+${ await this.makeInstallSection() }
+
+${ await this.makeUninstallSection() }
+`;
+
+    }
+
+    protected async makeGeneralSection(): Promise<string> {
+        return `${ NsisComposer.DIVIDER }
 #
 # General
 #
@@ -86,9 +102,11 @@ InstallDir "$LOCALAPPDATA\\${ this.options.appName }"
 InstallDirRegKey HKCU "Software\\${ this.options.appName }" "InstallDir"
 
 RequestExecutionLevel user
-XPStyle on
+XPStyle on`;
+    }
 
-${ NsisComposer.DIVIDER }
+    protected async makeModernUISection(): Promise<string> {
+        return `${ NsisComposer.DIVIDER }
 #
 # Modern UI
 #
@@ -125,11 +143,13 @@ ${
     this.options.languages.length > 1
     ? `!insertmacro MUI_RESERVEFILE_LANGDLL`
     : ''
-}
+}`;
+    }
 
-${ NsisComposer.DIVIDER }
+    protected async makeVersionSection(): Promise<string> {
+        return `${ NsisComposer.DIVIDER }
 #
-# Resources
+# Versions
 #
 ${ NsisComposer.DIVIDER }
 
@@ -138,9 +158,11 @@ VIAddVersionKey "ProductName" "${ this.options.appName }"
 VIAddVersionKey "CompanyName" "${ this.options.companyName }"
 VIAddVersionKey "FileDescription" "${ this.options.description }"
 VIAddVersionKey "FileVersion" "${ this.fixedVersion }"
-VIAddVersionKey "LegalCopyright" "${ this.options.copyright }"
+VIAddVersionKey "LegalCopyright" "${ this.options.copyright }"`;
+    }
 
-${ NsisComposer.DIVIDER }
+    protected async makeHookSection(): Promise<string> {
+        return `${ NsisComposer.DIVIDER }
 #
 # Hooks
 #
@@ -154,9 +176,11 @@ Function .onInit
         : ''
     }
 
-FunctionEnd
+FunctionEnd`;
+    }
 
-${ NsisComposer.DIVIDER }
+    protected async makeInstallSection(): Promise<string> {
+        return `${ NsisComposer.DIVIDER }
 #
 # Install
 #
@@ -181,9 +205,11 @@ ${ await this.makeInstallerFiles() }
 
   WriteUninstaller "$INSTDIR\\Uninstall.exe"
 
-SectionEnd
+SectionEnd`;
+    }
 
-${ NsisComposer.DIVIDER }
+    protected async makeUninstallSection(): Promise<string> {
+        return `${ NsisComposer.DIVIDER }
 #
 # Uninstall
 #
@@ -191,6 +217,7 @@ ${ NsisComposer.DIVIDER }
 
 Section Uninstall
 
+# FIXME: Remove only files installed.
 RMDir /r "$INSTDIR"
 
 !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
@@ -201,16 +228,12 @@ RMDir "$SMPROGRAMS\\$StartMenuFolder"
 
 DeleteRegKey HKCU "Software\\${ this.options.appName }"
 
-SectionEnd
-`;
-
+SectionEnd`;
     }
 
     protected async makeInstallerFiles(): Promise<string> {
-
         return `SetOutPath "$INSTDIR"
 FILE /r .\\*.*`;
-
     }
 
 }

+ 1 - 0
src/lib/nsis-gen/index.ts

@@ -4,6 +4,7 @@ import { spawn } from 'child_process';
 
 export * from './NsisComposer';
 export * from './NsisDiffer';
+export * from './Nsis7Zipper';
 
 const DIR_ASSETS = resolve(dirname(module.filename), '../../../assets/');
 const DIR_NSIS = resolve(DIR_ASSETS, 'nsis');