Path: blob/main/package/src/windows/installer.ts
12925 views
import { info } from "../../../src/deno_ral/log.ts";1import { basename, dirname, join } from "../../../src/deno_ral/path.ts";23import { Configuration } from "../common/config.ts";4import { runCmd } from "../util/cmd.ts";5import { download, unzip } from "../util/utils.ts";6import { execProcess } from "../../../src/core/process.ts";7import { emptyDirSync, ensureDirSync, existsSync, moveSync, copySync } from "../../../src/deno_ral/fs.ts";89export async function makeInstallerWindows(configuration: Configuration) {10const packageName = `quarto-${configuration.version}-win.msi`;1112// Wix information13const wixFullVersion = "3112";14const wixShortVersion = "311";1516// Working dir17const workingDir = join(configuration.directoryInfo.out, "working_win");18const wixDir = join(workingDir, "tools", `wix-${wixShortVersion}`);1920// Wix commands21const heatCmd = join(wixDir, "heat");22const candleCmd = join(wixDir, "candle");23const lightCmd = join(wixDir, "light");2425// Download tools, if necessary26if (27!existsSync(workingDir) || !existsSync(wixDir) ||28!existsSync(heatCmd + ".exe")29) {30emptyDirSync(workingDir);31ensureDirSync(wixDir);3233const fileName = `wix${wixShortVersion}-binaries.zip`;34const wixToolsUrl =35`https://github.com/wixtoolset/wix3/releases/download/wix${wixFullVersion}rtm/${fileName}`;3637const destZip = join(workingDir, fileName);3839// Download the wix tools40info(`Downloading ${wixToolsUrl}`);41info(`to ${destZip}`);42await download(wixToolsUrl, destZip);4344// Uncompress the wix tools in the supporting directory45info("Unzipping wix tools...");46await unzip(destZip, wixDir);4748// Delete the downloaded zip file49Deno.remove(destZip);50}5152// Copy the 'dist' files into a temporary working directory53const tempDir = Deno.makeTempDirSync();54const workingDistPath = join(tempDir, "dist");55const workingBinPath = join(workingDistPath, "bin");56const workingToolsPath = join(workingBinPath, "tools", );57const archToolsPath = join(workingToolsPath, "x86_64");58copySync(configuration.directoryInfo.pkgWorking.root, workingDistPath);5960// Create a zip file61info("Creating zip installer");62const zipInput = join(workingDistPath, "*");63const zipOutput = join(64configuration.directoryInfo.out,65`quarto-${configuration.version}-win.zip`,66);67await zip(zipInput, zipOutput);6869// Set the installer version70Deno.env.set("QUARTO_INSTALLER_VERSION", configuration.version);7172// heat the directory to generate a wix file for it73info("Heating directory");74const heatOutput = join(workingDir, "quarto-frag.wxs");75await runCmd(76heatCmd,77[78"dir",79workingDistPath,80"-var",81"var.SourceDir",82"-gg",83"-sfrag",84"-srd",85"-cg",86"ProductComponents",87"-dr",88"APPLICATIONFOLDER",89"-out",90heatOutput,91],92);9394// use candle to build the wixobj file95info("Making the candle");96const candleFiles = [97join(98configuration.directoryInfo.pkg,99"src",100"windows",101"WixUI_Advanced_Custom.wxs",102),103join(configuration.directoryInfo.pkg, "src", "windows", "quarto.wxs"),104heatOutput,105];106const candleOutput: string[] = [];107await Promise.all(candleFiles.map(async (candleInput) => {108const outputFileName = basename(candleInput, ".wxs");109const outputPath = join(workingDir, outputFileName + ".wixobj");110candleOutput.push(outputPath);111return await runCmd(112candleCmd,113[114`-dSourceDir=${workingDistPath}`,115"-arch",116"x64",117"-out",118outputPath,119candleInput,120],121);122}));123124info("Lighting the candle");125const licenseRtf = join(126configuration.directoryInfo.pkg,127"src",128"windows",129"license.rtf",130);131132const lightOutput = join(workingDir, packageName);133const lightArgs = ["-out", lightOutput, ...candleOutput];134lightArgs.push("-ext");135lightArgs.push("WixUtilExtension");136lightArgs.push("-ext");137lightArgs.push("WixUIExtension");138lightArgs.push(`-dWixUILicenseRtf=${licenseRtf}`);139await runCmd(lightCmd, lightArgs);140141Deno.env.delete("QUARTO_INSTALLER_VERSION");142143info(144`Moving ${lightOutput} to ${configuration.directoryInfo.out}`,145);146moveSync(147lightOutput,148join(configuration.directoryInfo.out, basename(lightOutput)),149{ overwrite: true },150);151152// Clean up the working directory153Deno.remove(workingDir, { recursive: true });154Deno.remove(workingDistPath, { recursive: true });155}156157export function zip(input: string, output: string) {158const dir = dirname(input);159const cmd = "powershell";160const args = [161"Compress-Archive",162"-Force",163input,164"-DestinationPath",165output,166];167info(cmd);168return execProcess(169{170cmd,171args,172cwd: dir,173stdout: "piped",174},175);176}177178179