From 12873d32d67a28c52360d4e1d1e4d3e073036df2 Mon Sep 17 00:00:00 2001 From: Kirill Shumilov Date: Thu, 18 Oct 2018 16:44:20 +0300 Subject: [PATCH 1/8] fix(arduino-cli): parse options with any character as option name --- packages/arduino-cli/src/optionParser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/arduino-cli/src/optionParser.js b/packages/arduino-cli/src/optionParser.js index 32c529cb..9e5dd5f8 100644 --- a/packages/arduino-cli/src/optionParser.js +++ b/packages/arduino-cli/src/optionParser.js @@ -45,9 +45,9 @@ export const getLines = R.compose( const menuRegExp = /^menu\./; -const optionNameRegExp = /^menu\.([a-zA-Z0-9_]+)=([a-zA-Z0-9-_ ]+)$/; +const optionNameRegExp = /^menu\.([a-zA-Z0-9_]+)=(.+)$/; -const boardOptionRegExp = /^([a-zA-Z0-9_]+)\.menu\.([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)=([a-zA-Z0-9-_ ()]+)$/; +const boardOptionRegExp = /^([a-zA-Z0-9_]+)\.menu\.([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)=(.+)$/; const osRegExp = /(linux|macosx|windows)/; From 448845e023d4dadffcc638846b514f60dab68d73 Mon Sep 17 00:00:00 2001 From: Kirill Shumilov Date: Thu, 18 Oct 2018 17:26:56 +0300 Subject: [PATCH 2/8] test(arduino-cli): add special characters into unit test for optionParser --- .../esp8266/hardware/esp8266/2.4.2/boards.txt | 22 +++++++++---------- .../arduino-cli/test/optionParser.spec.js | 12 +++++----- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/packages/arduino-cli/test/fixtures/packages/esp8266/hardware/esp8266/2.4.2/boards.txt b/packages/arduino-cli/test/fixtures/packages/esp8266/hardware/esp8266/2.4.2/boards.txt index c0983dab..05bbcc97 100644 --- a/packages/arduino-cli/test/fixtures/packages/esp8266/hardware/esp8266/2.4.2/boards.txt +++ b/packages/arduino-cli/test/fixtures/packages/esp8266/hardware/esp8266/2.4.2/boards.txt @@ -1,15 +1,13 @@ -#### JUST A PART OF BOARDS.TXT FILE FROM ESP8266 PACKAGE -#### SOME OPTIONS WAS REMOVED TO MINIFY FIXTURE +#### A PART OF BOARDS.TXT FILE FROM ESP8266 PACKAGE +#### WITH SOME CHANGES: MENU AND OPTION NAMES +#### NOW CONTAINS SPECIAL CHARACTERS AND CYRILLIC SYMBOLS +#### TO MAKE SURE IN THE UNIT TESTS IT WILL WORK FINE +#### WITH ANY PACKAGE. +#### #### ONLY FOR TESTS! -# -# Do not create pull-requests for this file only, CI will not accept them. -# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. -# All modified files after running with option "--allgen" must be included in the pull-request. -# - -menu.UploadSpeed=Upload Speed -menu.CpuFrequency=CPU Frequency +menu.UploadSpeed=Uplo@d Speed (Скорость загрузки) +menu.CpuFrequency=CPU Frequency 123,-_[]():@we$ome ############################################################## generic.name=Generic ESP8266 Module @@ -26,7 +24,7 @@ generic.build.variant=generic generic.build.spiffs_pagesize=256 generic.build.debug_port= generic.build.debug_level= -generic.menu.CpuFrequency.80=80 MHz +generic.menu.CpuFrequency.80=80 MHz (!@#$$%^&*()[]_-+,./) generic.menu.CpuFrequency.80.build.f_cpu=80000000L generic.menu.CpuFrequency.160=160 MHz generic.menu.CpuFrequency.160.build.f_cpu=160000000L @@ -64,7 +62,7 @@ wifi_slot.build.core=esp8266 wifi_slot.build.spiffs_pagesize=256 wifi_slot.build.debug_port= wifi_slot.build.debug_level= -wifi_slot.menu.CpuFrequency.80=80 MHz +wifi_slot.menu.CpuFrequency.80=80 MHz (!@#$$%^&*()[]_-+,./) wifi_slot.menu.CpuFrequency.80.build.f_cpu=80000000L wifi_slot.menu.CpuFrequency.160=160 MHz wifi_slot.menu.CpuFrequency.160.build.f_cpu=160000000L diff --git a/packages/arduino-cli/test/optionParser.spec.js b/packages/arduino-cli/test/optionParser.spec.js index cd3b11a3..20757251 100644 --- a/packages/arduino-cli/test/optionParser.spec.js +++ b/packages/arduino-cli/test/optionParser.spec.js @@ -22,8 +22,8 @@ const fixtureDir = path.resolve(__dirname, 'fixtures'); // ============================================================================= const espOptionNames = { - UploadSpeed: 'Upload Speed', - CpuFrequency: 'CPU Frequency', + UploadSpeed: 'Uplo@d Speed (Скорость загрузки)', + CpuFrequency: 'CPU Frequency 123,-_[]():@we$ome', }; const espOptions = { @@ -47,7 +47,7 @@ const espOptions = { ], CpuFrequency: [ { - name: '80 MHz', + name: '80 MHz (!@#$$%^&*()[]_-+,./)', value: '80', }, { @@ -58,7 +58,7 @@ const espOptions = { }; const uploadSpeedOptions = { - optionName: 'Upload Speed', + optionName: 'Uplo@d Speed (Скорость загрузки)', optionId: 'UploadSpeed', values: [ { @@ -80,11 +80,11 @@ const uploadSpeedOptions = { ], }; const cpuFrequencyOptions = { - optionName: 'CPU Frequency', + optionName: 'CPU Frequency 123,-_[]():@we$ome', optionId: 'CpuFrequency', values: [ { - name: '80 MHz', + name: '80 MHz (!@#$$%^&*()[]_-+,./)', value: '80', }, { From 419dc1168210ce8be85de0b173b91e44cdaba3ca Mon Sep 17 00:00:00 2001 From: Kirill Shumilov Date: Thu, 18 Oct 2018 19:21:47 +0300 Subject: [PATCH 3/8] fix(xod-client-electron): make proper errors for different steps of upload process --- .../xod-client-electron/src/app/arduinoCli.js | 100 ++++++++++++------ .../src/upload/messages.js | 8 +- .../src/view/containers/App.jsx | 10 +- 3 files changed, 73 insertions(+), 45 deletions(-) diff --git a/packages/xod-client-electron/src/app/arduinoCli.js b/packages/xod-client-electron/src/app/arduinoCli.js index abcb3196..81e54734 100644 --- a/packages/xod-client-electron/src/app/arduinoCli.js +++ b/packages/xod-client-electron/src/app/arduinoCli.js @@ -209,6 +209,30 @@ const patchFqbnWithOptions = board => { )(selectedBoardOptions); }; +// ============================================================================= +// +// Error wrappers +// +// ============================================================================= + +// :: Error -> RejectedPromise Error +const wrapCompileError = err => + Promise.reject( + createError('COMPILE_TOOL_ERROR', { + message: err.message, + code: err.code, + }) + ); + +// :: Error -> RejectedPromise Error +const wrapUploadError = err => + Promise.reject( + createError('UPLOAD_TOOL_ERROR', { + message: err.message, + code: err.code, + }) + ); + // ============================================================================= // // Handlers @@ -369,18 +393,20 @@ const uploadThroughCloud = async (onProgress, cli, payload) => { message: CODE_COMPILED, tab: 'compiler', }); - const uploadLog = await cli.upload( - stdout => - onProgress({ - percentage: 60, - message: stdout, - tab: 'uploader', - }), - payload.port.comName, - payload.board.fqbn, - sketchName, - false - ); + const uploadLog = await cli + .upload( + stdout => + onProgress({ + percentage: 60, + message: stdout, + tab: 'uploader', + }), + payload.port.comName, + payload.board.fqbn, + sketchName, + false + ) + .catch(wrapUploadError); onProgress({ percentage: 100, message: '', @@ -416,17 +442,19 @@ const uploadThroughUSB = async (onProgress, cli, payload) => { tab: 'compiler', }); - const compileLog = await cli.compile( - stdout => - onProgress({ - percentage: 40, - message: stdout, - tab: 'compiler', - }), - payload.board.fqbn, - sketchName, - false - ); + const compileLog = await cli + .compile( + stdout => + onProgress({ + percentage: 40, + message: stdout, + tab: 'compiler', + }), + payload.board.fqbn, + sketchName, + false + ) + .catch(wrapCompileError); onProgress({ percentage: 50, @@ -434,18 +462,20 @@ const uploadThroughUSB = async (onProgress, cli, payload) => { tab: 'uploader', }); - const uploadLog = await cli.upload( - stdout => - onProgress({ - percentage: 60, - message: stdout, - tab: 'uploader', - }), - payload.port.comName, - payload.board.fqbn, - sketchName, - false - ); + const uploadLog = await cli + .upload( + stdout => + onProgress({ + percentage: 60, + message: stdout, + tab: 'uploader', + }), + payload.port.comName, + payload.board.fqbn, + sketchName, + false + ) + .catch(wrapUploadError); onProgress({ percentage: 100, message: '', diff --git a/packages/xod-client-electron/src/upload/messages.js b/packages/xod-client-electron/src/upload/messages.js index c4a58414..fa9ee9e7 100644 --- a/packages/xod-client-electron/src/upload/messages.js +++ b/packages/xod-client-electron/src/upload/messages.js @@ -4,8 +4,14 @@ export default { note: `Cloud compilation does not support ${boardName} yet.`, solution: 'Try to compile it on your own computer', }), + COMPILE_TOOL_ERROR: ({ message }) => ({ + title: 'Compilation failed', + note: `Command ${message}`, + solution: + 'The generated C++ code contains errors. It can be due to a bad node implementation or if your board is not compatible with XOD runtime code. The original compiler error message is above. Fix C++ errors to continue. If you believe it is a bug, report the problem to XOD developers.', + }), UPLOAD_TOOL_ERROR: ({ message }) => ({ - title: 'Upload tool exited with error', + title: 'Upload failed', note: `Command ${message}`, solution: 'Make sure the board is connected, the cable is working, the board model set correctly, the upload port belongs to the board, the board drivers are installed, the upload options (if any) match your board specs.', diff --git a/packages/xod-client-electron/src/view/containers/App.jsx b/packages/xod-client-electron/src/view/containers/App.jsx index d77b14c2..95c4fce2 100644 --- a/packages/xod-client-electron/src/view/containers/App.jsx +++ b/packages/xod-client-electron/src/view/containers/App.jsx @@ -331,15 +331,7 @@ class App extends client.App { board, port, } - ).catch(err => { - console.error(err); // eslint-disable-line no-console - return Promise.reject( - createError('UPLOAD_TOOL_ERROR', { - message: err.message, - code: err.code, - }) - ); - }) + ) ) .then(() => proc.success()) .then(() => { From ffd066ab82af050a41fa8041073e1448d0ec725f Mon Sep 17 00:00:00 2001 From: Kirill Shumilov Date: Thu, 18 Oct 2018 17:38:21 +0300 Subject: [PATCH 4/8] fix(xod-client): endouble ampersand in the menu item label to show it --- packages/xod-client/src/utils/menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/xod-client/src/utils/menu.js b/packages/xod-client/src/utils/menu.js index 165b0d31..9223df02 100644 --- a/packages/xod-client/src/utils/menu.js +++ b/packages/xod-client/src/utils/menu.js @@ -107,7 +107,7 @@ const rawItems = { label: 'Upload to Arduino...', }, updatePackages: { - label: 'Upgrade Arduino Packages & Toolchains...', + label: 'Upgrade Arduino Packages && Toolchains...', }, view: { From 422b63c86ba5caf7565b1f36ca4acf2161b3ab27 Mon Sep 17 00:00:00 2001 From: Evgeny Kochetkov Date: Thu, 18 Oct 2018 16:48:38 +0300 Subject: [PATCH 5/8] fix(xod-arduino, stdlib): do not rely on NUM_DIGITAL_PINS being defined fixes #1477 --- packages/xod-arduino/platform/runtime.cpp | 8 ++++++++ workspace/__lib__/xod/common-hardware/servo/patch.cpp | 2 +- workspace/__lib__/xod/gpio/digital-read/patch.cpp | 3 +-- workspace/__lib__/xod/gpio/digital-write/patch.cpp | 3 +-- workspace/__lib__/xod/gpio/pwm-write/patch.cpp | 3 +-- workspace/blink/__fixtures__/arduino.cpp | 11 +++++++++-- .../__fixtures__/arduino.cpp | 8 ++++++++ workspace/lcd-time/__fixtures__/arduino.cpp | 8 ++++++++ workspace/two-button-switch/__fixtures__/arduino.cpp | 8 ++++++++ 9 files changed, 45 insertions(+), 9 deletions(-) diff --git a/packages/xod-arduino/platform/runtime.cpp b/packages/xod-arduino/platform/runtime.cpp index 3df224dc..70eac599 100644 --- a/packages/xod-arduino/platform/runtime.cpp +++ b/packages/xod-arduino/platform/runtime.cpp @@ -198,6 +198,14 @@ bool isTimedOut(const ContextT* ctx) { return detail::isTimedOut(ctx->_node); } +bool isValidDigitalPort(uint8_t port) { +#ifdef NUM_DIGITAL_PINS + return port < NUM_DIGITAL_PINS; +#else + return true; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- diff --git a/workspace/__lib__/xod/common-hardware/servo/patch.cpp b/workspace/__lib__/xod/common-hardware/servo/patch.cpp index 74b732fb..f168ceb9 100644 --- a/workspace/__lib__/xod/common-hardware/servo/patch.cpp +++ b/workspace/__lib__/xod/common-hardware/servo/patch.cpp @@ -16,7 +16,7 @@ void evaluate(Context ctx) { State* state = getState(ctx); auto port = (int)getValue(ctx); - if (port > NUM_DIGITAL_PINS - 1) { + if (!isValidDigitalPort(port)) { emitValue(ctx, 1); return; } diff --git a/workspace/__lib__/xod/gpio/digital-read/patch.cpp b/workspace/__lib__/xod/gpio/digital-read/patch.cpp index 8f923d9c..fa793d14 100644 --- a/workspace/__lib__/xod/gpio/digital-read/patch.cpp +++ b/workspace/__lib__/xod/gpio/digital-read/patch.cpp @@ -8,8 +8,7 @@ void evaluate(Context ctx) { return; const uint8_t port = getValue(ctx); - bool err = (port > NUM_DIGITAL_PINS - 1); - if (err) { + if (!isValidDigitalPort(port)) { emitValue(ctx, 1); return; } diff --git a/workspace/__lib__/xod/gpio/digital-write/patch.cpp b/workspace/__lib__/xod/gpio/digital-write/patch.cpp index 8c35d630..f4aa82e9 100644 --- a/workspace/__lib__/xod/gpio/digital-write/patch.cpp +++ b/workspace/__lib__/xod/gpio/digital-write/patch.cpp @@ -8,8 +8,7 @@ void evaluate(Context ctx) { return; const uint8_t port = getValue(ctx); - bool err = (port > NUM_DIGITAL_PINS - 1); - if (err) { + if (!isValidDigitalPort(port)) { emitValue(ctx, 1); return; } diff --git a/workspace/__lib__/xod/gpio/pwm-write/patch.cpp b/workspace/__lib__/xod/gpio/pwm-write/patch.cpp index 519eadd1..041190d8 100644 --- a/workspace/__lib__/xod/gpio/pwm-write/patch.cpp +++ b/workspace/__lib__/xod/gpio/pwm-write/patch.cpp @@ -14,9 +14,8 @@ void evaluate(Context ctx) { return; const uint8_t port = getValue(ctx); - bool err = (port > NUM_DIGITAL_PINS - 1); - if (err) { + if (!isValidDigitalPort(port)) { emitValue(ctx, 1); return; } diff --git a/workspace/blink/__fixtures__/arduino.cpp b/workspace/blink/__fixtures__/arduino.cpp index c18b1484..189dd9bc 100644 --- a/workspace/blink/__fixtures__/arduino.cpp +++ b/workspace/blink/__fixtures__/arduino.cpp @@ -777,6 +777,14 @@ bool isTimedOut(const ContextT* ctx) { return detail::isTimedOut(ctx->_node); } +bool isValidDigitalPort(uint8_t port) { +#ifdef NUM_DIGITAL_PINS + return port < NUM_DIGITAL_PINS; +#else + return true; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- @@ -1235,8 +1243,7 @@ void evaluate(Context ctx) { return; const uint8_t port = getValue(ctx); - bool err = (port > NUM_DIGITAL_PINS - 1); - if (err) { + if (!isValidDigitalPort(port)) { emitValue(ctx, 1); return; } diff --git a/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp b/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp index 7595d95b..12922fab 100644 --- a/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp +++ b/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp @@ -777,6 +777,14 @@ bool isTimedOut(const ContextT* ctx) { return detail::isTimedOut(ctx->_node); } +bool isValidDigitalPort(uint8_t port) { +#ifdef NUM_DIGITAL_PINS + return port < NUM_DIGITAL_PINS; +#else + return true; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- diff --git a/workspace/lcd-time/__fixtures__/arduino.cpp b/workspace/lcd-time/__fixtures__/arduino.cpp index ef38d140..9a5b8db0 100644 --- a/workspace/lcd-time/__fixtures__/arduino.cpp +++ b/workspace/lcd-time/__fixtures__/arduino.cpp @@ -777,6 +777,14 @@ bool isTimedOut(const ContextT* ctx) { return detail::isTimedOut(ctx->_node); } +bool isValidDigitalPort(uint8_t port) { +#ifdef NUM_DIGITAL_PINS + return port < NUM_DIGITAL_PINS; +#else + return true; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- diff --git a/workspace/two-button-switch/__fixtures__/arduino.cpp b/workspace/two-button-switch/__fixtures__/arduino.cpp index 5402b3b2..50ad124d 100644 --- a/workspace/two-button-switch/__fixtures__/arduino.cpp +++ b/workspace/two-button-switch/__fixtures__/arduino.cpp @@ -777,6 +777,14 @@ bool isTimedOut(const ContextT* ctx) { return detail::isTimedOut(ctx->_node); } +bool isValidDigitalPort(uint8_t port) { +#ifdef NUM_DIGITAL_PINS + return port < NUM_DIGITAL_PINS; +#else + return true; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- From 645f32ac202932a401ee06142b1398ada4f0ac52 Mon Sep 17 00:00:00 2001 From: Evgeny Kochetkov Date: Thu, 18 Oct 2018 18:43:53 +0300 Subject: [PATCH 6/8] fix(xod-arduino, xod-tabtest, stdlib): do not rely on NUM_ANALOG_INPUTS being defined --- packages/xod-arduino/platform/runtime.cpp | 8 ++++++++ packages/xod-tabtest/cpp/Arduino.h | 2 ++ workspace/__lib__/xod/gpio/analog-read/patch.cpp | 4 ++-- workspace/blink/__fixtures__/arduino.cpp | 8 ++++++++ .../count-with-feedback-loops/__fixtures__/arduino.cpp | 8 ++++++++ workspace/lcd-time/__fixtures__/arduino.cpp | 8 ++++++++ workspace/two-button-switch/__fixtures__/arduino.cpp | 8 ++++++++ 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/packages/xod-arduino/platform/runtime.cpp b/packages/xod-arduino/platform/runtime.cpp index 70eac599..55fae8b5 100644 --- a/packages/xod-arduino/platform/runtime.cpp +++ b/packages/xod-arduino/platform/runtime.cpp @@ -206,6 +206,14 @@ bool isValidDigitalPort(uint8_t port) { #endif } +bool isValidAnalogPort(uint8_t port) { +#ifdef NUM_ANALOG_INPUTS + return port >= A0 && port < A0 + NUM_ANALOG_INPUTS; +#else + return port >= A0; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- diff --git a/packages/xod-tabtest/cpp/Arduino.h b/packages/xod-tabtest/cpp/Arduino.h index b3e08b16..9c53c915 100644 --- a/packages/xod-tabtest/cpp/Arduino.h +++ b/packages/xod-tabtest/cpp/Arduino.h @@ -11,6 +11,8 @@ void setup(); void loop(); +#define A0 14 + uint32_t millis(); void delay(uint32_t); diff --git a/workspace/__lib__/xod/gpio/analog-read/patch.cpp b/workspace/__lib__/xod/gpio/analog-read/patch.cpp index b0fe4f86..ca855b56 100644 --- a/workspace/__lib__/xod/gpio/analog-read/patch.cpp +++ b/workspace/__lib__/xod/gpio/analog-read/patch.cpp @@ -8,8 +8,8 @@ void evaluate(Context ctx) { return; const uint8_t port = getValue(ctx); - bool err = (port < A0 || port > A0 + NUM_ANALOG_INPUTS - 1); - if (err) { + + if (!isValidAnalogPort(port)) { emitValue(ctx, 1); return; } diff --git a/workspace/blink/__fixtures__/arduino.cpp b/workspace/blink/__fixtures__/arduino.cpp index 189dd9bc..289473d4 100644 --- a/workspace/blink/__fixtures__/arduino.cpp +++ b/workspace/blink/__fixtures__/arduino.cpp @@ -785,6 +785,14 @@ bool isValidDigitalPort(uint8_t port) { #endif } +bool isValidAnalogPort(uint8_t port) { +#ifdef NUM_ANALOG_INPUTS + return port >= A0 && port < A0 + NUM_ANALOG_INPUTS; +#else + return port >= A0; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- diff --git a/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp b/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp index 12922fab..8dc6aab7 100644 --- a/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp +++ b/workspace/count-with-feedback-loops/__fixtures__/arduino.cpp @@ -785,6 +785,14 @@ bool isValidDigitalPort(uint8_t port) { #endif } +bool isValidAnalogPort(uint8_t port) { +#ifdef NUM_ANALOG_INPUTS + return port >= A0 && port < A0 + NUM_ANALOG_INPUTS; +#else + return port >= A0; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- diff --git a/workspace/lcd-time/__fixtures__/arduino.cpp b/workspace/lcd-time/__fixtures__/arduino.cpp index 9a5b8db0..6391038c 100644 --- a/workspace/lcd-time/__fixtures__/arduino.cpp +++ b/workspace/lcd-time/__fixtures__/arduino.cpp @@ -785,6 +785,14 @@ bool isValidDigitalPort(uint8_t port) { #endif } +bool isValidAnalogPort(uint8_t port) { +#ifdef NUM_ANALOG_INPUTS + return port >= A0 && port < A0 + NUM_ANALOG_INPUTS; +#else + return port >= A0; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- diff --git a/workspace/two-button-switch/__fixtures__/arduino.cpp b/workspace/two-button-switch/__fixtures__/arduino.cpp index 50ad124d..b8e41fb6 100644 --- a/workspace/two-button-switch/__fixtures__/arduino.cpp +++ b/workspace/two-button-switch/__fixtures__/arduino.cpp @@ -785,6 +785,14 @@ bool isValidDigitalPort(uint8_t port) { #endif } +bool isValidAnalogPort(uint8_t port) { +#ifdef NUM_ANALOG_INPUTS + return port >= A0 && port < A0 + NUM_ANALOG_INPUTS; +#else + return port >= A0; +#endif +} + } // namespace xod //---------------------------------------------------------------------------- From 2387ca6253926197cd84be67107a51d2884b32c5 Mon Sep 17 00:00:00 2001 From: Kirill Shumilov Date: Tue, 16 Oct 2018 19:05:52 +0300 Subject: [PATCH 7/8] feat(arduino-cli): make possible to change config of arduino-cli without recreating wrapper object --- packages/arduino-cli/README.md | 8 +++++++ packages/arduino-cli/src/config.js | 14 +++++++++---- packages/arduino-cli/src/index.js | 15 +++++++++++-- packages/arduino-cli/test-func/index.spec.js | 22 ++++++++++++++++++++ 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/packages/arduino-cli/README.md b/packages/arduino-cli/README.md index 5a66a792..29b0d656 100644 --- a/packages/arduino-cli/README.md +++ b/packages/arduino-cli/README.md @@ -36,6 +36,14 @@ Wraps `arduino-cli config dump`. - Returns `Promise` +### updateConfig(newConfig) +Replaces old config with the new one. + +Accepts: +- `newConfig` `` — Plain JS object representation of `.cli-config.yml` + +- Returns `` with the new config + ### listConnectedBoards() A wrapper with a custom extension over `arduino-cli board list`. diff --git a/packages/arduino-cli/src/config.js b/packages/arduino-cli/src/config.js index d08e6198..84b21599 100644 --- a/packages/arduino-cli/src/config.js +++ b/packages/arduino-cli/src/config.js @@ -9,10 +9,8 @@ const getDefaultConfig = configDir => ({ arduino_data: resolve(configDir, 'data'), }); -export const configure = inputConfig => { - const configDir = fse.mkdtempSync(resolve(tmpdir(), 'arduino-cli')); - const configPath = resolve(configDir, '.cli-config.yml'); - const config = inputConfig || getDefaultConfig(configDir); +// :: Path -> Object -> { config: Object, path: Path } +export const saveConfig = (configPath, config) => { const yamlString = YAML.stringify(config, 2); // Write config @@ -28,6 +26,14 @@ export const configure = inputConfig => { }; }; +// :: Object -> { config: Object, path: Path } +export const configure = inputConfig => { + const configDir = fse.mkdtempSync(resolve(tmpdir(), 'arduino-cli')); + const configPath = resolve(configDir, '.cli-config.yml'); + const config = inputConfig || getDefaultConfig(configDir); + return saveConfig(configPath, config); +}; + // :: Path -> [URL] -> Promise [URL] Error export const addPackageIndexUrls = (configPath, urls) => fse diff --git a/packages/arduino-cli/src/index.js b/packages/arduino-cli/src/index.js index 30c1a32a..67723736 100644 --- a/packages/arduino-cli/src/index.js +++ b/packages/arduino-cli/src/index.js @@ -5,7 +5,12 @@ import { exec, spawn } from 'child-process-promise'; import YAML from 'yamljs'; import { remove } from 'fs-extra'; -import { configure, addPackageIndexUrl, addPackageIndexUrls } from './config'; +import { + saveConfig, + configure, + addPackageIndexUrl, + addPackageIndexUrls, +} from './config'; import { patchBoardsWithOptions } from './optionParser'; import listAvailableBoards from './listAvailableBoards'; import parseProgressLog from './parseProgressLog'; @@ -19,7 +24,7 @@ const escapeSpacesNonWin = R.unless(() => IS_WIN, R.replace(/\s/g, '\\ ')); * @param {Object} config Plain-object representation of `.cli-config.yml` */ const ArduinoCli = (pathToBin, config = null) => { - const { path: configPath, config: cfg } = configure(config); + let { path: configPath, config: cfg } = configure(config); const escapedConfigPath = escapeSpacesNonWin(configPath); const run = args => @@ -68,6 +73,12 @@ const ArduinoCli = (pathToBin, config = null) => { return { dumpConfig: getConfig, + updateConfig: newConfig => { + const newCfg = saveConfig(configPath, newConfig); + configPath = newCfg.path; + cfg = newCfg.config; + return cfg; + }, listConnectedBoards: () => listBoardsWith('list', R.prop('serialBoards')), listInstalledBoards: () => listBoardsWith('listall', R.prop('boards')), listAvailableBoards: () => listAvailableBoards(cfg.arduino_data), diff --git a/packages/arduino-cli/test-func/index.spec.js b/packages/arduino-cli/test-func/index.spec.js index f394218e..d3a8a084 100644 --- a/packages/arduino-cli/test-func/index.spec.js +++ b/packages/arduino-cli/test-func/index.spec.js @@ -1,3 +1,4 @@ +import * as R from 'ramda'; import { resolve } from 'path'; import * as fse from 'fs-extra'; import { assert } from 'chai'; @@ -42,6 +43,27 @@ describe('Arduino Cli', () => { })); }); + describe('Update arduino-cli config', () => { + afterEach(() => fse.remove(tmpDir)); + it('updates config', async () => { + const cli = arduinoCli(PATH_TO_CLI, cfg); + const curConf = await cli.dumpConfig(); + + assert.strictEqual(curConf.sketchbook_path, cfg.sketchbook_path); + assert.strictEqual(curConf.arduino_data, cfg.arduino_data); + + const newDataDir = resolve(tmpDir, 'newData'); + const newConf = R.assoc('arduino_data', newDataDir, curConf); + cli.updateConfig(newConf); + const updatedConf = await cli.dumpConfig(); + + assert.strictEqual(updatedConf.sketchbook_path, cfg.sketchbook_path); + assert.strictEqual(updatedConf.arduino_data, newDataDir); + + return cli; + }); + }); + describe('Installs additional package index', () => { afterEach(() => fse.remove(tmpDir)); const url = From 46a55e911c21906d8b9a92690f70dc9c9b9b36ba Mon Sep 17 00:00:00 2001 From: Kirill Shumilov Date: Tue, 16 Oct 2018 19:06:50 +0300 Subject: [PATCH 8/8] refactor(xod-client-electron): handle switch workspace to work properly with arduino-cli without restarting the IDE --- .../xod-client-electron/src/app/arduinoCli.js | 94 +++++++++++++------ packages/xod-client-electron/src/app/main.js | 6 +- .../src/app/migrateArduinoPackages.js | 6 +- 3 files changed, 72 insertions(+), 34 deletions(-) diff --git a/packages/xod-client-electron/src/app/arduinoCli.js b/packages/xod-client-electron/src/app/arduinoCli.js index 81e54734..c5ffa499 100644 --- a/packages/xod-client-electron/src/app/arduinoCli.js +++ b/packages/xod-client-electron/src/app/arduinoCli.js @@ -97,12 +97,16 @@ const copyLibraries = async (bundledLibDir, userLibDir, sketchbookLibDir) => { return sketchbookLibDir; }; -// :: _ -> Promise Path Error -const ensureExtraTxt = R.composeP( - extraFilePath => fse.ensureFile(extraFilePath).then(R.always(extraFilePath)), - ws => path.join(ws, ARDUINO_PACKAGES_DIRNAME, ARDUINO_EXTRA_URLS_FILENAME), - loadWorkspacePath -); +// :: Path -> Promise Path Error +const ensureExtraTxt = async wsPath => { + const extraTxtFilePath = path.join( + wsPath, + ARDUINO_PACKAGES_DIRNAME, + ARDUINO_EXTRA_URLS_FILENAME + ); + await fse.ensureFile(extraTxtFilePath); + return extraTxtFilePath; +}; const copyPackageIndexes = async wsPackageDir => { const filesToCopy = await R.composeP( @@ -249,6 +253,26 @@ const wrapUploadError = err => export const prepareSketchDir = () => fse.mkdtemp(path.resolve(os.tmpdir(), 'xod_temp_sketchbook')); +/** + * Prepare `__packages__` directory inside user's workspace if + * it does not prepared earlier: + * - copy bundled package index json files + * - migrate old arduino packages if they are exist + * - create `extra.txt` file + * + * Returns Path to the `__packages__` directory inside user's workspace + * + * :: Path -> Promise Path Error + */ +const prepareWorkspacePackagesDir = async wsPath => { + const packagesDirPath = getArduinoPackagesPath(wsPath); + + await copyPackageIndexes(packagesDirPath); + await migrateArduinoPackages(wsPath); + await ensureExtraTxt(wsPath); + + return packagesDirPath; +}; /** * Creates an instance of ArduinoCli. * @@ -261,31 +285,42 @@ export const prepareSketchDir = () => * * :: Path -> Promise ArduinoCli Error */ -export const create = sketchDir => - loadWorkspacePath().then(async wsPath => { - const arduinoCliPath = await getArduinoCliPath(); +export const create = async sketchDir => { + const wsPath = await loadWorkspacePath(); + const arduinoCliPath = await getArduinoCliPath(); + const packagesDirPath = await prepareWorkspacePackagesDir(wsPath); - const packagesDirPath = getArduinoPackagesPath(wsPath); - - await copyPackageIndexes(packagesDirPath); - await migrateArduinoPackages(); - await ensureExtraTxt(); - - if (!await fse.pathExists(arduinoCliPath)) { - throw createError('ARDUINO_CLI_NOT_FOUND', { - path: arduinoCliPath, - isDev: IS_DEV, - }); - } - - return arduinoCli(arduinoCliPath, { - arduino_data: packagesDirPath, - sketchbook_path: sketchDir, - board_manager: { - additional_urls: BUNDLED_ADDITIONAL_URLS, - }, + if (!await fse.pathExists(arduinoCliPath)) { + throw createError('ARDUINO_CLI_NOT_FOUND', { + path: arduinoCliPath, + isDev: IS_DEV, }); + } + + return arduinoCli(arduinoCliPath, { + arduino_data: packagesDirPath, + sketchbook_path: sketchDir, + board_manager: { + additional_urls: BUNDLED_ADDITIONAL_URLS, + }, }); +}; + +/** + * Updates path to the `arduino_data` in the arduino-cli `.cli-config.yml` + * and prepares `__packages__` directory in the user's workspace if needed. + * + * We have to call this function when user changes workspace to make all + * functions provided by this module works properly without restarting the IDE. + * + * :: ArduinoCli -> Path -> Promise Object Error + */ +export const switchWorkspace = async (cli, newWsPath) => { + const oldConfig = await cli.dumpConfig(); + const packagesDirPath = await prepareWorkspacePackagesDir(newWsPath); + const newConfig = R.assoc('arduino_data', packagesDirPath, oldConfig); + return cli.updateConfig(newConfig); +}; /** * Updates package index json files. @@ -304,7 +339,8 @@ const updateIndexes = async cli => { R.reject(isAmong(urls)), R.split('\r\n'), p => fse.readFile(p, { encoding: 'utf8' }), - ensureExtraTxt + ensureExtraTxt, + loadWorkspacePath )(); }; diff --git a/packages/xod-client-electron/src/app/main.js b/packages/xod-client-electron/src/app/main.js index cbe24e59..e6648ccd 100644 --- a/packages/xod-client-electron/src/app/main.js +++ b/packages/xod-client-electron/src/app/main.js @@ -241,13 +241,17 @@ const onReady = () => { .prepareSketchDir() .then(aCli.create) .then(arduinoCli => { - // TODO: Refactor (WS) aCli.subscribeListBoards(arduinoCli); aCli.subscribeUpload(arduinoCli); aCli.subscribeUpdateIndexes(arduinoCli); aCli.subscibeCheckUpdates(arduinoCli); aCli.subscribeUpgradeArduinoPackages(arduinoCli); + // On switching workspace -> update arduino-cli config + ipcMain.on(EVENTS.SWITCH_WORKSPACE, (event, newWsPath) => + aCli.switchWorkspace(arduinoCli, newWsPath) + ); + subscribeOnCheckArduinoDependencies(arduinoCli); subscribeOnInstallArduinoDependencies(arduinoCli); }) diff --git a/packages/xod-client-electron/src/app/migrateArduinoPackages.js b/packages/xod-client-electron/src/app/migrateArduinoPackages.js index 6ab60061..a0863ad4 100644 --- a/packages/xod-client-electron/src/app/migrateArduinoPackages.js +++ b/packages/xod-client-electron/src/app/migrateArduinoPackages.js @@ -12,7 +12,6 @@ import * as R from 'ramda'; import * as fse from 'fs-extra'; import { app } from 'electron'; -import { loadWorkspacePath } from './workspaceActions'; import { ARDUINO_PACKAGES_DIRNAME } from './constants'; const OLD_PACKAGE_VERSIONS = { @@ -32,9 +31,9 @@ const moveWithoutEexistError = (from, to) => /** * Moves old packages into Users' workspace. * - * :: _ -> Promise 0 Error + * :: Path -> Promise 0 Error */ -export default async () => { +export default async wsPath => { const appData = app.getPath('userData'); const oldPackagesDir = path.join(appData, 'packages'); if (!await fse.pathExists(oldPackagesDir)) return 0; @@ -42,7 +41,6 @@ export default async () => { const oldHardwareDir = path.join(oldPackagesDir, 'arduino', 'hardware'); const archs = await fse.readdir(oldHardwareDir); - const wsPath = await loadWorkspacePath(); const wsPackagesDir = path.join(wsPath, ARDUINO_PACKAGES_DIRNAME, 'packages'); const wsHardwareDir = path.join(wsPackagesDir, 'arduino', 'hardware');