Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/package/src/windows/installer.ts
6450 views
1
import { info } from "../../../src/deno_ral/log.ts";
2
import { basename, dirname, join } from "../../../src/deno_ral/path.ts";
3
4
import { Configuration } from "../common/config.ts";
5
import { runCmd } from "../util/cmd.ts";
6
import { download, unzip } from "../util/utils.ts";
7
import { execProcess } from "../../../src/core/process.ts";
8
import { emptyDirSync, ensureDirSync, existsSync, moveSync, copySync } from "../../../src/deno_ral/fs.ts";
9
10
export async function makeInstallerWindows(configuration: Configuration) {
11
const packageName = `quarto-${configuration.version}-win.msi`;
12
13
// Wix information
14
const wixFullVersion = "3112";
15
const wixShortVersion = "311";
16
17
// Working dir
18
const workingDir = join(configuration.directoryInfo.out, "working_win");
19
const wixDir = join(workingDir, "tools", `wix-${wixShortVersion}`);
20
21
// Wix commands
22
const heatCmd = join(wixDir, "heat");
23
const candleCmd = join(wixDir, "candle");
24
const lightCmd = join(wixDir, "light");
25
26
// Download tools, if necessary
27
if (
28
!existsSync(workingDir) || !existsSync(wixDir) ||
29
!existsSync(heatCmd + ".exe")
30
) {
31
emptyDirSync(workingDir);
32
ensureDirSync(wixDir);
33
34
const fileName = `wix${wixShortVersion}-binaries.zip`;
35
const wixToolsUrl =
36
`https://github.com/wixtoolset/wix3/releases/download/wix${wixFullVersion}rtm/${fileName}`;
37
38
const destZip = join(workingDir, fileName);
39
40
// Download the wix tools
41
info(`Downloading ${wixToolsUrl}`);
42
info(`to ${destZip}`);
43
await download(wixToolsUrl, destZip);
44
45
// Uncompress the wix tools in the supporting directory
46
info("Unzipping wix tools...");
47
await unzip(destZip, wixDir);
48
49
// Delete the downloaded zip file
50
Deno.remove(destZip);
51
}
52
53
// Copy the 'dist' files into a temporary working directory
54
const tempDir = Deno.makeTempDirSync();
55
const workingDistPath = join(tempDir, "dist");
56
const workingBinPath = join(workingDistPath, "bin");
57
const workingToolsPath = join(workingBinPath, "tools", );
58
const archToolsPath = join(workingToolsPath, "x86_64");
59
copySync(configuration.directoryInfo.pkgWorking.root, workingDistPath);
60
61
// Create a zip file
62
info("Creating zip installer");
63
const zipInput = join(workingDistPath, "*");
64
const zipOutput = join(
65
configuration.directoryInfo.out,
66
`quarto-${configuration.version}-win.zip`,
67
);
68
await zip(zipInput, zipOutput);
69
70
// Set the installer version
71
Deno.env.set("QUARTO_INSTALLER_VERSION", configuration.version);
72
73
// heat the directory to generate a wix file for it
74
info("Heating directory");
75
const heatOutput = join(workingDir, "quarto-frag.wxs");
76
await runCmd(
77
heatCmd,
78
[
79
"dir",
80
workingDistPath,
81
"-var",
82
"var.SourceDir",
83
"-gg",
84
"-sfrag",
85
"-srd",
86
"-cg",
87
"ProductComponents",
88
"-dr",
89
"APPLICATIONFOLDER",
90
"-out",
91
heatOutput,
92
],
93
);
94
95
// use candle to build the wixobj file
96
info("Making the candle");
97
const candleFiles = [
98
join(
99
configuration.directoryInfo.pkg,
100
"src",
101
"windows",
102
"WixUI_Advanced_Custom.wxs",
103
),
104
join(configuration.directoryInfo.pkg, "src", "windows", "quarto.wxs"),
105
heatOutput,
106
];
107
const candleOutput: string[] = [];
108
await Promise.all(candleFiles.map(async (candleInput) => {
109
const outputFileName = basename(candleInput, ".wxs");
110
const outputPath = join(workingDir, outputFileName + ".wixobj");
111
candleOutput.push(outputPath);
112
return await runCmd(
113
candleCmd,
114
[
115
`-dSourceDir=${workingDistPath}`,
116
"-arch",
117
"x64",
118
"-out",
119
outputPath,
120
candleInput,
121
],
122
);
123
}));
124
125
info("Lighting the candle");
126
const licenseRtf = join(
127
configuration.directoryInfo.pkg,
128
"src",
129
"windows",
130
"license.rtf",
131
);
132
133
const lightOutput = join(workingDir, packageName);
134
const lightArgs = ["-out", lightOutput, ...candleOutput];
135
lightArgs.push("-ext");
136
lightArgs.push("WixUtilExtension");
137
lightArgs.push("-ext");
138
lightArgs.push("WixUIExtension");
139
lightArgs.push(`-dWixUILicenseRtf=${licenseRtf}`);
140
await runCmd(lightCmd, lightArgs);
141
142
Deno.env.delete("QUARTO_INSTALLER_VERSION");
143
144
info(
145
`Moving ${lightOutput} to ${configuration.directoryInfo.out}`,
146
);
147
moveSync(
148
lightOutput,
149
join(configuration.directoryInfo.out, basename(lightOutput)),
150
{ overwrite: true },
151
);
152
153
// Clean up the working directory
154
Deno.remove(workingDir, { recursive: true });
155
Deno.remove(workingDistPath, { recursive: true });
156
}
157
158
export function zip(input: string, output: string) {
159
const dir = dirname(input);
160
const cmd = "powershell";
161
const args = [
162
"Compress-Archive",
163
"-Force",
164
input,
165
"-DestinationPath",
166
output,
167
];
168
info(cmd);
169
return execProcess(
170
{
171
cmd,
172
args,
173
cwd: dir,
174
stdout: "piped",
175
},
176
);
177
}
178
179