mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-11 13:26:32 +00:00
[ci]: Made various changes for the electron app:
- Support for multiple electron targe per platform. - Removed packager CLI. Changed the logic we calculate the app name. - Fixed various OS-specific tests: stubbed `os`. - Restructured the final ZIP formats for Windows and Linux. - Added packager tests. - Switched from `@grpc/grpc-js` to native `grpc`. - Updated the version from 0.0.5 to 0.0.6. Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
parent
d54a69935e
commit
6ce4143d49
@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "arduino-debugger-extension",
|
"name": "arduino-debugger-extension",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"description": "An extension for debugging Arduino programs",
|
"description": "An extension for debugging Arduino programs",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.10.0"
|
"node": ">=10.11.0 <12"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@theia/debug": "next",
|
"@theia/debug": "next",
|
||||||
"arduino-ide-extension": "0.0.5",
|
"arduino-ide-extension": "0.0.6",
|
||||||
"cdt-gdb-adapter": "^0.0.14",
|
"cdt-gdb-adapter": "^0.0.14",
|
||||||
"vscode-debugadapter": "^1.26.0",
|
"vscode-debugadapter": "^1.26.0",
|
||||||
"vscode-debugprotocol": "^1.26.0"
|
"vscode-debugprotocol": "^1.26.0"
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "arduino-ide-extension",
|
"name": "arduino-ide-extension",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"description": "An extension for Theia building the Arduino IDE",
|
"description": "An extension for Theia building the Arduino IDE",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.10.0"
|
"node": ">=10.11.0 <12"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "yarn download-cli && yarn generate-protocol && yarn download-ls && yarn run clean && yarn run build",
|
"prepare": "yarn download-cli && yarn generate-protocol && yarn download-ls && yarn run clean && yarn run build",
|
||||||
@ -19,7 +19,6 @@
|
|||||||
"test:watch": "mocha --watch --watch-files lib \"./lib/test/**/*.test.js\""
|
"test:watch": "mocha --watch --watch-files lib \"./lib/test/**/*.test.js\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@grpc/grpc-js": "^0.6.18",
|
|
||||||
"@theia/application-package": "next",
|
"@theia/application-package": "next",
|
||||||
"@theia/core": "next",
|
"@theia/core": "next",
|
||||||
"@theia/cpp": "next",
|
"@theia/cpp": "next",
|
||||||
@ -37,11 +36,12 @@
|
|||||||
"@types/dateformat": "^3.0.1",
|
"@types/dateformat": "^3.0.1",
|
||||||
"@types/deepmerge": "^2.2.0",
|
"@types/deepmerge": "^2.2.0",
|
||||||
"@types/glob": "^5.0.35",
|
"@types/glob": "^5.0.35",
|
||||||
"@types/google-protobuf": "^3.7.1",
|
"@types/google-protobuf": "^3.7.2",
|
||||||
"@types/js-yaml": "^3.12.2",
|
"@types/js-yaml": "^3.12.2",
|
||||||
"@types/lodash.debounce": "^4.0.6",
|
"@types/lodash.debounce": "^4.0.6",
|
||||||
"@types/ps-tree": "^1.1.0",
|
"@types/ps-tree": "^1.1.0",
|
||||||
"@types/react-select": "^3.0.0",
|
"@types/react-select": "^3.0.0",
|
||||||
|
"@types/sinon": "^7.5.2",
|
||||||
"@types/which": "^1.3.1",
|
"@types/which": "^1.3.1",
|
||||||
"ajv": "^6.5.3",
|
"ajv": "^6.5.3",
|
||||||
"css-element-queries": "^1.2.0",
|
"css-element-queries": "^1.2.0",
|
||||||
@ -49,7 +49,8 @@
|
|||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"fuzzy": "^0.1.3",
|
"fuzzy": "^0.1.3",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"google-protobuf": "^3.11.0",
|
"google-protobuf": "^3.11.4",
|
||||||
|
"grpc": "^1.24.2",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"p-queue": "^5.0.0",
|
"p-queue": "^5.0.0",
|
||||||
@ -79,6 +80,7 @@
|
|||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"protoc": "1.0.4",
|
"protoc": "1.0.4",
|
||||||
"shelljs": "^0.8.3",
|
"shelljs": "^0.8.3",
|
||||||
|
"sinon": "^9.0.1",
|
||||||
"temp": "^0.9.1",
|
"temp": "^0.9.1",
|
||||||
"uuid": "^3.2.1",
|
"uuid": "^3.2.1",
|
||||||
"yargs": "^11.1.0"
|
"yargs": "^11.1.0"
|
||||||
|
@ -86,8 +86,6 @@ ${protos.join(' ')}`).code !== 0) {
|
|||||||
shell.exit(1);
|
shell.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { patch } = require('./patch-grpc-js');
|
|
||||||
patch([out])
|
|
||||||
shell.echo('Done.');
|
shell.echo('Done.');
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
// Use `@grpc/grpc-js` instead of `grpc` at runtime.
|
|
||||||
// https://github.com/grpc/grpc-node/issues/624
|
|
||||||
// https://github.com/grpc/grpc-node/issues/931
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
module.exports.patch = function (roots = [path.join(__dirname, '..', 'src', 'node')]) {
|
|
||||||
console.info('🔧 <<< Patching code...');
|
|
||||||
patch(roots);
|
|
||||||
console.info('👌 <<< Done. The code has been patched.');
|
|
||||||
};
|
|
||||||
|
|
||||||
function patch(paths) {
|
|
||||||
for (const p of paths) {
|
|
||||||
const exist = fs.existsSync(p);
|
|
||||||
if (exist) {
|
|
||||||
const stat = fs.statSync(p);
|
|
||||||
if (stat.isDirectory()) {
|
|
||||||
console.info(`🔧 >>> Scanning code in ${p}...`);
|
|
||||||
patch(fs.readdirSync(p).map(name => path.join(p, name)));
|
|
||||||
} else {
|
|
||||||
let content = fs.readFileSync(p, { encoding: 'utf8' });
|
|
||||||
if (content.indexOf("require('grpc')") !== -1) {
|
|
||||||
console.info(`Updated require('grpc') to require('@grpc/grpc-js') in ${p}.`);
|
|
||||||
fs.writeFileSync(p, content.replace("require('grpc')", "require('@grpc/grpc-js')"));
|
|
||||||
}
|
|
||||||
content = fs.readFileSync(p, { encoding: 'utf8' });
|
|
||||||
if (content.indexOf('import * as grpc from "grpc"') !== -1) {
|
|
||||||
console.info(`Updated import * as grpc from "grpc" to import * as grpc from "@grpc/grpc-js" in ${p}.`);
|
|
||||||
fs.writeFileSync(p, content.replace('import * as grpc from "grpc"', 'import * as grpc from "@grpc/grpc-js"'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.warn(`${p} does not exist. Skipping.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
import * as grpc from '@grpc/grpc-js';
|
import * as grpc from 'grpc';
|
||||||
import * as deepmerge from 'deepmerge';
|
import * as deepmerge from 'deepmerge';
|
||||||
import { injectable, inject, named } from 'inversify';
|
import { injectable, inject, named } from 'inversify';
|
||||||
import URI from '@theia/core/lib/common/uri';
|
import URI from '@theia/core/lib/common/uri';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as grpc from '@grpc/grpc-js';
|
import * as grpc from 'grpc';
|
||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import { ToolOutputServiceServer } from '../common/protocol';
|
import { ToolOutputServiceServer } from '../common/protocol';
|
||||||
import { GrpcClientProvider } from './grpc-client-provider';
|
import { GrpcClientProvider } from './grpc-client-provider';
|
||||||
@ -35,7 +35,7 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async createClient(port: string | number): Promise<CoreClientProvider.Client> {
|
protected async createClient(port: string | number): Promise<CoreClientProvider.Client> {
|
||||||
const client = new ArduinoCoreClient(`localhost:${port}`, grpc.credentials.createInsecure());
|
const client = new ArduinoCoreClient(`localhost:${port}`, grpc.credentials.createInsecure(), this.channelOptions);
|
||||||
const initReq = new InitReq();
|
const initReq = new InitReq();
|
||||||
initReq.setLibraryManagerOnly(false);
|
initReq.setLibraryManagerOnly(false);
|
||||||
const initResp = await new Promise<InitResp>(resolve => {
|
const initResp = await new Promise<InitResp>(resolve => {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import * as grpc from 'grpc';
|
||||||
import { inject, injectable, postConstruct } from 'inversify';
|
import { inject, injectable, postConstruct } from 'inversify';
|
||||||
import { ILogger } from '@theia/core/lib/common/logger';
|
import { ILogger } from '@theia/core/lib/common/logger';
|
||||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||||
@ -68,4 +69,11 @@ export abstract class GrpcClientProvider<C> {
|
|||||||
|
|
||||||
protected abstract close(client: C): void;
|
protected abstract close(client: C): void;
|
||||||
|
|
||||||
|
protected get channelOptions(): grpc.CallOptions {
|
||||||
|
return {
|
||||||
|
'grpc.max_send_message_length': 512 * 1024 * 1024,
|
||||||
|
'grpc.max_receive_message_length': 512 * 1024 * 1024
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as grpc from '@grpc/grpc-js';
|
import * as grpc from 'grpc';
|
||||||
import { injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import { MonitorClient } from '../cli-protocol/monitor/monitor_grpc_pb';
|
import { MonitorClient } from '../cli-protocol/monitor/monitor_grpc_pb';
|
||||||
import { GrpcClientProvider } from '../grpc-client-provider';
|
import { GrpcClientProvider } from '../grpc-client-provider';
|
||||||
@ -7,7 +7,7 @@ import { GrpcClientProvider } from '../grpc-client-provider';
|
|||||||
export class MonitorClientProvider extends GrpcClientProvider<MonitorClient> {
|
export class MonitorClientProvider extends GrpcClientProvider<MonitorClient> {
|
||||||
|
|
||||||
createClient(port: string | number): MonitorClient {
|
createClient(port: string | number): MonitorClient {
|
||||||
return new MonitorClient(`localhost:${port}`, grpc.credentials.createInsecure());
|
return new MonitorClient(`localhost:${port}`, grpc.credentials.createInsecure(), this.channelOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(client: MonitorClient): void {
|
close(client: MonitorClient): void {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ClientDuplexStream } from '@grpc/grpc-js';
|
import { ClientDuplexStream } from 'grpc';
|
||||||
import { TextDecoder, TextEncoder } from 'util';
|
import { TextDecoder, TextEncoder } from 'util';
|
||||||
import { injectable, inject, named } from 'inversify';
|
import { injectable, inject, named } from 'inversify';
|
||||||
import { Struct } from 'google-protobuf/google/protobuf/struct_pb';
|
import { Struct } from 'google-protobuf/google/protobuf/struct_pb';
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
|
import * as sinon from 'sinon';
|
||||||
|
import * as os from '@theia/core/lib/common/os';
|
||||||
import { Container, injectable } from 'inversify';
|
import { Container, injectable } from 'inversify';
|
||||||
import { Event } from '@theia/core/lib/common/event';
|
import { Event } from '@theia/core/lib/common/event';
|
||||||
import { ILogger } from '@theia/core/lib/common/logger';
|
import { ILogger } from '@theia/core/lib/common/logger';
|
||||||
@ -26,18 +28,23 @@ describe('boards-service-client-impl', () => {
|
|||||||
const guessed = AvailableBoard.State.guessed;
|
const guessed = AvailableBoard.State.guessed;
|
||||||
const incomplete = AvailableBoard.State.incomplete;
|
const incomplete = AvailableBoard.State.incomplete;
|
||||||
|
|
||||||
|
let stub: sinon.SinonStub;
|
||||||
|
|
||||||
let server: MockBoardsService;
|
let server: MockBoardsService;
|
||||||
let client: BoardsServiceClientImpl;
|
let client: BoardsServiceClientImpl;
|
||||||
// let storage: MockStorageService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stub = sinon.stub(os, 'isOSX').value(true);
|
||||||
const container = init();
|
const container = init();
|
||||||
server = container.get(MockBoardsService);
|
server = container.get(MockBoardsService);
|
||||||
client = container.get(BoardsServiceClientImpl);
|
client = container.get(BoardsServiceClientImpl);
|
||||||
// storage = container.get(MockStorageService);
|
|
||||||
server.setClient(client);
|
server.setClient(client);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
stub.reset();
|
||||||
|
});
|
||||||
|
|
||||||
it('should have no available boards by default', () => {
|
it('should have no available boards by default', () => {
|
||||||
expect(client.availableBoards).to.have.length(0);
|
expect(client.availableBoards).to.have.length(0);
|
||||||
});
|
});
|
||||||
|
@ -45,16 +45,9 @@ jobs:
|
|||||||
RELEASE_TAG: $(Release.Tag)
|
RELEASE_TAG: $(Release.Tag)
|
||||||
condition: or(in(variables['Agent.OS'], 'Windows_NT'), in(variables['Build.Reason'], 'Manual', 'Schedule'))
|
condition: or(in(variables['Agent.OS'], 'Windows_NT'), in(variables['Build.Reason'], 'Manual', 'Schedule'))
|
||||||
displayName: Package
|
displayName: Package
|
||||||
- bash: |
|
|
||||||
export ARDUINO_POC_NAME=$(./electron/packager/cli name)
|
|
||||||
echo "##vso[task.setvariable variable=ArduinoPoC.AppName]$ARDUINO_POC_NAME"
|
|
||||||
env:
|
|
||||||
RELEASE_TAG: $(Release.Tag)
|
|
||||||
condition: or(in(variables['Agent.OS'], 'Windows_NT'), in(variables['Build.Reason'], 'Manual', 'Schedule'))
|
|
||||||
displayName: '[Config] Use - ARDUINO_POC_NAME env'
|
|
||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
inputs:
|
inputs:
|
||||||
pathtoPublish: electron/build/dist/$(ArduinoPoC.AppName)
|
pathtoPublish: electron/build/dist/build-artifacts
|
||||||
artifactName: 'Arduino Pro IDE - Applications'
|
artifactName: 'Arduino Pro IDE - Applications'
|
||||||
condition: or(in(variables['Agent.OS'], 'Windows_NT'), in(variables['Build.Reason'], 'Manual', 'Schedule'))
|
condition: or(in(variables['Agent.OS'], 'Windows_NT'), in(variables['Build.Reason'], 'Manual', 'Schedule'))
|
||||||
displayName: Publish
|
displayName: Publish
|
||||||
@ -77,7 +70,7 @@ jobs:
|
|||||||
assets: |
|
assets: |
|
||||||
gh-release/Arduino Pro IDE - Applications/*.zip
|
gh-release/Arduino Pro IDE - Applications/*.zip
|
||||||
gh-release/Arduino Pro IDE - Applications/*.dmg
|
gh-release/Arduino Pro IDE - Applications/*.dmg
|
||||||
gh-release/Arduino Pro IDE - Applications/*.tar.xz
|
gh-release/Arduino Pro IDE - Applications/*.AppImage
|
||||||
target: $(Build.SourceVersion)
|
target: $(Build.SourceVersion)
|
||||||
action: Edit
|
action: Edit
|
||||||
tagSource: auto
|
tagSource: auto
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "browser-app",
|
"name": "browser-app",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@theia/core": "next",
|
"@theia/core": "next",
|
||||||
@ -20,8 +20,8 @@
|
|||||||
"@theia/process": "next",
|
"@theia/process": "next",
|
||||||
"@theia/terminal": "next",
|
"@theia/terminal": "next",
|
||||||
"@theia/workspace": "next",
|
"@theia/workspace": "next",
|
||||||
"arduino-ide-extension": "0.0.5",
|
"arduino-ide-extension": "0.0.6",
|
||||||
"arduino-debugger-extension": "0.0.5"
|
"arduino-debugger-extension": "0.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@theia/cli": "next"
|
"@theia/cli": "next"
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "electron-app",
|
"name": "electron-app",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"main": "src-gen/frontend/electron-main.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@theia/core": "next",
|
"@theia/core": "next",
|
||||||
"@theia/cpp": "next",
|
"@theia/cpp": "next",
|
||||||
@ -21,8 +22,8 @@
|
|||||||
"@theia/process": "next",
|
"@theia/process": "next",
|
||||||
"@theia/terminal": "next",
|
"@theia/terminal": "next",
|
||||||
"@theia/workspace": "next",
|
"@theia/workspace": "next",
|
||||||
"arduino-ide-extension": "0.0.5",
|
"arduino-ide-extension": "0.0.6",
|
||||||
"arduino-debugger-extension": "0.0.5"
|
"arduino-debugger-extension": "0.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@theia/cli": "next"
|
"@theia/cli": "next"
|
||||||
|
BIN
electron/build/resources/icons/512x512.png
Normal file
BIN
electron/build/resources/icons/512x512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
@ -1,6 +1,9 @@
|
|||||||
const os = require('os');
|
const os = require('os');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
// To be able to propagate the `process.versions.electron` to the backend main, so that we can load natives correctly.
|
||||||
|
process.env.THEIA_ELECTRON_VERSION = process.versions.electron;
|
||||||
|
|
||||||
process.env.THEIA_DEFAULT_PLUGINS = `local-dir:${path.resolve(__dirname, '..', 'plugins')}`;
|
process.env.THEIA_DEFAULT_PLUGINS = `local-dir:${path.resolve(__dirname, '..', 'plugins')}`;
|
||||||
process.env.THEIA_PLUGINS = [
|
process.env.THEIA_PLUGINS = [
|
||||||
process.env.THEIA_PLUGINS,
|
process.env.THEIA_PLUGINS,
|
||||||
|
57
electron/build/scripts/patch-backend-main.js
Normal file
57
electron/build/scripts/patch-backend-main.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//@ts-check
|
||||||
|
// Patches the `src-gen/backend/main.js` so that the forked backend process has the `process.versions.electron` in the bundled electron app.
|
||||||
|
// https://github.com/eclipse-theia/theia/issues/7358#issue-583306096
|
||||||
|
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
if (!args.length) {
|
||||||
|
console.error(`Expected an argument pointing to the app folder. An app folder is where you have the package.json and src-gen folder.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (args.length > 1) {
|
||||||
|
console.error(`Expected exactly one argument pointing to the app folder. Got multiple instead: ${JSON.stringify(args)}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const arg = args.shift();
|
||||||
|
if (!arg) {
|
||||||
|
console.error('App path was not specified.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const appPath = path.resolve((path.isAbsolute(arg) ? path.join(process.cwd(), arg) : arg));
|
||||||
|
if (!fs.existsSync(appPath)) {
|
||||||
|
console.error(`${appPath} does not exist.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.lstatSync(appPath).isDirectory()) {
|
||||||
|
console.error(`${appPath} is not a directory.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const patched = path.join(appPath, 'src-gen', 'backend', 'original-main.js');
|
||||||
|
if (fs.existsSync(patched)) {
|
||||||
|
console.error(`Already patched. ${patched} already exists.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toPatch = path.join(appPath, 'src-gen', 'backend', 'main.js');
|
||||||
|
if (fs.existsSync(patched)) {
|
||||||
|
console.error(`Cannot patch. ${toPatch} does not exist.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`⏱️ >>> Patching ${toPatch}...`);
|
||||||
|
|
||||||
|
const originalContent = fs.readFileSync(toPatch, { encoding: 'utf8' });
|
||||||
|
const patchedContent = `if (typeof process.versions.electron === 'undefined' && typeof process.env.THEIA_ELECTRON_VERSION === 'string') {
|
||||||
|
process.versions.electron = process.env.THEIA_ELECTRON_VERSION;
|
||||||
|
}
|
||||||
|
require('./original-main');
|
||||||
|
`
|
||||||
|
|
||||||
|
fs.writeFileSync(patched, originalContent);
|
||||||
|
fs.writeFileSync(toPatch, patchedContent);
|
||||||
|
|
||||||
|
console.log(`👌 <<< Patched ${toPatch}. Original 'main.js' is now at ${patched}.`);
|
@ -12,17 +12,17 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@theia/cli": "next",
|
"@theia/cli": "next",
|
||||||
"electron-builder": "^21.2.0"
|
"electron-builder": "^22.4.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn download:plugins && theia build --mode development",
|
"build": "yarn download:plugins && theia build --mode development && yarn patch:main",
|
||||||
"build:release": "yarn download:plugins && theia build --mode development",
|
"build:release": "yarn download:plugins && theia build --mode production && yarn patch:main",
|
||||||
"package": "electron-builder --publish=never",
|
"package": "electron-builder --publish=never",
|
||||||
"package:preview": "electron-builder --dir",
|
"download:plugins": "theia download:plugins",
|
||||||
"download:plugins": "theia download:plugins"
|
"patch:main": "node ./scripts/patch-backend-main ."
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.10.0"
|
"node": ">=10.11.0 <12"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -80,9 +80,17 @@
|
|||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": [
|
"target": [
|
||||||
"zip"
|
{
|
||||||
|
"target": "zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "AppImage",
|
||||||
|
"arch": "armv7l"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"artifactName": "${productName}-${env.ARDUINO_VERSION}-${os}.${ext}"
|
"category": "Development",
|
||||||
|
"icon": "resources/icons",
|
||||||
|
"artifactName": "${productName}-${env.ARDUINO_VERSION}-${os}-${arch}.${ext}"
|
||||||
},
|
},
|
||||||
"dmg": {
|
"dmg": {
|
||||||
"icon": "resources/icon.icns",
|
"icon": "resources/icon.icns",
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
// @ts-check
|
|
||||||
const { versionInfo } = require('./utils');
|
|
||||||
const yargs = require('yargs');
|
|
||||||
|
|
||||||
(() => {
|
|
||||||
yargs
|
|
||||||
.command({
|
|
||||||
command: 'name',
|
|
||||||
describe: 'Returns with the application name we build. The name includes the full application name with the version, the platform and the file extension.',
|
|
||||||
handler: () => {
|
|
||||||
const { platform } = process;
|
|
||||||
let ext = undefined;
|
|
||||||
let os = undefined;
|
|
||||||
if (platform === 'darwin') {
|
|
||||||
ext = 'dmg';
|
|
||||||
os = 'mac';
|
|
||||||
} else if (platform === 'win32') {
|
|
||||||
ext = 'zip';
|
|
||||||
os = 'win';
|
|
||||||
} else if (platform === 'linux') {
|
|
||||||
ext = 'zip';
|
|
||||||
os = 'linux';
|
|
||||||
} else {
|
|
||||||
process.stderr.write(`Unexpected platform: ${platform}.`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
process.stdout.write(`Arduino Pro IDE-${versionInfo().version}-${os}.${ext}`);
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.demandCommand(1)
|
|
||||||
.argv;
|
|
||||||
})();
|
|
@ -5,6 +5,8 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const join = require('path').join;
|
const join = require('path').join;
|
||||||
const shell = require('shelljs');
|
const shell = require('shelljs');
|
||||||
|
const glob = require('glob');
|
||||||
|
const isCI = require('is-ci');
|
||||||
shell.env.THEIA_ELECTRON_SKIP_REPLACE_FFMPEG = '1'; // Do not run the ffmpeg validation for the packager.
|
shell.env.THEIA_ELECTRON_SKIP_REPLACE_FFMPEG = '1'; // Do not run the ffmpeg validation for the packager.
|
||||||
shell.env.NODE_OPTIONS = '--max_old_space_size=4096'; // Increase heap size for the CI
|
shell.env.NODE_OPTIONS = '--max_old_space_size=4096'; // Increase heap size for the CI
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
@ -138,6 +140,18 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
|
|||||||
// Package the electron application. |
|
// Package the electron application. |
|
||||||
//-----------------------------------+
|
//-----------------------------------+
|
||||||
exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} package`, `Packaging your Arduino Pro IDE application`);
|
exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} package`, `Packaging your Arduino Pro IDE application`);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------------------+
|
||||||
|
// Copy to another folder. Azure does not support wildcard for `PublishBuildArtifacts@1.pathToPublish` |
|
||||||
|
//-----------------------------------------------------------------------------------------------------+
|
||||||
|
if (isCI) {
|
||||||
|
try {
|
||||||
|
await copyFilesToBuildArtifacts();
|
||||||
|
} catch (e) {
|
||||||
|
echo(JSON.stringify(e));
|
||||||
|
shell.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
echo(`🎉 Success. Your application is at: ${path('..', 'build', 'dist')}`);
|
echo(`🎉 Success. Your application is at: ${path('..', 'build', 'dist')}`);
|
||||||
|
|
||||||
restore();
|
restore();
|
||||||
@ -201,6 +215,47 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function copyFilesToBuildArtifacts() {
|
||||||
|
echo(`🚢 Detected CI, moving build artifacts...`);
|
||||||
|
const { platform } = process;
|
||||||
|
const cwd = path('..', 'build', 'dist');
|
||||||
|
const targetFolder = path('..', 'build', 'dist', 'build-artifacts');
|
||||||
|
mkdir('-p', targetFolder);
|
||||||
|
const filesToCopy = [];
|
||||||
|
switch (platform) {
|
||||||
|
case 'linux': {
|
||||||
|
filesToCopy.push(...glob.sync('**/Arduino Pro IDE*.{zip,AppImage}', { cwd }).map(p => join(cwd, p)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'win32': {
|
||||||
|
filesToCopy.push(...glob.sync('**/Arduino Pro IDE*.zip', { cwd }).map(p => join(cwd, p)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'darwin': {
|
||||||
|
filesToCopy.push(...glob.sync('**/Arduino Pro IDE*.dmg', { cwd }).map(p => join(cwd, p)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
echo(`Unsupported platform: ${platform}.`);
|
||||||
|
shell.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!filesToCopy.length) {
|
||||||
|
echo(`Could not collect any build artifacts from ${cwd}.`);
|
||||||
|
shell.exit(1);
|
||||||
|
}
|
||||||
|
for (const fileToCopy of filesToCopy) {
|
||||||
|
echo(`🚢 >>> Copying ${fileToCopy} to ${targetFolder}.`);
|
||||||
|
const isZip = await utils.isZip(fileToCopy);
|
||||||
|
if (isZip) {
|
||||||
|
await utils.adjustArchiveStructure(fileToCopy, targetFolder);
|
||||||
|
} else {
|
||||||
|
cp('-rf', fileToCopy, targetFolder);
|
||||||
|
}
|
||||||
|
echo(`👌 >>> Copied ${fileToCopy} to ${targetFolder}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Joins tha path from `__dirname`.
|
* Joins tha path from `__dirname`.
|
||||||
*/
|
*/
|
||||||
|
@ -5,19 +5,36 @@
|
|||||||
"description": "Packager for the Arduino Pro IDE electron application",
|
"description": "Packager for the Arduino Pro IDE electron application",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"prepare": "yarn test",
|
||||||
"package": "node index.js",
|
"package": "node index.js",
|
||||||
"cli": "./cli"
|
"test": "mocha \"./test/**/*.test.js\""
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Arduino SA",
|
"author": "Arduino SA",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"deepmerge": "4.2.2",
|
"@types/file-type": "^10.9.1",
|
||||||
"depcheck": "^0.7.1",
|
"@types/temp": "^0.8.32",
|
||||||
|
"7zip-min": "^1.1.1",
|
||||||
|
"chai": "^4.2.0",
|
||||||
|
"deepmerge": "^4.2.2",
|
||||||
|
"depcheck": "^0.9.2",
|
||||||
|
"file-type": "^14.1.4",
|
||||||
|
"glob": "^7.1.6",
|
||||||
|
"is-ci": "^2.0.0",
|
||||||
|
"mocha": "^7.1.1",
|
||||||
|
"sinon": "^9.0.1",
|
||||||
"shelljs": "^0.8.3",
|
"shelljs": "^0.8.3",
|
||||||
|
"temp": "^0.9.1",
|
||||||
"yargs": "^12.0.5"
|
"yargs": "^12.0.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.12.0"
|
"node": ">=10.11.0 <12"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"reporter": "spec",
|
||||||
|
"colors": true,
|
||||||
|
"watch-extensions": "js",
|
||||||
|
"timeout": 10000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
electron/packager/test/resources/not-a-zip.dmg
Normal file
BIN
electron/packager/test/resources/not-a-zip.dmg
Normal file
Binary file not shown.
BIN
electron/packager/test/resources/zip with whitespace.zip
Normal file
BIN
electron/packager/test/resources/zip with whitespace.zip
Normal file
Binary file not shown.
BIN
electron/packager/test/resources/zip-with-base-folder.zip
Normal file
BIN
electron/packager/test/resources/zip-with-base-folder.zip
Normal file
Binary file not shown.
BIN
electron/packager/test/resources/zip-with-symlink.zip
Normal file
BIN
electron/packager/test/resources/zip-with-symlink.zip
Normal file
Binary file not shown.
BIN
electron/packager/test/resources/zip-without-symlink.zip
Normal file
BIN
electron/packager/test/resources/zip-without-symlink.zip
Normal file
Binary file not shown.
119
electron/packager/test/utils.test.js
Normal file
119
electron/packager/test/utils.test.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const expect = require('chai').expect;
|
||||||
|
const track = require('temp').track();
|
||||||
|
const unpack = require('../utils').unpack;
|
||||||
|
const testMe = require('../utils');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
|
||||||
|
describe('utils', () => {
|
||||||
|
|
||||||
|
describe('adjustArchiveStructure', () => {
|
||||||
|
|
||||||
|
let consoleStub;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
consoleStub = sinon.stub(console, 'log').value(() => { });
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
consoleStub.reset();
|
||||||
|
track.cleanupSync();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject when not a zip file', async () => {
|
||||||
|
try {
|
||||||
|
const invalid = path.join(__dirname, 'resources', 'not-a-zip.dmg');
|
||||||
|
await testMe.adjustArchiveStructure(invalid, track.mkdirSync());
|
||||||
|
throw new Error('Expected a rejection');
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).to.be.an.instanceOf(Error);
|
||||||
|
expect(e.message).to.be.equal('Expected a ZIP file.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject when target directory does not exist', async () => {
|
||||||
|
try {
|
||||||
|
const zip = path.join(__dirname, 'resources', 'zip-with-base-folder.zip');
|
||||||
|
await testMe.adjustArchiveStructure(zip, path.join(__dirname, 'some', 'missing', 'path'));
|
||||||
|
throw new Error('Expected a rejection');
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).to.be.an.instanceOf(Error);
|
||||||
|
expect(e.message.endsWith('does not exist.')).to.be.true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject when target is a file', async () => {
|
||||||
|
try {
|
||||||
|
const zip = path.join(__dirname, 'resources', 'zip-with-base-folder.zip');
|
||||||
|
await testMe.adjustArchiveStructure(zip, path.join(__filename));
|
||||||
|
throw new Error('Expected a rejection');
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).to.be.an.instanceOf(Error);
|
||||||
|
expect(e.message.endsWith('is not a directory.')).to.be.true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be a NOOP when the zip already has the desired base folder', async () => {
|
||||||
|
const zip = path.join(__dirname, 'resources', 'zip-with-base-folder.zip');
|
||||||
|
const actual = await testMe.adjustArchiveStructure(zip, track.mkdirSync());
|
||||||
|
expect(actual).to.be.equal(zip);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle whitespace in file path gracefully', async () => {
|
||||||
|
const zip = path.join(__dirname, 'resources', 'zip with whitespace.zip');
|
||||||
|
const out = track.mkdirSync();
|
||||||
|
const actual = await testMe.adjustArchiveStructure(zip, out, true);
|
||||||
|
expect(actual).to.be.equal(path.join(out, 'zip with whitespace.zip'));
|
||||||
|
console.log(actual);
|
||||||
|
expect(fs.existsSync(actual)).to.be.true;
|
||||||
|
|
||||||
|
const verifyOut = track.mkdirSync();
|
||||||
|
await unpack(actual, verifyOut);
|
||||||
|
|
||||||
|
const root = path.join(verifyOut, 'zip with whitespace');
|
||||||
|
expect(fs.existsSync(root)).to.be.true;
|
||||||
|
expect(fs.lstatSync(root).isDirectory()).to.be.true;
|
||||||
|
const subs = fs.readdirSync(root);
|
||||||
|
expect(subs).to.have.lengthOf(3);
|
||||||
|
expect(subs.sort()).to.be.deep.equal(['a.txt', 'b.txt', 'foo']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should keep the symlinks after ZIP adjustments', async function () {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
this.skip();
|
||||||
|
}
|
||||||
|
const zip = path.join(__dirname, 'resources', 'zip-with-symlink.zip');
|
||||||
|
const out = track.mkdirSync();
|
||||||
|
const actual = await testMe.adjustArchiveStructure(zip, out, true);
|
||||||
|
expect(actual).to.be.equal(path.join(out, 'zip-with-symlink.zip'));
|
||||||
|
console.log(actual);
|
||||||
|
expect(fs.existsSync(actual)).to.be.true;
|
||||||
|
|
||||||
|
const verifyOut = track.mkdirSync();
|
||||||
|
await unpack(actual, verifyOut);
|
||||||
|
expect(fs.lstatSync(path.join(verifyOut, 'zip-with-symlink', 'folder', 'symlinked-sub')).isSymbolicLink()).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should adjust the archive structure if base folder is not present', async () => {
|
||||||
|
const zip = path.join(__dirname, 'resources', 'zip-without-symlink.zip');
|
||||||
|
const out = track.mkdirSync();
|
||||||
|
const actual = await testMe.adjustArchiveStructure(zip, out, true);
|
||||||
|
expect(actual).to.be.equal(path.join(out, 'zip-without-symlink.zip'));
|
||||||
|
console.log(actual);
|
||||||
|
expect(fs.existsSync(actual)).to.be.true;
|
||||||
|
|
||||||
|
const verifyOut = track.mkdirSync();
|
||||||
|
await unpack(actual, verifyOut);
|
||||||
|
|
||||||
|
const root = path.join(verifyOut, 'zip-without-symlink');
|
||||||
|
expect(fs.existsSync(root)).to.be.true;
|
||||||
|
expect(fs.lstatSync(root).isDirectory()).to.be.true;
|
||||||
|
const subs = fs.readdirSync(root);
|
||||||
|
expect(subs).to.have.lengthOf(3);
|
||||||
|
expect(subs.sort()).to.be.deep.equal(['a.txt', 'b.txt', 'foo']);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const temp = require('temp');
|
||||||
|
const zip = require('7zip-min');
|
||||||
const shell = require('shelljs');
|
const shell = require('shelljs');
|
||||||
const depcheck = require('depcheck');
|
const depcheck = require('depcheck');
|
||||||
|
const fromFile = require('file-type').fromFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns with the version info for the artifact.
|
* Returns with the version info for the artifact.
|
||||||
@ -67,7 +70,7 @@ function currentCommitish() {
|
|||||||
*/
|
*/
|
||||||
function collectUnusedDependencies(pathToProject = process.cwd()) {
|
function collectUnusedDependencies(pathToProject = process.cwd()) {
|
||||||
const p = path.isAbsolute(pathToProject) ? pathToProject : path.resolve(process.cwd(), pathToProject);
|
const p = path.isAbsolute(pathToProject) ? pathToProject : path.resolve(process.cwd(), pathToProject);
|
||||||
console.log(`⏱️ >>> Collecting unused backend dependencies for ${p}.`);
|
console.log(`⏱️ >>> Collecting unused backend dependencies for ${p}...`);
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
depcheck(p, {
|
depcheck(p, {
|
||||||
ignoreDirs: [
|
ignoreDirs: [
|
||||||
@ -97,4 +100,108 @@ function collectUnusedDependencies(pathToProject = process.cwd()) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { versionInfo, collectUnusedDependencies };
|
/**
|
||||||
|
* `pathToZip` is a `path/to/your/app-name.zip`.
|
||||||
|
* If the `pathToZip` archive does not have a root directory with name `app-name`, it creates one, and move the content from the
|
||||||
|
* archive's root to the new root folder. If the archive already has the desired root folder, calling this function is a NOOP.
|
||||||
|
* If `pathToZip` is not a ZIP, rejects. `targetFolderName` is the destination folder not the new archive location.
|
||||||
|
*/
|
||||||
|
function adjustArchiveStructure(pathToZip, targetFolderName, noCleanup) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
if (!await isZip(pathToZip)) {
|
||||||
|
reject(new Error(`Expected a ZIP file.`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(targetFolderName)) {
|
||||||
|
reject(new Error(`${targetFolderName} does not exist.`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!fs.lstatSync(targetFolderName).isDirectory()) {
|
||||||
|
reject(new Error(`${targetFolderName} is not a directory.`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`⏱️ >>> Adjusting ZIP structure ${pathToZip}...`);
|
||||||
|
|
||||||
|
const root = basename(pathToZip);
|
||||||
|
const resources = await list(pathToZip);
|
||||||
|
const hasBaseFolder = resources.find(name => name === root);
|
||||||
|
if (hasBaseFolder) {
|
||||||
|
if (resources.filter(name => name.indexOf(path.sep) === -1).length > 1) {
|
||||||
|
console.warn(`${pathToZip} ZIP has the desired root folder ${root}, however the ZIP contains other entries too: ${JSON.stringify(resources)}`);
|
||||||
|
}
|
||||||
|
console.log(`👌 <<< The ZIP already has the desired ${root} folder.`);
|
||||||
|
resolve(pathToZip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const track = temp.track();
|
||||||
|
try {
|
||||||
|
const unzipOut = path.join(track.mkdirSync(), root);
|
||||||
|
fs.mkdirSync(unzipOut);
|
||||||
|
await unpack(pathToZip, unzipOut);
|
||||||
|
const adjustedZip = path.join(targetFolderName, path.basename(pathToZip));
|
||||||
|
await pack(unzipOut, adjustedZip);
|
||||||
|
console.log(`👌 <<< Adjusted the ZIP structure. Moved the modified ${basename(pathToZip)} to the ${targetFolderName} folder.`);
|
||||||
|
resolve(adjustedZip);
|
||||||
|
} finally {
|
||||||
|
if (!noCleanup) {
|
||||||
|
track.cleanupSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the `basename` of `pathToFile` without the file extension.
|
||||||
|
*/
|
||||||
|
function basename(pathToFile) {
|
||||||
|
const name = path.basename(pathToFile);
|
||||||
|
const ext = path.extname(pathToFile);
|
||||||
|
return name.substr(0, name.length - ext.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpack(what, where) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zip.unpack(what, where, error => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function pack(what, where) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zip.pack(what, where, error => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function list(what) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zip.list(what, (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(result.map(({ name }) => name));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function isZip(pathToFile) {
|
||||||
|
if (!fs.existsSync(pathToFile)) {
|
||||||
|
throw new Error(`${pathToFile} does not exist`);
|
||||||
|
}
|
||||||
|
const type = await fromFile(pathToFile);
|
||||||
|
return type && type.ext === 'zip';
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { versionInfo, collectUnusedDependencies, adjustArchiveStructure, isZip, unpack };
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "arduino-editor",
|
"name": "arduino-editor",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"description": "Arduino Pro IDE",
|
"description": "Arduino Pro IDE",
|
||||||
"repository": "https://github.com/bcmi-labs/arduino-editor.git",
|
"repository": "https://github.com/bcmi-labs/arduino-editor.git",
|
||||||
"author": "Arduino SA",
|
"author": "Arduino SA",
|
||||||
@ -16,7 +16,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "lerna run prepare && yarn test && yarn download:plugins",
|
"prepare": "lerna run prepare && yarn test && yarn download:plugins",
|
||||||
"rebuild:browser": "theia rebuild:browser",
|
"rebuild:browser": "theia rebuild:browser",
|
||||||
"rebuild:electron": "theia rebuild:electron",
|
"rebuild:electron": "theia rebuild:electron --modules \"@theia/node-pty\" nsfw native-keymap find-git-repositories grpc",
|
||||||
"start": "yarn --cwd ./browser-app start",
|
"start": "yarn --cwd ./browser-app start",
|
||||||
"watch": "lerna run watch --parallel",
|
"watch": "lerna run watch --parallel",
|
||||||
"test": "lerna run test",
|
"test": "lerna run test",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user