Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/darwin/create-dmg.ts
5229 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import fs from 'fs';
7
import path from 'path';
8
import { spawn } from '@malept/cross-spawn-promise';
9
10
const root = path.dirname(path.dirname(import.meta.dirname));
11
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
12
13
interface DmgBuildSettings {
14
title: string;
15
icon?: string | null;
16
'badge-icon'?: string | null;
17
background?: string;
18
'background-color'?: string;
19
'icon-size'?: number;
20
'text-size'?: number;
21
format?: string;
22
window?: {
23
position?: { x: number; y: number };
24
size?: { width: number; height: number };
25
};
26
contents: Array<{
27
path: string;
28
x: number;
29
y: number;
30
type: 'file' | 'link';
31
name?: string;
32
}>;
33
}
34
35
function getDmgBuilderPath(): string {
36
return path.join(import.meta.dirname, '..', 'node_modules', 'dmg-builder');
37
}
38
39
function getDmgBuilderVendorPath(): string {
40
return path.join(getDmgBuilderPath(), 'vendor');
41
}
42
43
async function runDmgBuild(settingsFile: string, volumeName: string, artifactPath: string): Promise<void> {
44
const vendorDir = getDmgBuilderVendorPath();
45
const scriptPath = path.join(vendorDir, 'run_dmgbuild.py');
46
await spawn('python3', [scriptPath, '-s', settingsFile, volumeName, artifactPath], {
47
cwd: vendorDir,
48
stdio: 'inherit'
49
});
50
}
51
52
async function main(buildDir?: string, outDir?: string): Promise<void> {
53
const arch = process.env['VSCODE_ARCH'];
54
const quality = process.env['VSCODE_QUALITY'];
55
56
if (!buildDir) {
57
throw new Error('Build directory argument is required');
58
}
59
60
if (!arch) {
61
throw new Error('$VSCODE_ARCH not set');
62
}
63
64
if (!outDir) {
65
throw new Error('Output directory argument is required');
66
}
67
68
const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`);
69
const appName = product.nameLong + '.app';
70
const appPath = path.join(appRoot, appName);
71
const dmgName = `VSCode-darwin-${arch}`;
72
const artifactPath = path.join(outDir, `${dmgName}.dmg`);
73
const backgroundPath = path.join(import.meta.dirname, `dmg-background-${quality}.tiff`);
74
const diskIconPath = path.join(root, 'resources', 'darwin', 'code.icns');
75
let title = 'Code OSS';
76
switch (quality) {
77
case 'stable':
78
title = 'VS Code';
79
break;
80
case 'insider':
81
title = 'VS Code Insiders';
82
break;
83
case 'exploration':
84
title = 'VS Code Exploration';
85
break;
86
}
87
88
if (!fs.existsSync(appPath)) {
89
throw new Error(`App path does not exist: ${appPath}`);
90
}
91
92
console.log(`Creating DMG for ${product.nameLong}...`);
93
console.log(` App path: ${appPath}`);
94
console.log(` Output directory: ${outDir}`);
95
console.log(` DMG name: ${dmgName}`);
96
97
if (fs.existsSync(artifactPath)) {
98
fs.unlinkSync(artifactPath);
99
}
100
101
const settings: DmgBuildSettings = {
102
title,
103
'badge-icon': diskIconPath,
104
background: backgroundPath,
105
format: 'ULMO',
106
'text-size': 12,
107
window: {
108
position: { x: 100, y: 400 },
109
size: { width: 480, height: 352 }
110
},
111
contents: [
112
{
113
path: appPath,
114
x: 120,
115
y: 160,
116
type: 'file'
117
},
118
{
119
path: '/Applications',
120
x: 360,
121
y: 160,
122
type: 'link'
123
}
124
]
125
};
126
127
const settingsFile = path.join(outDir, '.dmg-settings.json');
128
fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
129
130
try {
131
await runDmgBuild(settingsFile, dmgName, artifactPath);
132
} finally {
133
if (fs.existsSync(settingsFile)) {
134
fs.unlinkSync(settingsFile);
135
}
136
}
137
138
if (!fs.existsSync(artifactPath)) {
139
throw new Error(`DMG was not created at expected path: ${artifactPath}`);
140
}
141
142
const stats = fs.statSync(artifactPath);
143
console.log(`Successfully created DMG: ${artifactPath} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
144
}
145
146
if (import.meta.main) {
147
main(process.argv[2], process.argv[3]).catch(err => {
148
console.error('Failed to create DMG:', err);
149
process.exit(1);
150
});
151
}
152
153