Skip to content

Commit 2a27a14

Browse files
author
Alberto Iannaccone
authored
put Linux build files inside a folder before zipping (#870)
* add preference to set a custom update url * put linux build inside a folder before zipping
1 parent f2d492b commit 2a27a14

9 files changed

+187
-2
lines changed

electron/packager/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,11 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
392392
for (const fileToCopy of filesToCopy) {
393393
echo(`🚢 >>> Copying ${fileToCopy} to ${targetFolder}.`);
394394
const isZip = await utils.isZip(fileToCopy);
395-
cp('-rf', fileToCopy, targetFolder);
395+
if (isZip && platform === 'linux') {
396+
await utils.adjustArchiveStructure(fileToCopy, targetFolder);
397+
} else {
398+
cp('-rf', fileToCopy, targetFolder);
399+
}
396400
echo(`👌 >>> Copied ${fileToCopy} to ${targetFolder}.`);
397401
}
398402
}

electron/packager/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"scripts": {
88
"prepare": "yarn test",
99
"package": "node index.js",
10-
"test": "echo 'No test implemented'"
10+
"test": "mocha \"./test/**/*.test.js\""
1111
},
1212
"keywords": [],
1313
"author": "Arduino SA",
7.99 MB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

electron/packager/test/utils.test.js

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const expect = require('chai').expect;
4+
const track = require('temp').track();
5+
const unpack = require('../utils').unpack;
6+
const testMe = require('../utils');
7+
const sinon = require('sinon');
8+
9+
describe('utils', () => {
10+
11+
describe('adjustArchiveStructure', () => {
12+
13+
let consoleStub;
14+
15+
beforeEach(() => {
16+
consoleStub = sinon.stub(console, 'log').value(() => { });
17+
});
18+
19+
afterEach(() => {
20+
consoleStub.reset();
21+
track.cleanupSync();
22+
});
23+
24+
it('should reject when not a zip file', async () => {
25+
try {
26+
const invalid = path.join(__dirname, 'resources', 'not-a-zip.dmg');
27+
await testMe.adjustArchiveStructure(invalid, track.mkdirSync());
28+
throw new Error('Expected a rejection');
29+
} catch (e) {
30+
expect(e).to.be.an.instanceOf(Error);
31+
expect(e.message).to.be.equal('Expected a ZIP file.');
32+
}
33+
});
34+
35+
it('should reject when target directory does not exist', async () => {
36+
try {
37+
const zip = path.join(__dirname, 'resources', 'zip-with-base-folder.zip');
38+
await testMe.adjustArchiveStructure(zip, path.join(__dirname, 'some', 'missing', 'path'));
39+
throw new Error('Expected a rejection');
40+
} catch (e) {
41+
expect(e).to.be.an.instanceOf(Error);
42+
expect(e.message.endsWith('does not exist.')).to.be.true;
43+
}
44+
});
45+
46+
it('should reject when target is a file', async () => {
47+
try {
48+
const zip = path.join(__dirname, 'resources', 'zip-with-base-folder.zip');
49+
await testMe.adjustArchiveStructure(zip, path.join(__filename));
50+
throw new Error('Expected a rejection');
51+
} catch (e) {
52+
expect(e).to.be.an.instanceOf(Error);
53+
expect(e.message.endsWith('is not a directory.')).to.be.true;
54+
}
55+
});
56+
57+
it('should be a NOOP when the zip already has the desired base folder', async () => {
58+
const zip = path.join(__dirname, 'resources', 'zip-with-base-folder.zip');
59+
const actual = await testMe.adjustArchiveStructure(zip, track.mkdirSync());
60+
expect(actual).to.be.equal(zip);
61+
});
62+
63+
it('should handle whitespace in file path gracefully', async () => {
64+
const zip = path.join(__dirname, 'resources', 'zip with whitespace.zip');
65+
const out = track.mkdirSync();
66+
const actual = await testMe.adjustArchiveStructure(zip, out, true);
67+
expect(actual).to.be.equal(path.join(out, 'zip with whitespace.zip'));
68+
console.log(actual);
69+
expect(fs.existsSync(actual)).to.be.true;
70+
71+
const verifyOut = track.mkdirSync();
72+
await unpack(actual, verifyOut);
73+
74+
const root = path.join(verifyOut, 'zip with whitespace');
75+
expect(fs.existsSync(root)).to.be.true;
76+
expect(fs.lstatSync(root).isDirectory()).to.be.true;
77+
const subs = fs.readdirSync(root);
78+
expect(subs).to.have.lengthOf(3);
79+
expect(subs.sort()).to.be.deep.equal(['a.txt', 'b.txt', 'foo']);
80+
});
81+
82+
it('should keep the symlinks after ZIP adjustments', async function () {
83+
if (process.platform === 'win32') {
84+
this.skip();
85+
}
86+
const zip = path.join(__dirname, 'resources', 'zip-with-symlink.zip');
87+
const out = track.mkdirSync();
88+
const actual = await testMe.adjustArchiveStructure(zip, out, true);
89+
expect(actual).to.be.equal(path.join(out, 'zip-with-symlink.zip'));
90+
console.log(actual);
91+
expect(fs.existsSync(actual)).to.be.true;
92+
93+
const verifyOut = track.mkdirSync();
94+
await unpack(actual, verifyOut);
95+
expect(fs.lstatSync(path.join(verifyOut, 'zip-with-symlink', 'folder', 'symlinked-sub')).isSymbolicLink()).to.be.true;
96+
});
97+
98+
it('should adjust the archive structure if base folder is not present', async () => {
99+
const zip = path.join(__dirname, 'resources', 'zip-without-symlink.zip');
100+
const out = track.mkdirSync();
101+
const actual = await testMe.adjustArchiveStructure(zip, out, true);
102+
expect(actual).to.be.equal(path.join(out, 'zip-without-symlink.zip'));
103+
console.log(actual);
104+
expect(fs.existsSync(actual)).to.be.true;
105+
106+
const verifyOut = track.mkdirSync();
107+
await unpack(actual, verifyOut);
108+
109+
const root = path.join(verifyOut, 'zip-without-symlink');
110+
expect(fs.existsSync(root)).to.be.true;
111+
expect(fs.lstatSync(root).isDirectory()).to.be.true;
112+
const subs = fs.readdirSync(root);
113+
expect(subs).to.have.lengthOf(3);
114+
expect(subs.sort()).to.be.deep.equal(['a.txt', 'b.txt', 'foo']);
115+
});
116+
117+
});
118+
119+
});

electron/packager/utils.js

+62
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,67 @@ function collectUnusedDependencies(pathToProject = process.cwd()) {
5050
});
5151
}
5252

53+
/**
54+
* `pathToZip` is a `path/to/your/app-name.zip`.
55+
* If the `pathToZip` archive does not have a root directory with name `app-name`, it creates one, and move the content from the
56+
* archive's root to the new root folder. If the archive already has the desired root folder, calling this function is a NOOP.
57+
* If `pathToZip` is not a ZIP, rejects. `targetFolderName` is the destination folder not the new archive location.
58+
*/
59+
function adjustArchiveStructure(pathToZip, targetFolderName, noCleanup) {
60+
return new Promise(async (resolve, reject) => {
61+
if (!(await isZip(pathToZip))) {
62+
reject(new Error(`Expected a ZIP file.`));
63+
return;
64+
}
65+
if (!fs.existsSync(targetFolderName)) {
66+
reject(new Error(`${targetFolderName} does not exist.`));
67+
return;
68+
}
69+
if (!fs.lstatSync(targetFolderName).isDirectory()) {
70+
reject(new Error(`${targetFolderName} is not a directory.`));
71+
return;
72+
}
73+
console.log(`⏱️ >>> Adjusting ZIP structure ${pathToZip}...`);
74+
75+
const root = basename(pathToZip);
76+
const resources = await list(pathToZip);
77+
const hasBaseFolder = resources.find((name) => name === root);
78+
if (hasBaseFolder) {
79+
if (
80+
resources.filter((name) => name.indexOf(path.sep) === -1).length > 1
81+
) {
82+
console.warn(
83+
`${pathToZip} ZIP has the desired root folder ${root}, however the ZIP contains other entries too: ${JSON.stringify(
84+
resources
85+
)}`
86+
);
87+
}
88+
console.log(`👌 <<< The ZIP already has the desired ${root} folder.`);
89+
resolve(pathToZip);
90+
return;
91+
}
92+
93+
const track = temp.track();
94+
try {
95+
const unzipOut = path.join(track.mkdirSync(), root);
96+
fs.mkdirSync(unzipOut);
97+
await unpack(pathToZip, unzipOut);
98+
const adjustedZip = path.join(targetFolderName, path.basename(pathToZip));
99+
await pack(unzipOut, adjustedZip);
100+
console.log(
101+
`👌 <<< Adjusted the ZIP structure. Moved the modified ${basename(
102+
pathToZip
103+
)} to the ${targetFolderName} folder.`
104+
);
105+
resolve(adjustedZip);
106+
} finally {
107+
if (!noCleanup) {
108+
track.cleanupSync();
109+
}
110+
}
111+
});
112+
}
113+
53114
/**
54115
* Returns the `basename` of `pathToFile` without the file extension.
55116
*/
@@ -152,6 +213,7 @@ function getChannelFile(platform) {
152213

153214
module.exports = {
154215
collectUnusedDependencies,
216+
adjustArchiveStructure,
155217
isZip,
156218
unpack,
157219
isNightly,

0 commit comments

Comments
 (0)