Compare commits

..

1412 Commits

Author SHA1 Message Date
Balena CI
166b30bb0a v1.5.79 2020-02-20 19:33:28 +02:00
Alexis Svinartchouk
8eeb81f58e Merge pull request #3077 from balena-io/fix-start-script
Fix start script
2020-02-20 18:31:34 +01:00
Alexis Svinartchouk
0b20a1eeaa Remove "Download the React DevTools for a better development experience" message
Changelog-entry: Remove "Download the React DevTools for a better development experience" message
Change-type: patch
2020-02-20 14:21:55 +01:00
Alois Klink
d8cb8f7815 fix(afterPack): error on launch from deb terminal
When installing balena-etcher via apt on Debian/Ubuntu,
the command `balena-etcher-electron` fails with the error:
line 3: /usr/bin/balena-etcher-electron.bin: No such file or directory

This is because the /usr/bin/balena-etcher-electron is a symlink
to /opt/balenaEtcher/balena-etcher-electron, but the script looks
for balena-etcher-electron.bin in the symlink directory, not the
actual script location directory.

This commit uses `$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")` to
find the real location of the balena-etcher-electron script without
symlink, so that balena-etcher-electron.bin is correctly found.

Change-Type: patch
Changelog-Entry: Fix error when launching from terminal when installed via apt.
Fixes: https://github.com/balena-io/etcher/issues/3074
2020-02-20 13:04:17 +01:00
Balena CI
36f79593cf v1.5.78 2020-02-19 19:29:10 +02:00
Alexis Svinartchouk
1014b25bf5 Merge pull request #3073 from balena-io/update-drivelist-escape
Update drivelist to 8.0.10 to fix parsing lsblk --pairs
2020-02-19 18:27:30 +01:00
Alexis Svinartchouk
55dcfc1a85 Update drivelist to 8.0.10 to fix parsing lsblk --pairs
Changelog-entry: Update drivelist to 8.0.10 to fix parsing lsblk --pairs
Change-type: patch
2020-02-19 11:51:39 +01:00
Balena CI
9b6a628d51 v1.5.77 2020-02-17 22:19:00 +02:00
Alexis Svinartchouk
8b5a42073d Merge pull request #3072 from balena-io/updates
Updates
2020-02-17 21:15:54 +01:00
Alexis Svinartchouk
7991d40760 Specify flashImageToDrive return type
Change-type: patch
2020-02-17 18:43:01 +01:00
Alexis Svinartchouk
4203296414 Fix error message not being shown on write error
Changelog-entry: Fix error message not being shown on write error
Change-type: patch
2020-02-17 18:39:30 +01:00
Alexis Svinartchouk
93d319275f Fix imports in lib/start.ts
Change-type: patch
2020-02-13 12:04:26 +01:00
Alexis Svinartchouk
94d262263c The RGBLed module has been moved to a separate repository
Changelog-entry: The RGBLed module has been moved to a separate repository
Change-type: patch
2020-02-13 11:15:39 +01:00
Alexis Svinartchouk
ed90f21188 Running make lint will now fix the typescript files
Change-type: patch
2020-02-13 11:14:46 +01:00
Balena CI
80e0231727 v1.5.76 2020-02-06 15:55:10 +02:00
Alexis Svinartchouk
981197583a Merge pull request #3064 from balena-io/update-etcher-sdk-to-2.0.17
Update etcher-sdk to ^2.0.17
2020-02-06 14:53:14 +01:00
Lorenzo Alberto Maria Ambrosi
6f58344e7b Prefix temp permissions script name
Change-type: patch
Changelog-entry: Prefix temp permissions script name
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2020-02-05 18:14:14 +01:00
Alexis Svinartchouk
07be844985 Fix image drop zone, remove react-dropzone dependency
Changelog-entry: Fix image drop zone, remove react-dropzone dependency
Change-type: patch
2020-02-05 16:55:44 +01:00
Alexis Svinartchouk
45262583e6 Update etcher-sdk to ^2.0.17
Changelog-entry: Update etcher-sdk to ^2.0.17
Change-type: patch
2020-02-05 15:14:37 +01:00
Balena CI
c113e38531 v1.5.75 2020-02-05 14:37:20 +02:00
Alexis Svinartchouk
8771f311d7 Merge pull request #3062 from balena-io/init-leds-map
Initialize leds object map
2020-02-05 13:35:10 +01:00
Omar López
fdec65e9bd Initialize leds object map
Fixes: #3056 #3057 #3058
Change-type: patch
Changelog-entry: Initialize leds object map
2020-02-05 12:32:42 +01:00
Balena CI
f8b46dc647 v1.5.74 2020-02-05 00:17:12 +02:00
Alexis Svinartchouk
847e47b5db Merge pull request #3046 from balena-io/etcher-pro-leds
Etcher pro leds
2020-02-04 23:15:39 +01:00
Alexis Svinartchouk
227bad9e99 Keep leds sysfs files open
Change-type: patch
2020-02-04 20:08:58 +01:00
Alexis Svinartchouk
cb8168de41 Etcher pro leds feature
Changelog-entry: Etcher pro leds feature
Change-type: patch
2020-02-04 20:08:57 +01:00
Alexis Svinartchouk
c200a0c7ac Compress deb package with bzip instead of xz
7za fails on ia32 CI with "ERROR: Can't allocate required memory!"

Changelog-entry: Compress deb package with bzip instead of xz
Change-type: patch
2020-02-04 20:08:56 +01:00
Alexis Svinartchouk
81e80572d8 A warning about the selected image does not prevent the selection
This was introduced in 1.5.72

Change-type: patch
2020-02-04 20:08:55 +01:00
Alexis Svinartchouk
2aa6c83714 Update electron to 7.1.11
Changelog-entry: Update electron to 7.1.11
Chanege-type: patch
2020-02-04 20:08:53 +01:00
Alexis Svinartchouk
a22ea0b82b Update scripts submodule to prevent electon-mocha crashes on CI
Change-type: patch
2020-02-04 20:08:51 +01:00
Alexis Svinartchouk
af64579eb2 Update resin-lint to ^3.2.0
Change-type: patch
2020-02-03 20:22:12 +01:00
Alexis Svinartchouk
f2705a611d Update mocha and electron-mocha
Change-type: patch
2020-02-03 20:22:12 +01:00
Alexis Svinartchouk
990dcc9d5a Fix loading driveBlacklist settings
Change-type: patch
2020-01-31 15:44:03 +01:00
Alexis Svinartchouk
c09237f0c3 Sort devices by device path on Linux
Changelog-entry: Sort devices by device path on Linux
Change-type: patch
2020-01-31 13:06:37 +01:00
Alexis Svinartchouk
571a3533fb Load settings before rendering the app
Change-type: patch
2020-01-30 16:59:29 +01:00
Alexis Svinartchouk
6fcd9e1595 Remove settings.getDefaults function
Change-type: patch
2020-01-30 16:59:28 +01:00
Alexis Svinartchouk
9caa42d257 Remove unused settings.assign function
Change-type: patch
2020-01-30 16:59:28 +01:00
Balena CI
18fdbbaabb v1.5.73 2020-01-29 15:56:45 +02:00
Alexis Svinartchouk
7381c1c0cb Merge pull request #3012 from balena-io/electron7
Electron7
2020-01-29 14:54:18 +01:00
Alexis Svinartchouk
2bdcae7209 Remove unused BUILD_TEMPORARY_DIRECTORY scripts parameter
Change-type: patch
2020-01-28 17:01:18 +01:00
Alexis Svinartchouk
fc694b90b6 Target es2018
Change-type: patch
2020-01-27 16:47:24 +01:00
Alexis Svinartchouk
945cd7ff8e Update electron to v7.1.10
Changelog-entry: Update electron to v7.1.10
Change-type: patch
2020-01-27 16:47:23 +01:00
Balena CI
3b32ca1e60 v1.5.72 2020-01-27 17:39:34 +02:00
Alexis Svinartchouk
98611267d5 Merge pull request #3026 from balena-io/remove-remaining-angular
Remove remaining angular and convert everything to typescript
2020-01-27 16:37:19 +01:00
Alexis Svinartchouk
4d53002e5c Replace use of lodash's assign with destructuring assignment in image-writer
Change-type: patch
2020-01-27 12:35:30 +01:00
Alexis Svinartchouk
f6b7b0d3d2 Fix error reportning when elevating Etcher fails
Change-type: patch
2020-01-27 12:35:29 +01:00
Alexis Svinartchouk
fbbd7ccf49 Remove babel dependency
Change-type: patch
2020-01-27 12:35:28 +01:00
Alexis Svinartchouk
d41ce65a78 Remove eslint dependency
Change-type: patch
2020-01-27 12:35:27 +01:00
Alexis Svinartchouk
c477fd2071 Remove mochainon dependency
Change-type: patch
2020-01-27 12:35:27 +01:00
Alexis Svinartchouk
7fab8395c8 Run ts-lint on typings
Change-type: patch
2020-01-27 12:35:27 +01:00
Alexis Svinartchouk
7d72e0c046 Convert clean-shrinkwrap.js to typescript
Change-type: patch
2020-01-27 12:35:26 +01:00
Alexis Svinartchouk
9ce97be6a4 Convert runner.spec.js to typescript
Change-type: patch
2020-01-27 12:35:26 +01:00
Alexis Svinartchouk
121b69b0c3 Convert available-drives.spec.ts to typescript
Change-type: patch
2020-01-27 12:35:25 +01:00
Alexis Svinartchouk
cb7cc2f276 Convert selection-state.spec.ts to typescript
Change-type: patch
2020-01-27 12:35:25 +01:00
Alexis Svinartchouk
d01849306e Convert errors.spec.js to typescript
Change-type: patch
2020-01-27 12:35:24 +01:00
Alexis Svinartchouk
a4e87982a6 Convert drive-constraints.spec.ts to typescript
Change-type: patch
2020-01-27 12:35:24 +01:00
Alexis Svinartchouk
e1c3c80c0f Convert supported-formats.spec.js to typescript
Change-type: patch
2020-01-27 12:35:23 +01:00
Alexis Svinartchouk
fd6346ed59 Convert utils.spec.js to typescript
Change-type: patch
2020-01-27 12:35:23 +01:00
Alexis Svinartchouk
2e4f7b5a8c Convert permissions.spec.js to typescript
Change-type: patch
2020-01-27 12:35:22 +01:00
Alexis Svinartchouk
d812d4e12e Convert flash-state.spec.js to typescript
Change-type: patch
2020-01-27 12:35:22 +01:00
Alexis Svinartchouk
10b3f09e7e Convert image-writer.spc.js to typescript
Change-type: patch
2020-01-27 12:35:21 +01:00
Alexis Svinartchouk
2d3776844c Convert child-writer.spec.js to typescript
Change-type: patch
2020-01-27 12:35:21 +01:00
Alexis Svinartchouk
914a4574de Convert progress-status.spec.js to typescript
Change-type: patch
2020-01-27 12:35:20 +01:00
Alexis Svinartchouk
2b3c84f21a Convert settings.spec.js to typescript
Change-type: patch
2020-01-27 12:35:20 +01:00
Alexis Svinartchouk
f4eb1af8d0 Convert windows-network-drives.spec.js to typescript
Change-type: patch
2020-01-27 12:35:19 +01:00
Alexis Svinartchouk
c01fc332d2 Convert window-progress.spec.js to typescript
Change-type: patch
2020-01-27 12:35:19 +01:00
Alexis Svinartchouk
b8fdbc3e94 Convert middle-ellipsis.spec.js to typescript
Change-type: patch
2020-01-27 12:35:18 +01:00
Alexis Svinartchouk
3c7c55364b Convert file-extensions.spc.js to typescript
Change-type: patch
2020-01-27 12:35:18 +01:00
Alexis Svinartchouk
bff4355a1a Convert messages.spec.js to typescript
Change-type: patch
2020-01-27 12:35:17 +01:00
Alexis Svinartchouk
9ea57a7df1 Convert units.spc.js to typescript
Change-type: patch
2020-01-27 12:35:17 +01:00
Alexis Svinartchouk
4c4171e7fb Remove no longer used prop-types
Change-type: patch
2020-01-27 12:35:16 +01:00
Alexis Svinartchouk
77ece044ad Replace <React.Fragment> with <>
Change-type: patch
2020-01-27 12:35:16 +01:00
Alexis Svinartchouk
d633b36b23 Remove useless export.
Change-type: patch
2020-01-27 12:35:15 +01:00
Alexis Svinartchouk
2eda6601c0 Remove remaining Promise.then
Change-type: patch
2020-01-27 12:35:15 +01:00
Alexis Svinartchouk
6202393637 Don't run eslint on lib, run ts-lint on webpack.config.ts
Change-type: patch
2020-01-27 12:35:14 +01:00
Alexis Svinartchouk
1b76044242 Convert image-selector.jsx to typescript
Change-type: patch
2020-01-27 12:35:14 +01:00
Alexis Svinartchouk
28648e27cf Convert DriveSelectorModal.jsx to typescript
Change-type: patch
2020-01-27 12:35:14 +01:00
Alexis Svinartchouk
90921a74ea Convert target-selector.jsx to typescript
Also fix showing the drive compatibility warnings

Change-type: patch
2020-01-27 12:35:13 +01:00
Alexis Svinartchouk
950b764ff1 Convert progress-button.jsx to typescript
Change-type: patch
2020-01-27 12:35:13 +01:00
Alexis Svinartchouk
15ba30bf8f Convert save-webview.jsx to typescript
Change-type: patch
2020-01-27 12:35:12 +01:00
Alexis Svinartchouk
c96654d50f Convert reduced-flashing-infos.jsx to typescript
Change-type: patch
2020-01-27 12:35:12 +01:00
Alexis Svinartchouk
b5f175d220 Convert svg-icon.jsx to typescript
Change-type: patch
2020-01-27 12:35:12 +01:00
Alexis Svinartchouk
c535543922 Convert featured-project.jsx to typescript
Change-type: patch
2020-01-27 12:35:11 +01:00
Alexis Svinartchouk
9913030e6f Remove eslint comments from tsx file
Change-type: patch
2020-01-27 12:35:11 +01:00
Alexis Svinartchouk
e7f58fc7fa Convert webpack.config.js to typescript
Change-type: patch
2020-01-27 12:35:10 +01:00
Alexis Svinartchouk
746ee50027 Convert start.js to typescript
Change-type: patch
2020-01-27 12:35:10 +01:00
Alexis Svinartchouk
683c2da224 Convert etcher.js to typescript
Change-type: patch
2020-01-27 12:35:10 +01:00
Alexis Svinartchouk
2671c83337 Use Dictionary type from lodash
Change-type: patch
2020-01-27 12:35:09 +01:00
Alexis Svinartchouk
bd35c89c04 Convert app.js to typescript
Change-type: patch
2020-01-27 12:35:09 +01:00
Alexis Svinartchouk
616baecafb Convert dialog.js to typescript
Changeètype: patch
2020-01-27 12:35:09 +01:00
Alexis Svinartchouk
bfe895c690 Convert image-writer.js to typescript
Change-type: patch
2020-01-27 12:35:08 +01:00
Alexis Svinartchouk
97aff2eb4c Convert child-writer.js to typescript
Change-type: patch
2020-01-21 17:54:17 +01:00
Alexis Svinartchouk
1c46ee2988 Convert flash-state.js to typescript
Change-type: patch
2020-01-21 17:54:15 +01:00
Alexis Svinartchouk
d0d4ee843d Convert selection-state.js to typescript
Change-type: patch
2020-01-21 17:54:14 +01:00
Alexis Svinartchouk
fd127da342 Convert available-drives.js to typescript
Change-type: patch
2020-01-21 17:54:12 +01:00
Alexis Svinartchouk
a8728336ca Convert store.js to typescript
Change-type: patch
2020-01-21 17:54:11 +01:00
Alexis Svinartchouk
c0eb9bd1e9 Convert settings.js to typescript
Change-type: patch
2020-01-21 17:54:10 +01:00
Alexis Svinartchouk
c85896845f Convert drive-constraints.js to typescript
Change-type: patch
2020-01-21 17:54:08 +01:00
Alexis Svinartchouk
efe953d8cd Convert permissions.js to typescript
Change-type: patch
2020-01-21 17:54:07 +01:00
Alexis Svinartchouk
b5593ef5b2 Convert utils.js to typescript
Change-type: patch
2020-01-21 17:54:05 +01:00
Alexis Svinartchouk
d08d2e00ee Convert messages.js to typescript
Change-type: patch
2020-01-21 17:54:04 +01:00
Alexis Svinartchouk
bc8908cca1 Convert units.js to typescript
Change-type: patch
2020-01-21 17:54:02 +01:00
Alexis Svinartchouk
9109f0ccd5 Convert errors.js to typescript
Change-type: patch
2020-01-21 17:54:01 +01:00
Alexis Svinartchouk
30c2ef58cd Convert supported-formats.js to typescript
Change-type: patch
2020-01-21 17:54:00 +01:00
Alexis Svinartchouk
23b295c7c1 Convert file-extensions.js to typescript
Change-type: patch
2020-01-21 17:53:58 +01:00
Alexis Svinartchouk
db24ee4d37 Convert catalina-sudo/sudo.js to typescript
Change-type: patch
2020-01-21 17:53:57 +01:00
Alexis Svinartchouk
e737a1edbd Convert exit-codes.js to typescript
Change-type: patch
2020-01-21 17:53:55 +01:00
Alexis Svinartchouk
109d84302c Remove no longer used storage.js and its tests
Change-type: patch
2020-01-21 17:53:54 +01:00
Alexis Svinartchouk
e50974a86a Convert local-settings.js to typescript
Change-type: patch
2020-01-21 17:53:53 +01:00
Alexis Svinartchouk
ef491e1e96 Remove no longer used lib/gui/app/models/files.js and its tests
Change-type: patch
2020-01-21 17:53:51 +01:00
Alexis Svinartchouk
f366a68159 Convert theme.js to typescript
Change-type: patch
2020-01-21 17:53:50 +01:00
Alexis Svinartchouk
0377faadd6 Convert drive-scanner.js to typescript
Change-type: patch
2020-01-21 17:53:48 +01:00
Alexis Svinartchouk
a5825373e1 Convert analytics.js to typescript
Change-type: patch
2020-01-21 17:53:47 +01:00
Alexis Svinartchouk
fadfadd9e9 Convert exception-reporter.js to typescript
Change-type: patch
2020-01-21 17:53:46 +01:00
Alexis Svinartchouk
596b316d65 Convert update-lock.js to typescript
Change-type: patch
2020-01-21 17:53:44 +01:00
Alexis Svinartchouk
c1e24406d9 Convert notification.js to typescript
Change-type: patch
2020-01-21 17:53:42 +01:00
Alexis Svinartchouk
13dfb090b5 Convert open-external.js to typescript
Change-type: patch
2020-01-21 17:53:41 +01:00
Alexis Svinartchouk
ddd1ff0101 Convert progress-status.js and window-progress.js to typescript
Change-type: patch
2020-01-21 17:53:39 +01:00
Alexis Svinartchouk
b266a72726 Convert window-network-drives.js to typescript
Change-type: patch
2020-01-21 17:53:37 +01:00
Alexis Svinartchouk
255fae3a90 Convert middle-ellipsis.js to typescript
Change-type: patch
2020-01-21 17:53:35 +01:00
Alexis Svinartchouk
b4a60cfee2 Remove unused styled-components.js
Change-type: patch
2020-01-21 17:53:34 +01:00
Alexis Svinartchouk
233a2e6400 Convert menu.js to typescript
Change-type: patch
2020-01-21 17:53:32 +01:00
Alexis Svinartchouk
f31cb49e2a Don't use prop-types in drive selector
Change-type: patch
2020-01-21 17:53:31 +01:00
Alexis Svinartchouk
47fd12e7a4 Remove html-angular-validate
Change-type: patch
2020-01-21 17:53:29 +01:00
Alexis Svinartchouk
d5eb679cf0 Remove remaining angular
Change-type: patch
2020-01-21 17:53:28 +01:00
Alexis Svinartchouk
26d0e46367 Convert angular SafeWebview to typescript
Change-type: patch
2020-01-21 17:53:26 +01:00
Alexis Svinartchouk
146bfaa9de Remove unused StateController.previousName
Change-type: patch
2020-01-21 17:53:25 +01:00
Alexis Svinartchouk
315051c14c Remove useless 'use strict' from a ts file
Change-type: patch
2020-01-21 17:53:23 +01:00
Alexis Svinartchouk
3a7d770f6d Remove no longer used angular flash-another component
Change-type: patch
2020-01-21 17:53:22 +01:00
Alexis Svinartchouk
2cd60af841 Remove no longer used angular flash-results component
Change-type: patch
2020-01-21 17:53:21 +01:00
Alexis Svinartchouk
e2f5775b07 Remove no longer needed angular specific utils.memoize
Change-type: patch
2020-01-21 17:53:19 +01:00
Alexis Svinartchouk
c27be733a9 Remove no longer used angular-ui-bootstrap
Change-type: patch
2020-01-21 17:53:18 +01:00
Alexis Svinartchouk
54fda697ce Remove no longer used .section-footer-main css rules
Change-type: patch
2020-01-21 17:53:16 +01:00
Alexis Svinartchouk
04e0b56dd5 Remove no longer used angular svg-icon component
Changelog-entry: Remove no longer used angular svg-icon component
Change-type: patch
2020-01-21 17:53:15 +01:00
Alexis Svinartchouk
b71824c5e8 Remove no longer used angular-if-state
Change-type: patch
2020-01-21 17:53:13 +01:00
Alexis Svinartchouk
65293ea5e4 Remove no longer used ModalService
Change-type: patch
2020-01-21 17:53:12 +01:00
Alexis Svinartchouk
05c2f5bebd Remove no longer used closestUnit angular filter
Changelog-entry: Remove no longer used closestUnit angular filter
Change-type: patch
2020-01-21 17:53:09 +01:00
Lorenzo Alberto Maria Ambrosi
e8b2255be0 Merge pull request #3035 from balena-io/trigger-update-1.5.71
Trigger update for 1.5.71
2020-01-17 16:36:40 +01:00
Lorenzo Alberto Maria Ambrosi
2c227d3475 Trigger update for 1.5.71
Change-type: none
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2020-01-17 12:11:01 +01:00
Balena CI
958f7b535a v1.5.71 2020-01-14 18:17:04 +02:00
Lorenzo Alberto Maria Ambrosi
9e34096139 Merge pull request #3024 from balena-io/update-resin-corvus
Update resin-corvus to 2.0.5
2020-01-14 17:15:04 +01:00
Alexis Svinartchouk
12b5536e22 Don't webpack package.json as analytics tokens are interted after webpacking
Change-type: patch
2020-01-14 15:11:44 +01:00
Lorenzo Alberto Maria Ambrosi
171a5b1793 Update scripts submodule
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2020-01-13 21:50:11 +01:00
Lorenzo Alberto Maria Ambrosi
b4fb82066b Update resin-corvus to 2.0.5
Change-type: patch
Changelog-entry: Update resin-corvus to 2.0.5
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2020-01-13 21:36:54 +01:00
Balena CI
57145436ab v1.5.70 2019-12-13 20:27:43 +02:00
Lorenzo Alberto Maria Ambrosi
cba69ca467 Merge pull request #2987 from balena-io/remove-angular
Remove angular
2019-12-13 19:25:52 +01:00
Alexis Svinartchouk
375fcab788 Remove no longer used HeaderController
Change-type: patch
2019-12-13 12:28:23 +01:00
Lorenzo Alberto Maria Ambrosi
de65c02222 Make header draggable again
Change-type: patch
Changelog-entry: Make header draggable again
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-12-12 18:25:56 +01:00
Lorenzo Alberto Maria Ambrosi
444b0beaca Refactor drive selector and confirm modal to React
Change-type: patch
Changelog-entry: Refactor drive selector and confirm modal to React
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-12-12 18:25:56 +01:00
Alexis Svinartchouk
4c931278b8 Remove angular os-open-external directive
Change-type: patch
2019-12-12 18:25:55 +01:00
Alexis Svinartchouk
3bdac794b3 React header
Change-type: patch
2019-12-12 18:25:55 +01:00
Alexis Svinartchouk
67eb593164 Remove manifest-bind
Change-type: patch
2019-12-12 18:25:54 +01:00
Alexis Svinartchouk
fe230e7d30 Rename resin -> balena
Change-type: patch
2019-12-12 18:25:54 +01:00
Alexis Svinartchouk
2f0ce3ee37 Only run prettier on ts and tsx files 2019-12-12 18:25:53 +01:00
Stevche Radevski
992b8a6fb6 Fix layout when flashing
Change-type: patch
Signed-off-by: Stevche Radevski <stevche@balena.io>
2019-12-12 18:25:53 +01:00
Alexis Svinartchouk
84e45caa6c Rework lib/gui/app/styled-components to typescript
Change-type: patch
Changelog-entry: Rework lib/gui/app/styled-components to typescript
2019-12-12 18:25:52 +01:00
Lorenzo Alberto Maria Ambrosi
68d9542816 Convert FlashAnother & FlashResults to typescript
Change-type: patch
Changelog-entry: Convert FlashAnother & FlashResults to typescript
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-12-12 18:25:52 +01:00
Lorenzo Alberto Maria Ambrosi
c9c9c50d6c Rework finish page with React
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-12-12 18:25:51 +01:00
Stevche Radevski
9f4e0ce920 Add husky and lint-staged to run linting on commit
Change-type: patch
Signed-off-by: Stevche Radevski <stevche@balena.io>
2019-12-12 18:25:51 +01:00
Stevche Radevski
388852d6b7 Move a couple of files to typescript and remove unnecessary $timeout
Change-type: patch
Signed-off-by: Stevche Radevski <stevche@balena.io>
2019-12-12 18:25:51 +01:00
Stevche Radevski
4e1f071951 Change Flash and Driveselector extension to .tsx
This is so the git history is preserved for the file

Change-type: patch
Signed-off-by: Stevche Radevski <stevche@balena.io>
2019-12-12 18:25:50 +01:00
Stevche Radevski
8e47829905 Move the main controller to React
Change-type: patch
Signed-off-by: Stevche Radevski <stevche@balena.io>
2019-12-12 18:25:43 +01:00
Alexis Svinartchouk
84fe5004a9 Remove broken settings shortcut from menu
Change-type: patch
2019-12-12 18:09:19 +01:00
Alexis Svinartchouk
28b51a9b46 Remove unused imports in main.js
Change-type: patch
2019-12-12 18:09:18 +01:00
Alexis Svinartchouk
07fc7af911 Remove experimental file picker
Change-type: patch
2019-12-12 18:09:18 +01:00
Alexis Svinartchouk
330405ae42 Remove tooltip-modal scss import
Change-type: patch
2019-12-12 18:09:17 +01:00
Lucian
ffb26ba67f Remove unused methods from drive selector component
Signed-off-by: Lucian <lucian.buzzo@gmail.com>
2019-12-12 18:09:17 +01:00
Lucian
fc597abbc9 Add sourcemap and elevate theme provider
Signed-off-by: Lucian <lucian.buzzo@gmail.com>
2019-12-12 18:09:16 +01:00
Lucian
177f10f76d Refactor tooltip modal to use react
Signed-off-by: Lucian <lucian.buzzo@gmail.com>
2019-12-12 18:09:16 +01:00
Lucian
a7a7f83e3e Fix link hover color
Signed-off-by: Lucian <lucian.buzzo@gmail.com>
2019-12-12 18:09:15 +01:00
Lucian
b6fb44d6a5 Fix bug where images can't be reselected
Signed-off-by: Lucian <lucian.buzzo@gmail.com>
2019-12-12 18:09:15 +01:00
Alexis Svinartchouk
996c2b55a4 Run make sass
Change-type: patch
2019-12-12 18:09:14 +01:00
Stevche Radevski
21d9d31a27 Use rendition modal for warning and errors when flashing
Change-type: patch
Signed-off-by: Stevche Radevski <stevche@balena.io>
2019-12-12 18:09:05 +01:00
Lucian
00536cba3a Refactor Warning modal in image selection 2019-12-10 12:35:42 +01:00
Lucian
641dde81e5 Refactor image-selection
Change-type: patch
Changelog-entry: Use React instead of Angular for image selection
Signed-off-by: Lucian <lucian.buzzo@gmail.com>
2019-12-10 12:35:42 +01:00
Thodoris Greasidis
8177e98014 Refactor the DriveSelector to use async-await
Change-type: patch
Signed-off-by: Thodoris Greasidis <thodoris@balena.io>
2019-12-10 12:35:42 +01:00
Thodoris Greasidis
abfc6be84d Convert the drive selection step to React
Change-type: patch
Changelog-entry: Convert the drive selection step to React
Signed-off-by: Thodoris Greasidis <thodoris@balena.io>
2019-12-10 12:35:42 +01:00
Stevche Radevski
1d15d582d9 chore: move flash step to React
Changelog-entry: chore: move flash step to React
Change-type: patch
Signed-off-by: Stevche Radevski <stevche@balena.io>
2019-12-10 12:35:42 +01:00
Lucian
5cd3c5fcc0 Refactor image-selection
Change-type: patch
Changelog-entry: Use React instead of Angular for image selection
Signed-off-by: Lucian <lucian.buzzo@gmail.com>
2019-12-10 12:35:42 +01:00
Balena CI
5e568d7dd8 v1.5.69 2019-12-10 13:35:21 +02:00
Alexis Svinartchouk
c251bce44d Merge pull request #3007 from balena-io/fix-appimage
Don't add --no-sandbox when ELECTRON_RUN_AS_NODE is 1
Fixes #2996
2019-12-10 12:33:28 +01:00
Alexis Svinartchouk
1408dd48a1 Don't add --no-sandbox when ELECTRON_RUN_AS_NODE true
Changelog-entry: Don't add --no-sandbox when ELECTRON_RUN_AS_NODE true
Change-type: patch
2019-12-10 11:04:01 +01:00
Balena CI
a77734797a v1.5.68 2019-12-09 11:44:03 +02:00
Lorenzo Alberto Maria Ambrosi
a119ae7efa Merge pull request #3005 from balena-io/add-version-settings
Add version in settings modal
2019-12-09 10:41:53 +01:00
Lorenzo Alberto Maria Ambrosi
7d284a7e18 Add version in settings modal
Change-type: patch
Changelog-entry: Add version in settings modal
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-12-08 17:25:11 +01:00
Balena CI
4d65bd9f1b v1.5.67 2019-12-06 13:50:04 +02:00
Alexis Svinartchouk
517511e5be Merge pull request #3000 from balena-io/fix-macos-elevation-in-development
Fix elevation on macos in development
2019-12-06 12:48:17 +01:00
Alexis Svinartchouk
2ef38fe06d Fix elevation on macos in development
Changelog-entry: Fix elevation on macos in development
Change-type: patch
2019-12-06 01:25:24 +01:00
Balena CI
b128d36121 v1.5.66 2019-12-03 18:30:04 +02:00
Alexis Svinartchouk
082025f0b6 Merge pull request #2932 from balena-io/electron6
Electron6
2019-12-03 17:28:09 +01:00
Alexis Svinartchouk
220b7f6d53 Remove usage of deprecated componentWillReceiveProps
Change-type: patch
2019-12-03 15:41:33 +01:00
Alexis Svinartchouk
062723bf15 Fix typing in settings.tsx
Change-type: patch
2019-12-03 15:35:52 +01:00
Alexis Svinartchouk
bcbbb64042 Update dependencies after rebase
Change-type: patch
2019-12-03 15:35:52 +01:00
Alexis Svinartchouk
59230a0f9e Fix windows elevation module import
Change-type: patch
2019-12-03 13:48:47 +01:00
Alexis Svinartchouk
18fb9c9de3 Package dll files (needed for lzma_native on windows)
Change-type: patch
2019-12-03 13:48:47 +01:00
Alexis Svinartchouk
26e827e4dc Update electron to 6.1.4
Change-type: patch
2019-12-03 13:48:47 +01:00
Alexis Svinartchouk
2f828b1d39 Wrapper script for linux to add --no-sandbox when running as root
Change-type: patch
2019-12-03 13:45:11 +01:00
Alexis Svinartchouk
5b22fcc2f5 Remove unused script
Change-type: patch
2019-12-03 13:45:11 +01:00
Alexis Svinartchouk
4f36b00ec3 Simplify webpack config
Change-type: patch
2019-12-03 13:45:11 +01:00
Alexis Svinartchouk
707c20513e Simplify electron-builder files config
Change-type: patch
2019-12-03 13:45:11 +01:00
Alexis Svinartchouk
cddd068887 Update spectron to ^8
Changelog-entry: Update spectron to ^8
Change-type: patch
2019-12-03 13:45:11 +01:00
Alexis Svinartchouk
cf6863b2c6 Update dependencies, get node-usb from npm
Changelog-entry: Update dependencies, get node-usb from npm
Change-type: patch
2019-12-03 13:45:11 +01:00
Alexis Svinartchouk
994d311ed3 Update nan to ^2.14
Changelog-entry: Update nan to ^2.14
Change-type: patch
2019-12-03 13:23:45 +01:00
Alexis Svinartchouk
1098f8cb1e Use the same entrypoint for etcher and the child writer
Changelog-entry: Use the same entrypoint for etcher and the child writer
Change-type: patch
2019-12-03 13:23:45 +01:00
Alexis Svinartchouk
1be1a2b8f7 Require angular-mocks only when needed
Changelog-entry: Require angular-mocks only when needed
Change-type: patch
2019-12-03 13:23:45 +01:00
Alexis Svinartchouk
07a6e40917 Remove no longer needed pkg dev dependency
Changelog-entry: Remove no longer needed pkg dev dependency
Change-type: patch
2019-12-03 13:09:58 +01:00
Alexis Svinartchouk
2c2057b5cb Update mocha, remove nock
Changelog-entry: Update mocha, remove nock
Change-type: patch
2019-12-03 13:09:24 +01:00
Alexis Svinartchouk
caf09e7498 Remove no longer needed xml2js
Changelog-entry: Remove no longer needed xml2js
Change-type: patch
2019-12-03 13:09:24 +01:00
Alexis Svinartchouk
9488468b67 Remove node-pre-gyp patch that is no longer needed with electron 6
Changelog-entry: Remove node-pre-gyp patch that is no longer needed with electron 6
Change-type: patch
2019-12-03 13:09:24 +01:00
Alexis Svinartchouk
d071bf8ade Update electron-mocha to ^8.1.2, remove acorn
Changelog-entry: Update electron-mocha to ^8.1.2, remove acorn
Change-type: patch
2019-12-03 13:09:24 +01:00
Alexis Svinartchouk
1626c01ff4 Update electron to 6.0.10
Change-type: patch
Changelog-entry: Update electron to 6.0.10
2019-12-03 13:09:24 +01:00
Balena CI
3dd6895662 v1.5.65 2019-12-03 12:08:43 +02:00
Lorenzo Alberto Maria Ambrosi
0ab967b7a4 Merge pull request #2965 from balena-io/revamp-settings
Refactor settings page into modal
2019-12-03 11:06:43 +01:00
Lorenzo Alberto Maria Ambrosi
3b07946065 Convert settings modal to typescript
Change-type: patch
Changelog-entry: Convert settings modal to typescript
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-12-02 16:26:52 +01:00
Lorenzo Alberto Maria Ambrosi
4c0a079d1e Refactor settings page into modal
Change-type: patch
Changelog-entry: Refactor settings page into modal
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-12-02 16:26:52 +01:00
Balena CI
1878b39e21 v1.5.64 2019-11-27 16:11:49 +02:00
Alexis Svinartchouk
7050111bf4 Merge pull request #2973 from balena-io/use-bash
Use bash instead of sh for running the elevated process on Linux and Mac
2019-11-27 15:09:43 +01:00
Alexis Svinartchouk
572f7d826a Use bash instead of sh for running the elevated process on Linux and Mac
Change-type: patch
Changelog-entry: Use bash instead of sh for running the elevated process on Linux and Mac
2019-11-22 15:45:27 +01:00
Balena CI
a155811678 v1.5.63 2019-11-08 15:02:17 +02:00
Dimitrios Lytras
54ccee3c0f Merge pull request #2964 from balena-io/add-faq
docs: Introduce an FAQ file
2019-11-08 15:00:13 +02:00
Dimitrios Lytras
88b7665b7f docs: Introduce an FAQ file
Much needed file in order to generate the FAQ section for the website using Landr

Changelog-entry: Introduce an FAQ file
Change-type: patch
Signed-off-by: Dimitrios Lytras dnlytras@gmail.com
2019-11-08 13:31:45 +02:00
Balena CI
a66007f8cc v1.5.62 2019-11-06 19:38:02 +02:00
Alexis Svinartchouk
d5f348c039 Merge pull request #2963 from balena-io/update-drivelist
Update drivelist to 8.0.9
2019-11-06 18:35:42 +01:00
Alexis Svinartchouk
c0d1899ad3 Update drivelist to 8.0.9
Changelog-entry: Update drivelist to 8.0.9
Change-type: patch
2019-11-06 17:20:24 +01:00
Balena CI
ea14ef6314 v1.5.61 2019-11-06 04:04:10 +02:00
Alexis Svinartchouk
75e6f1e39a Merge pull request #2939 from balena-io/update-macos-catalina
Make Etcher work on macOS Catalina
2019-11-06 02:55:46 +01:00
Alexis Svinartchouk
f372fba1fd Don't use electron-is-running-in-asar, fix AppImage builds
Change-type: patch
2019-11-05 18:36:01 +01:00
Alexis Svinartchouk
d494cee0da Don't spell check scripts
Change-type: patch
2019-11-05 18:36:01 +01:00
Alexis Svinartchouk
1b8380c5dc Update scripts repo as electron-builder's build command was renamed electron-builder
Change-type: patch
2019-11-05 18:36:01 +01:00
Alexis Svinartchouk
1ee2eb05eb Update electron-builder to ^22
Change-type: patch
2019-11-05 00:49:15 +01:00
Alexis Svinartchouk
9b82891abb Use sudo instead of sudo-prompt on macOS >= Catalina
Change-type: patch
2019-11-05 00:49:15 +01:00
Alexis Svinartchouk
64a28f891f Don't pack files in an asar archive on macOS
Change-type: patch
2019-11-05 00:49:15 +01:00
Lorenzo Alberto Maria Ambrosi
c4944f31d6 Notarize app on macOS
Change-type: patch
Changelog-entry: Notarize app on macOS
2019-11-04 14:47:56 +01:00
Balena CI
6fd696546c v1.5.60 2019-10-18 14:33:17 +03:00
Alexis Svinartchouk
e957dab993 Merge pull request #2937 from balena-io/ext2fs-1.0.30
ext2fs: upgrade ext2fs to 1.0.30
2019-10-18 13:31:03 +02:00
Matthew McGinn
831e7af9ed ext2fs: upgrade ext2fs to 1.0.30
Changelog-entry: Upgrade ext2fs to 1.0.30
Change-type: patch
Signed-off-by: Matthew McGinn <matthew@balena.io>
2019-10-18 10:45:05 +02:00
Balena CI
8ab779ffb9 v1.5.59 2019-10-14 16:36:42 +03:00
Alexis Svinartchouk
506f9bf0e0 Merge pull request #2931 from balena-io/roman/debugging
Catch console log messages from SafeWebView
2019-10-14 15:34:13 +02:00
Roman Mazur
5151d751a3 Catch console log messages from SafeWebView
This simplifies debugging of the content loaded by Etcher,
including analysis of loaded analytics libraries.

Changelog-entry: Catch console log messages from SafeWebView
Change-type: patch
Signed-off-by: Roman Mazur <roman@balena.io>
2019-10-14 13:46:44 +03:00
Balena CI
bde9a97b17 v1.5.58 2019-10-10 13:09:09 +03:00
Dimitrios Lytras
cede823a33 docs: Remove leftover GH-pages configuration file (#2923)
docs: Remove leftover GH-pages configuration file
2019-10-10 13:06:53 +03:00
Dimitrios Lytras
dda2f6eb70 docs: Remove leftover GH-pages configuration file
Changelog-entry: Remove leftover GH-pages configuration file
Change-type: patch
Signed-off-by: Dimitrios Lytras dnlytras@gmail.com
2019-10-10 12:21:40 +03:00
Balena CI
c54f2e08c2 v1.5.57 2019-09-17 16:25:19 +03:00
Alexis Svinartchouk
2a2e025ef7 Merge pull request #2906 from balena-io/fix-entrypoint
Fix entrypoint when options are passed to electron
2019-09-17 15:23:42 +02:00
Alexis Svinartchouk
93ea4efb33 Fix entrypoint when options are passed to electron
Change-type: patch
Changelog-entry: Fix entrypoint when options are passed to electron
2019-09-17 00:32:32 +02:00
Resin CI
284301a659 v1.5.56 2019-08-20 17:43:38 +03:00
Lorenzo Alberto Maria Ambrosi
8425dd9aa7 Merge pull request #2885 from balena-io/fix-win-download
Fix windows portable download
2019-08-20 16:41:50 +02:00
Lorenzo Alberto Maria Ambrosi
02bd8ed459 Fix windows portable download
Change-type: patch
Changelog-entry: Fix windows portable download
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-08-20 15:41:27 +02:00
Resin CI
25a7cf18cf v1.5.55 2019-08-20 14:23:35 +03:00
Alexis Svinartchouk
003929754d Merge pull request #2883 from balena-io/update-etcher-sdk
Update etcher-sdk to ^2.0.13
2019-08-20 13:21:42 +02:00
Alexis Svinartchouk
f6c0172257 Update etcher-sdk to ^2.0.13
Change-type: patch
Changelog-entry: Update etcher-sdk to ^2.0.13
2019-08-19 17:25:58 +02:00
Resin CI
75be3a3778 v1.5.54 2019-08-19 14:08:36 +03:00
Lorenzo Alberto Maria Ambrosi
5cfb95e8ea Merge pull request #2875 from balena-io/fix-auto-updater
Fix auto updater
2019-08-19 13:06:39 +02:00
Lorenzo Alberto Maria Ambrosi
8c2c4e233a Fix auto-updater check for updates
Change-type: patch
Changelog-entry: Fix auto-updater check for updates
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-08-07 18:43:16 +02:00
Resin CI
f4ac4dee60 v1.5.53 2019-08-06 15:45:22 +03:00
Lorenzo Alberto Maria Ambrosi
1b4053d959 Merge pull request #2864 from balena-io/add-typescript-2
Allow typescript files
2019-08-06 14:43:25 +02:00
Lorenzo Alberto Maria Ambrosi
8df5d972fc Allow typescript files
Change-type: patch
Changelog-entry: Allow typescript files
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-08-05 16:31:50 +02:00
Lorenzo Alberto Maria Ambrosi
3a68d84376 Merge pull request #2863 from balena-io/trigger-update-1.5.52
Trigger update for 1.5.52
2019-07-31 13:01:09 +02:00
Lorenzo Alberto Maria Ambrosi
865ea0ddd2 Trigger update for 1.5.52
Change-type: none
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-07-24 10:19:42 +02:00
Resin CI
54dca31d66 v1.5.52 2019-07-23 15:59:09 +03:00
Alexis Svinartchouk
17103570f1 Merge pull request #2862 from balena-io/fix-windows-mapped-network-drives-vmware
Don't use wmic's ProviderName if it's empty
2019-07-23 14:56:47 +02:00
Alexis Svinartchouk
b5d04a2031 Don't use wmic's ProviderName if it's empty
Changelog-entry: Don't use wmic's ProviderName if it's empty
Change-type: patch
2019-07-22 19:40:01 +02:00
Resin CI
86238af380 v1.5.51 2019-06-28 16:04:34 +03:00
Alexis Svinartchouk
d10073a052 Merge pull request #2842 from balena-io/update-sudo-prompt
Update sudo-prompt to ^9.0.0
2019-06-28 15:02:51 +02:00
Alexis Svinartchouk
b99b0d4bf8 Update sudo-prompt to ^9.0.0
Change-type: patch
Changelog-entry: Update sudo-prompt to ^9.0.0
2019-06-28 14:00:49 +02:00
Resin CI
27b5b1bf10 v1.5.50 2019-06-14 16:43:18 +03:00
Alexis Svinartchouk
bab9069dee Merge pull request #2702 from balena-io/trim
Trim
2019-06-14 15:41:29 +02:00
Alexis Svinartchouk
52a3258814 Option for trimming ext partitions on raw images
Changelog-entry: Option for trimming ext partitions on raw images
Change-type: patch
2019-06-13 20:00:20 +02:00
Alexis Svinartchouk
da548f59d1 Replace promise chains with async/await in child-writer
Change-type: patch
2019-06-13 18:42:41 +02:00
Resin CI
ecc500907c v1.5.49 2019-06-13 19:42:18 +03:00
Alexis Svinartchouk
724dade1f6 Merge pull request #2830 from balena-io/etcher-pro
Make window size configurable
2019-06-13 18:39:30 +02:00
Alexis Svinartchouk
c5dc869c03 Make window size configurable
Change-type: patch
Changelog-entry: Make window size configurable
2019-06-13 17:23:49 +02:00
Resin CI
273f7e4535 v1.5.48 2019-06-13 17:30:09 +03:00
Alexis Svinartchouk
a58e060138 Merge pull request #2829 from balena-io/dont-elevate-when-root
Don't use sudo-prompt when already elevated
2019-06-13 16:26:48 +02:00
Alexis Svinartchouk
ef4d2fcc72 Don't use sudo-prompt when already elevated
Changelog-entry: Don't use sudo-prompt when already elevated
Change-type: patch
2019-06-13 15:22:10 +02:00
Resin CI
330c06d926 v1.5.47 2019-06-12 16:30:52 +03:00
Lorenzo Alberto Maria Ambrosi
be9c36828a Merge pull request #2795 from balena-io/bump-styled-components-system
Upgrade rendition to v8
2019-06-12 15:28:08 +02:00
Lorenzo Alberto Maria Ambrosi
17f83135c5 Rework drive-selector with react + rendition
Change-type: patch
Changelog-entry: Rework drive-selector with react + rendition
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-06-10 11:43:47 +02:00
Lorenzo Alberto Maria Ambrosi
543ba51d3c Add first rendition theme configs
Change-type: patch
Changelog-entry: Use rendition theme property for step buttons
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-06-10 11:43:47 +02:00
Lorenzo Alberto Maria Ambrosi
33df23fc8c Upgrade styled-system to v4.1.0
Change-type: patch
Changelog-entry: Upgrade styled-system to v4.1.0
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-06-10 11:43:47 +02:00
Lorenzo Alberto Maria Ambrosi
3236d6b934 Upgrade rendition to v8.7.2
Change-type: patch
Changelog-entry: Upgrade rendition to v8.7.2
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-06-10 11:43:47 +02:00
Resin CI
e0e7775367 v1.5.46 2019-06-09 17:09:46 +03:00
Alexis Svinartchouk
198679583c Merge pull request #2827 from balena-io/update-ext2fs
Update ext2fs to 1.0.29
2019-06-09 16:07:37 +02:00
Alexis Svinartchouk
6dae2a604f Update ext2fs to 1.0.29
Change-type: patch
Changelog-entry: Update ext2fs to 1.0.29
2019-06-09 14:18:17 +02:00
Resin CI
68905c6ae4 v1.5.45 2019-06-04 12:58:44 +03:00
Alexis Svinartchouk
26630c4d64 Merge pull request #2823 from balena-io/trigger-build
Empty commit to trigger build
2019-06-04 11:56:24 +02:00
Alexis Svinartchouk
d382f030f0 Empty commit to trigger build
Change-type: patch
Changelog-entry: Empty commit to trigger build
2019-06-04 10:59:01 +02:00
Resin CI
08fca87b2f v1.5.44 2019-06-03 21:16:49 +03:00
Alexis Svinartchouk
33441a1c5c Merge pull request #2803 from balena-io/fix-windows-elevation
Fix elevation on windows when the path contains "&" or "'"
2019-06-03 20:14:45 +02:00
Alexis Svinartchouk
6d8346b13a Fix elevation on windows when the path contains "&" or "'"
Change-type: patch
Changelog-entry: Fix elevation on windows when the path contains "&" or "'"
2019-05-29 17:52:01 +02:00
Resin CI
d9b340ca45 v1.5.43 2019-05-28 21:59:10 +03:00
Lorenzo Alberto Maria Ambrosi
ebbc52ee1f Merge pull request #2806 from balena-io/rollback-update-webpack
Rollback update webpack
2019-05-28 20:57:06 +02:00
Lorenzo Alberto Maria Ambrosi
de5bee29ef Revert "Include sass in webpack configs"
This reverts commit 156c25cea1.

Change-type: patch
Changelog-entry: Revert "Include sass in webpack configs"
2019-05-28 19:34:12 +02:00
Resin CI
25f843ec0b v1.5.42 2019-05-28 17:41:14 +03:00
Lorenzo Alberto Maria Ambrosi
df600a9e14 Merge pull request #2794 from balena-io/update-webpack
Add sass-loader to webpack configs
2019-05-28 16:38:55 +02:00
Lorenzo Alberto Maria Ambrosi
156c25cea1 Include sass in webpack configs
Change-type: patch
Changelog-entry: Include sass in webpack configs
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-05-28 11:08:54 +02:00
Resin CI
f7dd04e3de v1.5.41 2019-05-27 16:59:31 +03:00
Alexis Svinartchouk
3036d86cfa Merge pull request #2801 from mhajder/patch-1
waffle.io removal and adding a link to the license
2019-05-27 15:57:19 +02:00
Mateusz Hajder
3fccd52884 waffle.io removal and adding a link to the license
Change-type: patch
Changelog-entry: waffle.io removal and adding a link to the license
2019-05-27 14:56:17 +02:00
Resin CI
00640274fc v1.5.40 2019-05-27 13:16:18 +03:00
Lorenzo Alberto Maria Ambrosi
a7e8fb98b3 Merge pull request #2799 from balena-io/combine-ia32-and-x64-2
Combine ia32 and x64 2
2019-05-27 12:14:09 +02:00
Alexis Svinartchouk
bed6643437 Remove some unused files from the packages
Change-type: patch
2019-05-24 11:26:45 +02:00
Alexis Svinartchouk
f815e8511f Build packages that support both ia32 and x64 on windows
Changelog-entry: windows installer and portable version support both ia32 and x64
Change-type: patch
2019-05-21 18:02:06 +02:00
Resin CI
6360fd42e7 v1.5.39 2019-05-14 13:27:35 +03:00
Lorenzo Alberto Maria Ambrosi
62a9656888 Merge pull request #2768 from balena-io/clean-shrinkwrap
Add clean-shrinkwrap script to postshrinkwrap step
2019-05-14 12:25:05 +02:00
Lorenzo Alberto Maria Ambrosi
ffb89c7e5b Update scripts submodule to v1.5.2
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-05-14 09:39:48 +02:00
Lorenzo Alberto Maria Ambrosi
aa52735006 Add clean-shrinkwrap script to postshrinkwrap step
Change-type: patch
Changelog-entry: Add clean-shrinkwrap script to postshrinkwrap step
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-05-14 09:39:48 +02:00
Resin CI
b65526d8ee v1.5.38 2019-05-14 01:47:31 +03:00
Carlo Maria Curinga
ea8e2999ae Merge pull request #2786 from balena-io/add-mention-to-usbboot-devices
add mention to usbboot devices support
2019-05-14 00:45:00 +02:00
Carlo Maria Curinga
0b5017f992 add mention to usbboot devices support
Change-type: patch
Changelog-entry: Add mention to usbboot compatibility
Signed-off-by: Carlo Maria Curinga carlo@balena.io
2019-05-13 23:38:13 +02:00
Resin CI
8bf1bdaa04 v1.5.37 2019-05-13 20:53:18 +03:00
Lorenzo Alberto Maria Ambrosi
01eb3b1c94 Merge pull request #2783 from balena-io/bump-react
Bump react to v16.8.5
2019-05-13 19:51:00 +02:00
Lorenzo Alberto Maria Ambrosi
3402c9f601 Bump react to v16.8.5
Change-type: patch
Changelog-entry: Bump react dependency to v16.8.5
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-05-13 15:09:23 +02:00
Resin CI
13c3518c5e v1.5.36 2019-05-13 15:35:11 +03:00
Alexis Svinartchouk
821fad27dc Merge pull request #2782 from balena-io/sdk-2.0.9
Update etcher-sdk to ^2.0.9
2019-05-13 14:32:51 +02:00
Alexis Svinartchouk
50a34e2f4c Update etcher-sdk to ^2.0.9
Changelog-entry: Update etcher-sdk to ^2.0.9
Change-type: patch
2019-05-13 12:51:39 +02:00
Resin CI
2a19b2afbe v1.5.35 2019-05-10 20:29:42 +03:00
Alexis Svinartchouk
dc92d010fb Merge pull request #2775 from balena-io/electron-3.1.9
Downgrade electron 4.1.5 -> 3.1.9
2019-05-10 19:27:31 +02:00
Alexis Svinartchouk
9cb27a616a Downgrade electron 4.1.5 -> 3.1.9
Changelog-entry: Downgrade electron 4.1.5 -> 3.1.9
Change-type: patch
2019-05-10 14:18:33 +02:00
Resin CI
518a0ca45b v1.5.34 2019-05-10 13:21:12 +03:00
Alexis Svinartchouk
3526a0e3c5 Merge pull request #2774 from balena-io/1.5.34
1.5.34
2019-05-10 12:19:17 +02:00
Alexis Svinartchouk
6386f85258 Use https url for fetching config, avoid redirection
Changelog-entry: Use https url for fetching config, avoid redirection
Change-type: patch
2019-05-09 16:01:36 +02:00
Alexis Svinartchouk
e80106d8f8 Update etcher-sdk to ^2.0.7
Changelog-entry: win32: fix running diskpart when the tmp file path contains spaces
Change-type: patch
2019-05-09 15:58:40 +02:00
Resin CI
1145cbc75c v1.5.33 2019-04-30 22:17:08 +03:00
Alexis Svinartchouk
e669b81072 Merge pull request #2759 from balena-io/fix-gzip-progress
Update etcher-sdk to ^2.0.5
2019-04-30 21:14:26 +02:00
Alexis Svinartchouk
9d78da941b Update etcher-sdk to ^2.0.5
Changelog-entry: Fix gzipped files verification percentage and dmg verification.
Change-type: patch
2019-04-30 18:38:35 +02:00
Resin CI
63d0f5e2c6 v1.5.32 2019-04-30 19:05:05 +03:00
Alexis Svinartchouk
dae047eff1 Merge pull request #2758 from balena-io/makefile-npm-version
Export NPM_VERSION variable in Makefile
2019-04-30 18:03:21 +02:00
Lorenzo Alberto Maria Ambrosi
8a2db8bced Add CODEOWNERS file to repository
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-04-30 16:56:44 +02:00
Lorenzo Alberto Maria Ambrosi
792fab20e6 Export NPM_VERSION variable in Makefile
Change-type: patch
Changelog-entry: Export NPM_VERSION variable in Makefile
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-04-30 16:14:26 +02:00
Resin CI
f40c0f6bd3 v1.5.31 2019-04-30 13:55:10 +03:00
Alexis Svinartchouk
ccf11b9861 Merge pull request #2753 from balena-io/electron-4
Update electron to 4.1.5
2019-04-30 12:52:46 +02:00
Alexis Svinartchouk
1fcde5a17c Update etcher-sdk to ^2.0.3
Changelog-entry: Update etcher-sdk to ^2.0.3
Change-type: patch
2019-04-29 12:52:52 +02:00
Alexis Svinartchouk
88f543dd25 Update electron to 4.1.5
Changelog-entry: Update electron to 4.1.5
Change-type: patch
2019-04-25 16:12:03 +02:00
Resin CI
8b6f3f6022 v1.5.30 2019-04-24 15:00:52 +03:00
Alexis Svinartchouk
294ef8045a Merge pull request #2749 from balena-io/remove-double-error-message
Remove double error message
2019-04-24 13:58:38 +02:00
Alexis Svinartchouk
1f7e4c886b Don't show a dialog when the write fails.
There is already an error modal and the error detail will be shown in the console.

Changelog-entry: Don't show a dialog when the write fails.
2019-04-22 18:25:26 +02:00
Alexis Svinartchouk
63c047009f Remove useless returns and unused parameter
Change-type: patch
2019-04-22 18:24:50 +02:00
Resin CI
2c5f5004cc v1.5.29 2019-04-22 10:10:53 +03:00
Lorenzo Alberto Maria Ambrosi
2fa5426cf5 Merge pull request #2736 from balena-io/electron-updater-2
Add electron autoupdater
2019-04-22 09:08:08 +02:00
Alexis Svinartchouk
428c777402 Fix npm-shrinkwrap.json
Change-type: patch
2019-04-19 19:56:30 +02:00
Lorenzo Alberto Maria Ambrosi
7e2c62c520 Fix mixpanel events sampling rate
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2019-04-19 17:26:38 +02:00
Giovanni Garufi
3d3b4f4a46 Add electron autoupdater
Change-type: patch
Changelog-entry: Add support for auto-updating feature
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
2019-04-19 17:13:37 +02:00
Resin CI
a543dcf166 v1.5.28 2019-04-19 14:46:55 +03:00
Alexis Svinartchouk
5de54bb6bf Merge pull request #2741 from balena-io/update-etcher-sdk-2
Update etcher sdk to ^2.0.1
2019-04-19 13:44:52 +02:00
Alexis Svinartchouk
d95401e614 Update electron-builder to ^20.40.2
Changelog-entry: Update electron-builder to ^20.40.2
Change-type: patch
2019-04-18 18:40:59 +02:00
Alexis Svinartchouk
2c835437e9 Update etcher-sdk to ^2.0.1
Changelog-entry: Update etcher-sdk to ^2.0.1
Change-type: patch
2019-04-18 18:40:46 +02:00
Resin CI
498e70ed2b v1.5.27 2019-04-16 17:30:43 +03:00
Alexis Svinartchouk
fce5b500bf Merge pull request #2734 from balena-io/fix-wmic-tmp-spaces
Fix reading images from network drives on windows when the tmp dir has spaces
2019-04-16 16:28:39 +02:00
Alexis Svinartchouk
11def54adb Fix reading images from network drives on windows when the tmp dir has spaces
Changelog-entry: (Windows): Fix reading images from network drives when the tmp dir has spaces
Change-type: patch
2019-04-16 13:44:25 +02:00
Resin CI
9da9e73f7a v1.5.26 2019-04-12 20:44:41 +03:00
Alexis Svinartchouk
f90cd49a6d Merge pull request #2729 from balena-io/fix-wmic-output-encoding
Fix reading images from network drives containing non ascii characters
2019-04-12 19:42:13 +02:00
Alexis Svinartchouk
6e72c07190 Fix reading images from network drives containing non ascii characters
Changelog-entry: (Windows): Fix reading images from network drives containing non ascii characters
Change-type: patch
2019-04-12 18:56:12 +02:00
Resin CI
1997e1faeb v1.5.25 2019-04-10 14:27:04 +03:00
Lorenzo Alberto Maria Ambrosi
b33b34bd71 Merge pull request #2698 from balena-io/filter-analytics
New parameter in webview for opt-out analytics
2019-04-10 13:24:57 +02:00
Lorenzo Alberto Maria Ambrosi
6a9b739541 New parameter in webview for opt-out analytics
Change-type: patch
Changelog-entry: New parameter in webview for opt-out analytics
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-04-09 19:10:29 +02:00
Resin CI
6cb0bdd1a4 v1.5.24 2019-04-08 16:28:04 +03:00
Lorenzo Alberto Maria Ambrosi
b73ebb6f92 Merge pull request #2726 from balena-io/analytics-version-weight
Add sample property to Mixpanel events
2019-04-08 15:25:39 +02:00
Lorenzo Alberto Maria Ambrosi
24a83260ca Update building scripts to latest master
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-04-05 20:01:44 +02:00
Lorenzo Alberto Maria Ambrosi
fc1c1b402b Add sample property to Mixpanel events
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-04-05 17:02:04 +02:00
Alexis Svinartchouk
af462b3486 Merge pull request #2725 from balena-io/update-resin-corvus
Update resin-corvus to ^2.0.3
2019-04-03 18:09:20 +02:00
Alexis Svinartchouk
3e236996c8 Update resin-corvus to ^2.0.3
Changelog-entry: Update resin-corvus to ^2.0.3
Change-type: patch
2019-04-03 16:16:06 +02:00
Resin CI
c4e84483df v1.5.23 2019-04-03 13:19:19 +03:00
Giovanni Garufi
e9532f2158 Merge pull request #2720 from balena-io/publish-gh-pages
Set publishMetadata in repo.yml
2019-04-03 03:17:17 -07:00
Giovanni Garufi
15fc8ab2e7 Set publishMetadata in repo.yml
This will cause VB to publish metadata about the repo to its gh-pages
branch on merge

Change-type: patch
Changelog-entry: Configure versionbot to publish repo metadata to github pages
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
2019-04-03 11:22:31 +02:00
Resin CI
b39dbeb25e v1.5.22 2019-04-02 19:54:16 +03:00
Alexis Svinartchouk
e181c21f85 Merge pull request #2724 from balena-io/fix-wmic-not-in-path
Use full path to wmic as some systems don't have it in their PATH
2019-04-02 18:51:38 +02:00
Alexis Svinartchouk
db771bc2cc Use full path to wmic as some systems don't have it in their PATH
Changelog-entry: (Windows): Use full path to wmic as some systems don't have it in their PATH
Change-type: patch
2019-04-02 17:32:49 +02:00
Resin CI
0695cfb3c0 v1.5.21 2019-04-02 17:43:58 +03:00
Alexis Svinartchouk
ff3982efa4 Merge pull request #2721 from balena-io/fix-getMixpanelConfig
Fix error when config.analytics was undefined
2019-04-02 16:42:00 +02:00
Alexis Svinartchouk
40de7f5d54 Fix error when config.analytics was undefined
Changelog-entry: Fix error when config.analytics was undefined
Change-type: patch
2019-04-01 18:16:56 +02:00
Resin CI
18a848696f v1.5.20 2019-04-01 19:04:20 +03:00
Alexis Svinartchouk
58de7375a2 Merge pull request #2717 from balena-io/1.5.20
1.5.20
2019-04-01 18:00:27 +02:00
Alexis Svinartchouk
b61109a269 Fix reading images from network drives on windows
Change-type: patch
2019-04-01 15:40:30 +02:00
Alexis Svinartchouk
164fd8f022 Don't try to flash when no device is selected
Changelog-entry: Don't try to flash when no device is selected
Change-type: patch
2019-03-29 17:24:34 +01:00
Giovanni Garufi
cafaa9ff22 Delete versionist.conf
Versionist will now look at repo.yml and inject the versionist config
corresponding to the type

Change-type: patch
Changelog-Entry: Reformat changelog
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
2019-03-29 17:24:34 +01:00
Alexis Svinartchouk
34c98d1dcd Use async/await in flash.js
Avoid a rare race condition leading to "Error: There is already a flash in progress" messages

Changelog-entry: Avoid "Error: There is already a flash in progress" errors
Change-type: patch
2019-03-29 17:24:34 +01:00
Alexis Svinartchouk
ec015da795 Avoid "Invalid state percentage: null" errors
Change-type: patch
2019-03-29 17:24:34 +01:00
Resin CI
a21a82c64e v1.5.19 2019-03-28 16:49:12 +02:00
Alexis Svinartchouk
1aca669c62 Merge pull request #2714 from balena-io/report-unhandled-rejections
Better reporting of unhandled rejections to sentry
2019-03-28 15:47:02 +01:00
Alexis Svinartchouk
39573ada54 Update resin-corvus to ^2.0.2
Changelog-entry: Update resin-corvus to ^2.0.2
Change-type: patch
2019-03-28 13:47:30 +01:00
Alexis Svinartchouk
bceb7c77d1 Better reporting of unhandled rejections to sentry
Changelog-entry: Better reporting of unhandled rejections to sentry
Change-type: patch
2019-03-27 19:54:28 +01:00
Resin CI
68fa771905 v1.5.18 2019-03-27 01:42:35 +02:00
Lorenzo Alberto Maria Ambrosi
8a85968ec4 Merge pull request #2709 from balena-io/fix-appimage-build
Recreate zipped appImage
2019-03-27 00:40:22 +01:00
Giovanni Garufi
03b1a2dcff Update scripts
Change-type: patch
Changelog-entry: Update build scripts
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
2019-03-26 23:29:17 +01:00
Resin CI
5cb231e427 v1.5.17 2019-03-26 10:48:08 +02:00
Giovanni Garufi
e90f6764f5 Merge pull request #2705 from balena-io/publish-github
Set publish: github in repo.yml
2019-03-26 01:45:28 -07:00
Giovanni Garufi
d078055e40 Set publish: github in repo.yml
Change-type: patch
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
Changelog-entry: Automatically publish github release from CI
2019-03-25 17:48:21 +01:00
Resin CI
98134eb612 v1.5.16 2019-03-25 18:38:34 +02:00
Giovanni Garufi
b0f2dfc4fb Merge pull request #2696 from balena-io/test-pipeline
Add repo.yml
2019-03-25 09:31:05 -07:00
Giovanni Garufi
195f07c09f Update scripts
Change-type: patch
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
2019-03-22 18:23:16 +01:00
Giovanni Garufi
15f87edc96 Update .gitattributes to always use LF for EOL in json files 2019-03-22 12:12:36 +01:00
Giovanni Garufi
52caae8f05 Add repo.yml
Change-type: patch
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
Changelog-Entry: Add repo.yml for CI
2019-03-22 12:11:02 +01:00
Resin CI
99f7fc99da v1.5.15 2019-03-21 02:21:49 +02:00
Alexis Svinartchouk
89fc98c6f6 Merge pull request #2701 from balena-io/upgrade-etcher-sdk
etcher-sdk: Upgrade to 1.3.11
2019-03-21 01:19:14 +01:00
Juan Cruz Viotti
0c2eb1caab etcher-sdk: Upgrade to 1.3.11
Change-type: patch
Changelog-entry: Show the correct logo on usbboot devices on Ubuntu
Signed-off-by: Juan Cruz Viotti <juan@balena.io>
2019-03-20 21:18:30 +00:00
Resin CI
303969bdbf v1.5.14 2019-03-20 19:14:54 +02:00
Alexis Svinartchouk
8b7266a435 Merge pull request #2692 from balena-io/1.5.13
1.5.14
2019-03-20 18:09:34 +01:00
Alexis Svinartchouk
fc9282fff7 Remove versionist from dev dependencies
Change-type: patch
2019-03-20 16:13:38 +01:00
Alexis Svinartchouk
33fb79e0de Update etcher-sdk to ^1.3.10
Changelog-entry: Update etcher-sdk to ^1.3.10
Change-type: patch
2019-03-20 16:13:38 +01:00
Resin CI
b4418660df v1.5.13 2019-03-18 20:07:14 +02:00
Giovanni Garufi
3560a22a77 Merge pull request #2694 from balena-io/update-scripts
Update scripts
2019-03-18 19:02:30 +01:00
Giovanni Garufi
818b466687 Update scripts
Change-type: patch
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
Changelog-Entry: Update build scripts
2019-03-18 17:44:44 +01:00
Resin CI
91d29c1e2c v1.5.12 2019-03-15 19:18:17 +02:00
Alexis Svinartchouk
e06fe72131 Merge pull request #2691 from balena-io/local-node-gyp-electron-builder
Update electron-builder scripts
2019-03-15 18:12:01 +01:00
Alexis Svinartchouk
7d715fdca0 Disable node gyp rebuild while running electron-builder
Change-type: patch
2019-03-15 17:33:19 +01:00
Lorenzo Alberto Maria Ambrosi
3cfa6988ab Update build scripts
Changelog-entry: Update build scripts
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-03-15 17:33:19 +01:00
Resin CI
1c707b2d37 v1.5.11 2019-03-12 20:07:34 +02:00
Alexis Svinartchouk
2ed4c76abf Merge pull request #2689 from balena-io/1.5.11
1.5.11
2019-03-12 19:00:51 +01:00
David Lozano Jarque
94e91723f4 Update PUBLISHING.md
Fixed broken Hombrew cask link for etcher

Changelog-entry: Fixed broken Hombrew cask link for etcher
Change-type: patch
2019-03-12 17:35:19 +01:00
Alexis Svinartchouk
091bddbad8 Remove no longer used travis and appveyor configs
Changelog-entry: Remove no longer used travis and appveyor configs
Change-type: patch
2019-03-12 17:35:19 +01:00
Resin CI
b3f68c2638 v1.5.10 2019-03-12 18:01:29 +02:00
Alexis Svinartchouk
00c94c8efd Merge pull request #2688 from balena-io/fix-appimage
Use APPDIR from env in the child writer
2019-03-12 16:29:00 +01:00
Alexis Svinartchouk
66b19677bf Use APPDIR from env in the child writer
Change-type: patch
2019-03-12 13:30:26 +01:00
Alexis Svinartchouk
2d4170e0d7 Merge pull request #2683 from balena-io/fix-makefile
Fix Makefile
2019-03-07 17:54:00 +01:00
Alexis Svinartchouk
7f8f38ddf1 Update resin-scripts
Changelog-entry: Update resin-scripts
Change-type: patch
2019-03-07 16:29:20 +01:00
Alexis Svinartchouk
2e1763f19a Fix Makefile
Change-type: patch
2019-03-07 15:20:07 +01:00
Resin CI
a5f8b3c164 v1.5.9 2019-03-06 18:00:26 +02:00
Alexis Svinartchouk
a802087009 Merge pull request #2677 from balena-io/1.5.9
1.5.9
2019-03-06 16:56:45 +01:00
Alexis Svinartchouk
3b16c06f70 upgrade(scripts): Use master branch of resin-scripts
Change-type: patch
2019-03-05 17:04:06 +01:00
Alexis Svinartchouk
a979ae3ced upgrade(etcher-sdk): Update etcher-sdk to 1.3.0
Changelog-entry: Update etcher-sdk to 1.3.0
Change-type: patch
2019-03-05 17:04:06 +01:00
Resin CI
02e0f40702 v1.5.8 2019-03-01 20:04:48 +01:00
Alexis Svinartchouk
a4d7853bb2 Merge pull request #2675 from balena-io/update-node-ext2fs
upgrade(ext2fs): Update ext2fs to 1.0.27
2019-03-01 20:00:24 +01:00
Alexis Svinartchouk
ac463e0f65 upgrade(ext2fs): Update ext2fs to 1.0.27
Changelog-entry: Update ext2fs to 1.0.27
Change-type: patch
2019-03-01 19:06:13 +01:00
Resin CI
c187aa46b7 v1.5.7 2019-03-01 17:10:08 +01:00
Alexis Svinartchouk
e65fa9dcae Merge pull request #2674 from balena-io/1.5.7
1.5.7
2019-03-01 17:05:33 +01:00
Robert Vojta
fea230cfab fix(docs): Update macOS contributing info
Changelog-entry: Update docs
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:10:50 +01:00
Lorenzo Alberto Maria Ambrosi
90838c99fc Add missing line for supporting flashing CM3+
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-03-01 15:10:50 +01:00
Robert Vojta
8e96adeda9 Fix copyright year
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:10:50 +01:00
Robert Vojta
3cdb0f840e Fix electron links
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:10:50 +01:00
Robert Vojta
b6ad6e0a85 Fix macOS version requirements
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:10:50 +01:00
Robert Vojta
e73a577452 Fix electron links
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:10:50 +01:00
Robert Vojta
16e8aa2447 Fix AppImages link
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:10:50 +01:00
Robert Vojta
1d6958a67e fix(osx installer): Fix blurred background image
Changelog-entry: Fix blurred background image
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:10:05 +01:00
Robert Vojta
136ca282eb fix(gui): Fix disappearing modal window
Changelog-entry: Fix disappearing modal window
Change-type: patch
Signed-off-by: Robert Vojta <robert@balena.io>
2019-03-01 15:09:19 +01:00
Lorenzo Alberto Maria Ambrosi
388fc2f7d9 Remove screenshot
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-03-01 13:49:26 +01:00
Resin CI
72fdb7127a v1.5.6 2019-03-01 12:16:33 +01:00
Alexis Svinartchouk
f67832644f Merge pull request #2673 from balena-io/babel-target-electron-3
Target electron 3 runtime in babel options
2019-03-01 11:44:46 +01:00
Alexis Svinartchouk
2614f3261c Target electron 3 runtime in babel options
This saves around 40KiB in generated/gui.js

Changelog-entry: Target electron 3 runtime in babel options
Change-type: patch
2019-02-28 15:04:00 +01:00
Resin CI
e84204b49a v1.5.5 2019-02-28 13:13:02 +01:00
Alexis Svinartchouk
86aaa725d5 Merge pull request #2663 from balena-io/1.5-fixes
1.5.x fixes
2019-02-28 13:10:25 +01:00
Alexis Svinartchouk
dd583a176f Don't pass undefined sockets to ipc.server.emit()
Changelog-entry: Don't pass undefined sockets to ipc.server.emit()
Change-type: patch
2019-02-28 11:16:12 +01:00
Alexis Svinartchouk
5299d958f2 Fix error when event.dataTransfer.files is empty
Changelog-entry: Fix error when event.dataTransfer.files is empty
Change-type: patch
2019-02-28 11:16:12 +01:00
Alexis Svinartchouk
f0374cf9d9 Fix error message not showing when an unsupported image is selected
Changelog-entry: Fix error message not showing when an unsupported image is selected
Change-type: patch
2019-02-28 11:16:12 +01:00
Alexis Svinartchouk
6b6a0d7b4f Avoid Invalid percentage exceptions
Changelog-entry: Avoid `Invalid percentage` exceptions
Change-type: patch
2019-02-28 11:16:12 +01:00
Alexis Svinartchouk
4317892421 Update etcher-sdk to 1.1.0
Changelog-entry: Update etcher-sdk to 1.1.0
Change-type: patch
2019-02-28 11:16:12 +01:00
Resin CI
8052b2adfa v1.5.4 2019-02-28 11:03:17 +01:00
Lorenzo Alberto Maria Ambrosi
d44927447a Merge pull request #2668 from balena-io/add-missing-contributing-step
Add missing step for submodule init & update
2019-02-28 11:01:02 +01:00
Lorenzo Alberto Maria Ambrosi
09e6c6422d Add missing step for submodule init & update
Change-type: patch
Changelog-entry: Add missing step for submodule cloning in README
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-02-27 22:24:47 +01:00
Resin CI
df85ffb254 v1.5.3 2019-02-27 22:11:45 +01:00
Lorenzo Alberto Maria Ambrosi
752ba4405c Merge pull request #2669 from balena-io/fix-versionist-conf
Fix versionist conf
2019-02-27 22:09:02 +01:00
Lorenzo Alberto Maria Ambrosi
1f3a02b83d Bump version in npm-shrinkwrap.json
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-02-27 19:48:20 +01:00
Giovanni Garufi
8e372f1e93 Fix changelog 2019-02-27 16:25:10 +01:00
Giovanni Garufi
caeb84f58b Throw error if no commit is annotated with a changelog entry
Change-type: patch
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
Changelog-entry: Throw error if no commit is annotated with a changelog entry
2019-02-27 16:23:55 +01:00
Resin CI
759722bf7d v1.5.2 2019-02-26 15:21:12 +01:00
Lorenzo Alberto Maria Ambrosi
cefdc95c9b Merge pull request #2664 from balena-io/enable-edit-version-versionist
Enable versionist editVersion
2019-02-26 15:17:26 +01:00
Lorenzo Alberto Maria Ambrosi
3be7029078 Enable versionist editVersion
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-02-26 13:10:50 +01:00
Resin CI
3f16858a93 v1.5.1 2019-02-25 12:11:04 +01:00
Giovanni Garufi
c61c6deaa8 Merge pull request #2634 from balena-io/versioning
[WIP] Remove lodash use from versionist.conf.js
2019-02-25 11:04:33 +00:00
Giovanni Garufi
90c8483df8 Remove lodash dependency in versionist.conf.js
Changelog-entry: Removed lodash dependency in versionist.conf.js
Change-type: patch
Signed-off-by: Giovanni Garufi <giovanni@balena.io>
2019-02-22 13:30:49 +00:00
Lorenzo Alberto Maria Ambrosi
d70b189cec Merge pull request #2635 from balena-io/release-v1.5.0
Release v1.5.0
2019-02-21 17:13:26 +01:00
Lorenzo Alberto Maria Ambrosi
41a7fc4de5 Release v1.5.0
Change-type: minor
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-02-20 17:00:31 +01:00
Alexis Svinartchouk
db119d5230 Update npm-shrinkwrap.json to update drivelist
Change-type: patch
2019-02-20 17:00:31 +01:00
Alexis Svinartchouk
c88245954d Wait 100ms before disconnecting if a message is being sent
Change-Type: patch
2019-02-19 14:18:22 +01:00
Alexis Svinartchouk
b1ab3834b6 Merge pull request #2631 from balena-io/dont-use-drivelist-directly
Dont use drivelist directly
2019-02-15 14:16:41 +01:00
Alexis Svinartchouk
34b7c1be81 Update etcher-sdk to ^1.0.7
Change-type: patch
2019-02-14 19:19:19 +01:00
Alexis Svinartchouk
082c77586f Don't use drivelist directly
Use etcher-sdk's drive scanner instead.

Change-Type: patch
2019-02-14 19:19:19 +01:00
Alexis Svinartchouk
3b6fe7b548 Merge pull request #2630 from balena-io/drop-cli
Remove etcher-cli
2019-02-14 19:09:30 +01:00
Alexis Svinartchouk
da072e7621 Remove etcher-cli
Change-type: major
2019-02-14 18:22:40 +01:00
Alexis Svinartchouk
4568404a70 Merge pull request #2616 from balena-io/electron-3.0
Bump electron to v3.1.3
2019-02-14 17:12:39 +01:00
Alexis Svinartchouk
43319853ef Workaround a bug when 2 webviews are loaded at the same time.
In some cases the spectron tests time out in app:start. This should
prevent it.

Change-type: patch
2019-02-14 15:41:03 +01:00
Lorenzo Alberto Maria Ambrosi
ce9f142621 Bump electron to v3.1.3
Change-type: major
Changelog-entry: Upgrade to Electron v3
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-02-12 15:42:05 +01:00
Alexis Svinartchouk
8ef3add183 Merge pull request #2615 from balena-io/npm6-3
Npm6 replaces #2577
2019-02-11 17:15:18 +01:00
Alexis Svinartchouk
ef45696015 Double app:start test timeout
Change-type: patch
2019-02-11 14:46:05 +01:00
Alexis Svinartchouk
a8f8c2cd85 Increase svg icon test timeout
Change-type: patch
2019-02-11 14:08:13 +01:00
Alexis Svinartchouk
6d79a8e23a Rebuild node-sass before using it
It avoids an error for x86 win32 builds on x64 platforms:
`Node Sass could not find a binding for your current environment: Windows 64-bit with Node.js 6.x`

Change-type: patch
2019-02-11 12:06:27 +01:00
Alexis Svinartchouk
d65dc6ccac Use npx branch of resin-scripts
Change-type: patch
2019-02-08 15:37:45 +01:00
Alexis Svinartchouk
ccc9076a80 Use npx to force npm version
Change-type: patch
2019-02-01 15:32:06 +01:00
Alexis Svinartchouk
3c007cea34 Specify npm_version in .resinci.json
Change-type: patch
2019-02-01 13:07:13 +01:00
Alexis Svinartchouk
bf29312ecf npm6, electron 1.8.8
Change-type: patch
2019-01-30 16:24:01 +01:00
Alexis Svinartchouk
a53095b29e Merge pull request #2403 from balena-io/etcher-sdk
refactor: use etcher-sdk
2019-01-29 14:37:05 +01:00
Alexis Svinartchouk
d5c9e6b054 Move patches back to patches folder
Change-type: patch
2019-01-28 14:53:29 +01:00
Alexis Svinartchouk
d4f29bd2af Hardcode electron_version in node-pre-gyp patch
Because it is not available in electron when running with
ELECTRON_RUN_AS_NODE=1

Change-type: patch
2019-01-28 13:07:38 +01:00
Alexis Svinartchouk
a6661ac759 Update node-ext2fs to 1.0.25
Change-type: patch
2019-01-25 18:05:51 +01:00
Alexis Svinartchouk
6aa83819d1 Remove napi-build-utils from npm-shrinkwrap
Change-type: patch
2019-01-24 18:51:30 +01:00
Alexis Svinartchouk
8ff4c8a4a5 Fix npm-shrinkwrap.json and remove versionist
versionist is causing ci issues with the shrinkwrap file on windows.
You'll need to manually install versionist before running `make changelog`

Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
1d77b8dae7 Update node-pre-gyp patch and move it to another folder
To prevent the apply-patches script from doing stuff

Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
3e0062621b Update build scripts for electron-builder unresolved dependencies
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
b20e220910 Update styled-system to 3.1.11 (it was lost in a rebase)
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
0259572ded Update etcher-sdk to ^1.0.2 and update npm-shrinkwrap.json
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
a78866069b Update webpack to 4.27.0 and babel to 7.2.0
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
b8fc83577c Remove asar from devDependencies, update versionist
Change-Type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
c21969ab4e Remove etcher-sdk folder filtering from webpack config
This folder has been removed

Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
e02cfc4529 update(etcher-sdk): Update etcher-sdk and shrinkwrap.json
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
ac07c63631 update(etcher-sdk): Update etcher-sdk and shrinkwrap.json
Also update the node-pre-gyp patch (the directory has changed)

Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
1054bc995b fix(ci): Set node target to 6.14.4
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
3560ab6387 update(package): Update etcher-sdk and npm-shrinkwrap.json
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
e50274b962 Remove no longer used bluebird-retry
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
bb1773a1a1 Remove styled-system from package.json
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
941dc3b1b4 update(package): Update shrinkwrap.json
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
92d08d24ab fix(build): Update resin scripts to build modules from source
Change-type: patch
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
7f6ffe0f73 fix(package): Fix shrinkwrap file
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@balena.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
66457ca0c7 upgrade(package): Update to etcher-sdk@0.1.28
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
3344f1fd88 upgrade(package): Update to etcher-sdk@0.1.27
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
c4b636f80a upgrade(package): Update to etcher-sdk@0.1.26 and fix npm-shrinkwrap
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
0ea0975bd4 upgrade(package): Update to etcher-sdk@0.1.23
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
534f3a7469 fix(gui): Always show the "success" screen
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
f3110ba018 upgrade(package): Update to etcher-sdk@0.1.16
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
e76cc81fe1 upgrade(package): Update to etcher-sdk@0.1.15
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
adcc3343ec fix(gui): Disable compute modules selection during preparation
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
645e114a1f fix(gui): Allow drives to be objects
This fixes an error when plugging usbboot devices.

Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
65d86460cb fix(shared): Fix getDriveImageCompatibilityStatuses() and tests
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
aaccd10c2a fix(gui): Allow undefined eta
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
a237bfd930 upgrade(package): Update to etcher-sdk@0.1.13
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:27 +01:00
Alexis Svinartchouk
73f64d93b1 upgrade(package): Update to etcher-sdk@0.1.9
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
871db09447 fix(tests): Fix gui tests
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
8d79103392 upgrade(package): Update to etcher-sdk@0.1.7
Also update the shrinkwrap file

Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
fd765443e4 fix(image-selection): Only trigger digest loop after setting image
Change-type: patch
Signed-off-by: Jonas Hermsmeier <jhermsmeier@gmail.com>
2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
63967d1558 fix(tests): Remove throw if no percentage or eta test
Since 25916200f2864a9b137325f919c0f8ef5d62fa60 we can handle a progress
state with no percentage or eta.
2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
6b270885bf feat(driverless) show driverless devices 2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
47937d6aaa fix(package): remove diskpart helper, it is in the sdk now 2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
7d2ba45620 fix(store): Lowercase extensions before comparing 2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
b270d819a8 fix(store): Restore drive object validity check 2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
c50553fbf6 upgrade(package): Update etcher-sdk git ref 2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
a541c863be fix(test): Sort compressed extensions before comparing 2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
254b482651 upgrade(package): Update mime-types 2.1.15 -> 2.1.18
This update includes a previously missing mapping for gzip
(`application/gzip`), which contributes to fixing gzip compressed
image detection in the new SDK

Change-type: patch
2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
d3c2cd4215 fix(test): Sort supported extensions to fix order mismatch
Change-type: patch
2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
4f7cc7dd6b fix(lib): Fix MIME type exclusion condition
As `mime.extension()` returns `false`, instead of `null` or `undefined`,
this condition simply needs to check for truthyness.

Change-type: patch
2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
21f1f4e503 fix(test): Turn SDK integration tests for the GUI back on
Change-type: patch
2019-01-24 13:21:26 +01:00
Jonas Hermsmeier
47f2336673 fix(lib): Fix use of non-existent dependency
Change-Type: patch
2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
5ae93bf6d0 Update etcher-sdk and load DriverlessDeviceAdapter on windows 2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
caf5f10326 lint 2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
e68dbcf4ee Remove lib/sdk and its tests 2019-01-24 13:21:26 +01:00
Alexis Svinartchouk
a42e81cf8c Replace imageStream with etcher-sdk in the react file selector 2019-01-24 13:21:21 +01:00
Alexis Svinartchouk
98a8588c1b Update etcher-sdk and use it in the cli 2019-01-24 13:21:21 +01:00
Alexis Svinartchouk
8630af7646 Remove usage of old sdk in supported-formats 2019-01-24 13:21:21 +01:00
Alexis Svinartchouk
268c5302e8 Handle the last fail as an error if all devices failed 2019-01-24 13:21:21 +01:00
Alexis Svinartchouk
d07d535993 Show raspberry pi usbboot update progress in devices list 2019-01-24 13:21:21 +01:00
Alexis Svinartchouk
a8a75f22b2 Allow flashing from sources for which we don't know the compressed size
* don't show any percentage or eta, show the bytes written instead
2019-01-24 13:21:21 +01:00
Alexis Svinartchouk
6143023502 Integrate etcher-sdk 2019-01-24 13:21:21 +01:00
Alexis Svinartchouk
ca6aa5d4aa Merge pull request #2611 from balena-io/update-node-gyp
Update node-gyp to 3.8.0
2019-01-24 08:52:52 +01:00
Alexis Svinartchouk
bc028ed41f Add napi-build-utils to platformSpecificDependencies
Change-type: patch
2019-01-23 17:25:42 +01:00
Alexis Svinartchouk
911d3a9188 Update node-gyp to 3.8.0
Change-type: patch
2019-01-23 16:26:26 +01:00
Alexis Svinartchouk
b88e715fc5 Merge pull request #2610 from balena-io/update-winusb
Update winusb-driver-generator to 1.2.4
2019-01-23 13:22:17 +01:00
Alexis Svinartchouk
a4dfa5f281 Update winusb-driver-generator to 1.2.4
Change-type: patch
2019-01-22 18:29:20 +01:00
Lorenzo Alberto Maria Ambrosi
05fc1711b9 Merge pull request #2606 from balena-io/bump-dependencies
Bump dependencies
2019-01-18 19:13:32 +01:00
Lorenzo Alberto Maria Ambrosi
c16fbb5b47 Rename resin-io modules to balena-io
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-18 17:05:06 +01:00
Lorenzo Alberto Maria Ambrosi
7ca3e2b519 Update build scripts for electron-builder unresolved dependencies
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-18 16:51:20 +01:00
Lorenzo Alberto Maria Ambrosi
8c8a0bf8eb Fix linting error for winusb-driver-generator
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-18 14:48:10 +01:00
Lorenzo Alberto Maria Ambrosi
e85251d2e3 Bump drivelist to v6.4.6
Change-type: patch
Changelog-entry: Fix incorrect drives list on Linux
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-17 10:57:46 +01:00
Lorenzo Alberto Maria Ambrosi
73e4827249 Bump mountutils to v1.3.16 for XCode build fix
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-17 10:54:29 +01:00
Lorenzo Alberto Maria Ambrosi
c37270ea08 Switch to fork of xxhash with XCode build fix
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-17 10:52:34 +01:00
Lorenzo Alberto Maria Ambrosi
8cc33b46bb Make winusb-driver-generator optional (win only)
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-17 10:51:11 +01:00
Lorenzo Alberto Maria Ambrosi
700341f9cc Fix error with OSX XCode build
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-17 10:49:38 +01:00
Lorenzo Alberto Maria Ambrosi
ca85ad5995 Merge pull request #2460 from balena-io/contribution-file-fix
docs: Add info about required npm version
2019-01-14 19:59:16 +01:00
Lorenzo Alberto Maria Ambrosi
1c8c36a224 Update nodejs req to 6.11 (fixes package build)
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-14 18:36:25 +01:00
Agnieszka Domanska
25b814e796 docs: Add info about required npm version
Npm 3.10 version is required to install dev tools correctly on Linux.

Change-type: patch
Signed-off-by: amdomanska <aga@resin.io>
2019-01-14 17:22:40 +01:00
Lorenzo Alberto Maria Ambrosi
e89566e04a Merge pull request #2580 from balena-io/progress-button-disabled-prop-is-a-boolean
ProgressBar.disabled prop is a boolean
2019-01-09 14:04:55 +01:00
Alexis Svinartchouk
e946f388c0 ProgressBar.disabled prop is a boolean
Change-type: patch
2019-01-08 12:42:39 +01:00
Lorenzo Alberto Maria Ambrosi
7616e8dab7 Merge pull request #2582 from balena-io/2281-drive-mountpoint-contains-image
Change "Drive Contains Image" label.
2019-01-08 11:53:47 +01:00
Lorenzo Alberto Maria Ambrosi
2dc4fef4d3 Update scripts to build on other Linux distros
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-07 17:01:18 +01:00
Alexis Svinartchouk
f2ca997195 Change "Drive Contains Image" label.
Use "Drive Mountpoint Contains Image" instead as the image may not be on
this drive but on a drive mounted in one of the mountpoins of this
drive.
We still don't want to allow flashing this drive in that situation.

Changelog-entry: Changed “Drive Contains Image” to “Drive Mountpoint Contains Image”
Change-type: patch
2019-01-07 15:35:21 +01:00
Lorenzo Alberto Maria Ambrosi
7445004abf Merge pull request #2589 from balena-io/fix-offline-success-banner
Restored offline success-banner style
2019-01-07 15:34:23 +01:00
Lorenzo Alberto Maria Ambrosi
9b76abe2ed Restored offline success-banner style
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-07 14:06:05 +01:00
Lorenzo Alberto Maria Ambrosi
a97205c9fc Merge pull request #2595 from Jacalz/fix-solus-install
Refinements to the README
2019-01-07 09:56:39 +01:00
Jacalz
bf3d069aad Refinements to the README
This started out with the intention to fix a typo in the uninstall 
section of Solus, but developed in to a couple improvements to the 
README.
2019-01-05 16:44:49 +01:00
Lorenzo Alberto Maria Ambrosi
27ea74722c Merge pull request #2592 from balena-io/fix-readme
Fix readme
2019-01-04 17:38:53 +01:00
Lorenzo Alberto Maria Ambrosi
2525456d8b Update balena-etcher .deb and .rpm install steps
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-04 16:08:10 +01:00
Lorenzo Alberto Maria Ambrosi
9fa32df3a6 Remove travis-ci and appveyor badges
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2019-01-04 15:39:23 +01:00
Lorenzo Alberto Maria Ambrosi
5bdd5da13b Merge pull request #2587 from balena-io/fix-dmg-assets
New dmg package background assets
2018-12-23 15:54:06 +01:00
Lorenzo Alberto Maria Ambrosi
b8756edd29 New dmg package background assets
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-12-22 01:41:18 +01:00
Lorenzo Alberto Maria Ambrosi
c93910e858 Merge pull request #2586 from balena-io/release-v1.4.9
v1.4.9
2018-12-21 16:07:29 +01:00
Lorenzo Alberto Maria Ambrosi
ad4226ace7 Invert analytics event probability
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-12-21 15:12:08 +01:00
Lorenzo Alberto Maria Ambrosi
d71b3fe1bc v1.4.9
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-12-19 22:10:26 +01:00
Lorenzo Alberto Maria Ambrosi
07858eecac Merge pull request #2571 from balena-io/restyle-success-screen
Restyle success screen and enlarge UI elements
2018-12-19 19:36:49 +01:00
Lorenzo Alberto Maria Ambrosi
64ec6d0e58 Convert flash results component to React
Change-type: minor
Changelog-entry: Added React component for the Flash Results button
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-12-19 16:02:38 +01:00
Lorenzo Alberto Maria Ambrosi
cf722427ab Restyle success screen and enlarge UI elements
Change-type: patch
Changelog-entry: Added React component for the Flash Another button
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-12-19 13:20:02 +01:00
Lorenzo Alberto Maria Ambrosi
1b7ff07efc Merge pull request #2584 from balena-io/remove-webview-console-messages
Remove forwarding of SafeWebview console messages
2018-12-19 13:09:21 +01:00
Lorenzo Alberto Maria Ambrosi
87533f4417 Remove forwarding of SafeWebview console messages
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-12-19 12:19:42 +01:00
Lorenzo Alberto Maria Ambrosi
9077c95cdd Merge pull request #2583 from balena-io/add-mixpanel-configs
Customize Mixpanel configs
2018-12-18 15:13:16 +01:00
Lorenzo Alberto Maria Ambrosi
22acc5ae96 Customize Mixpanel configs
Change-type: minor
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-12-18 11:32:07 +01:00
Lorenzo Alberto Maria Ambrosi
cf596a88ab Merge pull request #2557 from balena-io/explicit-safe-webview-events
Use explicit names for safe-webview events
2018-11-28 21:11:10 +01:00
Lorenzo Alberto Maria Ambrosi
7354fa3050 Use explicit names for safe-webview events
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-28 15:57:58 +01:00
Lorenzo Alberto Maria Ambrosi
978497b287 Merge pull request #2539 from Jacalz/gitmodule-https
Use https for fetching sub modules
2018-11-28 15:35:33 +01:00
Lorenzo Alberto Maria Ambrosi
a52d745250 Merge branch 'master' into gitmodule-https 2018-11-28 14:14:13 +01:00
Chris Crocker-White
aae71f8105 Merge pull request #2562 from balena-io/chrisys-patch
Update URLs in GUI to balena
2018-11-27 15:51:23 -08:00
Jacob
5419b4b732 Use https for fetching sub modules
This switches over the sub module to using https instead of ssh. It simplifies a lot for people packaging the application and you won't need to have ssh configured correctly.
2018-11-27 18:19:02 +01:00
Chris Crocker-White
caf5a8917c Merge branch 'master' into chrisys-patch 2018-11-27 08:22:15 -08:00
Lorenzo Alberto Maria Ambrosi
beec00dcb3 Merge pull request #2560 from OSSystems/add-wic-support
Add `.wic` image extension as supported format
2018-11-27 14:31:42 +01:00
Otavio Salvador
7565e809b0 Add .wic image extension as supported format
The `.wic` is a widely used image format in the OpenEmbedded / Yocto
Project ecosystem and is straightforward to be supported.

Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
2018-11-27 10:01:05 -02:00
Lorenzo Alberto Maria Ambrosi
5c9a646bc1 Merge pull request #2561 from rhwood/patch-1
Update MacOS installation instructions.
2018-11-27 10:26:19 +01:00
Chris Crocker-White
dd8ef288f7 Update URLs in GUI to balena
Change-type: patch
Signed-off-by: Chris Crocker-White <chriscw@balena.io>
2018-11-26 17:38:06 -08:00
Randall Wood
db8d2953cb Update MacOS installation instructions.
Homebrew/homebrew-cask#55358 changed the name used for installation.
2018-11-26 17:23:38 -08:00
Lorenzo Alberto Maria Ambrosi
b75ca26db2 Merge pull request #2558 from Eate/patch-1
Updated Chocolatey section of Readme
2018-11-26 20:05:54 +01:00
Eate
948a04122a Updated Chocolatey section
Previously, the section header was a "###" header, and I changed it to a "####" header like all the other install variants so it is the same level header. I also added uninstall instructions like the other sections had.
2018-11-26 08:09:47 -08:00
Lorenzo Alberto Maria Ambrosi
b7c4562b85 Merge pull request #2556 from balena-io/fix-update-notification
fix(GUI): Fix update notification error
2018-11-26 17:08:49 +01:00
Lorenzo Alberto Maria Ambrosi
6d0fea1983 fix(GUI): Fix update notification error
Remove "this" and use "exports" instead

Change-type: patch
Changelog-entry: Fix update notifier error popping up on v1.4.1->1.4.8
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-26 15:53:55 +01:00
Lorenzo Alberto Maria Ambrosi
1a158a919a Merge pull request #2553 from balena-io/v1.4.8
v1.4.8
2018-11-23 18:52:18 +01:00
Lorenzo Alberto Maria Ambrosi
9a83bd4267 v1.4.8
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-23 17:51:41 +01:00
Lorenzo Alberto Maria Ambrosi
7e3f516b04 Merge pull request #2551 from balena-io/add-potm-webview
feat(GUI): Add featured-project component
2018-11-23 17:44:49 +01:00
Lorenzo Alberto Maria Ambrosi
afd888e14d fix(GUI): Fix styling issues with buttons
Change-type: patch
Changelog-entry: Moved back the write cancel button
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-23 16:28:06 +01:00
Lorenzo Alberto Maria Ambrosi
76af6e975e Add flashing info while showing webview
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-23 13:19:47 +01:00
Lorenzo Alberto Maria Ambrosi
2017df9ec6 feat(GUI): Add featured-project component
Change-type: patch
Changelog-entry: Added featured-project while flashing
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-22 22:05:11 +01:00
Lorenzo Alberto Maria Ambrosi
aa1e83dc24 Merge pull request #2552 from balena-io/reject-drives-null-size
fix(GUI): Reject drives with null size
2018-11-22 20:50:56 +01:00
Lorenzo Alberto Maria Ambrosi
20996b153d fix(GUI): Reject drives with null size
Change-type: patch
Changelog-entry: Reject drives with null size (fixes pretty-bytes error)
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-22 19:57:45 +01:00
Alexis Svinartchouk
b298e53fc4 Merge pull request #2544 from balena-io/usbboot-limit-transfer-size
Usbboot limit transfer size
2018-11-13 15:49:42 +01:00
Alexis Svinartchouk
7fb382bee0 fix(usbboot): Limit usbboot transfers to 1MiB
Change-type: patch
2018-11-13 14:57:42 +01:00
Alexis Svinartchouk
2158772e3b lint: don't run codespell on svg files
Change-type: patch
2018-11-13 14:55:45 +01:00
Lorenzo Alberto Maria Ambrosi
333298e6c3 Merge pull request #2542 from balena-io/release-1.4.7
v1.4.7
2018-11-12 11:47:34 +01:00
Lorenzo Alberto Maria Ambrosi
6e9deeba5b v1.4.7
Change-type: major
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-11 16:23:13 +01:00
apostolism
15951509a7 Merge pull request #2535 from balena-io/fix-versionist
fix(versionist): Adapt versionist.conf.js to new guidelines
2018-11-09 18:22:02 +02:00
Lorenzo Alberto Maria Ambrosi
dd8b7e42d6 fix(versionist): Adapt versionist.conf.js to new guidelines
Change-type: patch
Changelog-entry: Modify versionist.conf.js to match new internal commit guidelines
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-08 01:40:24 +01:00
Lorenzo Alberto Maria Ambrosi
2655c86be3 Merge pull request #2534 from balena-io/add-balena-icons
Add balena iconset & osx installer background
2018-11-07 18:10:01 +01:00
Lorenzo Alberto Maria Ambrosi
c4c4d347cf Update application name & copyright
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-05 15:58:09 +01:00
Lorenzo Alberto Maria Ambrosi
a3f7239c1b Add balena iconset & osx installer background
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
2018-11-02 12:14:52 +01:00
Lorenzo Alberto Maria Ambrosi
f90c2ad74e Merge pull request #2477 from balena-io/select-image-button
refactor(GUI): Image Selector Button
2018-11-02 10:54:15 +01:00
amdomanska
2907cd173b refactor(GUI): Convert Select Image button to Rendition
Convert Select Image button to Rendition component

Change-type: minor
Signed-off-by: amdomanska <aga@resin.io>
2018-11-01 19:21:39 +01:00
Lucian Buzzo
779ee8294f Merge pull request #2494 from balena-io/docs-typo
docs: fix typo in contributing guidelines
2018-11-01 10:37:42 +00:00
Lucian Buzzo
a229c9e10e docs: Fix typo in contributing guidelines
Change-type: patch
Signed-off-by: Lucian Buzzo <lucian.buzzo@gmail.com>
2018-11-01 09:51:29 +00:00
Petros Angelatos
3f8d2e4242 Merge pull request #2525 from resin-io/release-1.4.6
v1.4.6
2018-10-29 15:29:23 -07:00
Lorenzo Alberto Maria Ambrosi
c1a8b0c303 v1.4.6
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-28 22:00:27 +01:00
Lorenzo Alberto Maria Ambrosi
8e92c5b844 Merge pull request #2522 from resin-io/fix-progress-button
Put flash cancel button in foreground
2018-10-28 21:53:17 +01:00
Lorenzo Alberto Maria Ambrosi
c366fbde22 Put flash cancel button in foreground
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-28 21:15:30 +01:00
Lorenzo Alberto Maria Ambrosi
890e866ae2 Merge pull request #2513 from resin-io/balena
Add new logos
2018-10-28 21:13:54 +01:00
Lorenzo Alberto Maria Ambrosi
8eb11a8957 Change resin.io to balena.io
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-25 17:32:37 +02:00
Lorenzo Alberto Maria Ambrosi
9cc65a386b Add new logos
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-25 15:57:44 +02:00
Lorenzo Alberto Maria Ambrosi
e4d4af1587 Merge pull request #2475 from resin-io/progressBar
refactor(GUI): convert Progress Button to Rendition
2018-10-24 03:06:25 +02:00
amdomanska
b3aab5116a refactor(GUI): Convert Progress Button to Rendition
Convert progress-button component to Rendition

Change-type: minor
Signed-off-by: amdomanska <aga@resin.io>
2018-10-24 02:07:49 +02:00
Lorenzo Alberto Maria Ambrosi
7227c76538 Merge pull request #2507 from resin-io/react-lint-rules
Enable React lint rules
2018-10-24 01:47:12 +02:00
Lorenzo Alberto Maria Ambrosi
c2c59f4a9e Enable React lint rules
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-23 21:56:02 +02:00
Lorenzo Alberto Maria Ambrosi
eeede318fd Merge pull request #2488 from resin-io/refactor-build-system
Use Resin CI scripts to build Etcher
2018-10-23 00:02:35 +02:00
Juan Cruz Viotti
3855bb4d56 Use Resin CI scripts to build Etcher
Change-type: patch
Signed-off-by: Juan Cruz Viotti <juan@resin.io>
2018-10-22 14:58:15 +02:00
Lorenzo Alberto Maria Ambrosi
89fa682721 Merge pull request #2510 from resin-io/fix-file-selector-constraint-path
Fix incorrect file constraint path
2018-10-17 16:42:46 +02:00
Lorenzo Alberto Maria Ambrosi
cb701a7bbc Change spectron port
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-17 15:50:51 +02:00
Lorenzo Alberto Maria Ambrosi
407325b8ce Fix incorrect file constraint path
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-17 15:20:08 +02:00
Lorenzo Alberto Maria Ambrosi
161debb35a Merge pull request #2506 from resin-io/fix-64-bit-detection
fix: Fix 64 bit detection on arm
2018-10-12 19:00:13 +02:00
Alexis Svinartchouk
fd5385b127 fix: Fix 64 bit detection on arm
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2018-10-12 16:11:13 +02:00
Alexis Svinartchouk
e85e1410aa Merge pull request #2505 from resin-io/fix-xxhash-digest-read
fix: Provide a Buffer to xxhash.Stream
2018-10-12 16:08:06 +02:00
Alexis Svinartchouk
ac068f353a fix: Provide a Buffer to xxhash.Stream
This fixes the digest being a number instead of a buffer.

Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2018-10-12 15:24:00 +02:00
Lorenzo Alberto Maria Ambrosi
fe7c6d0d57 Merge pull request #2503 from resin-io/fix-changelog
fix: Correct 1.4.5 release date & remove checklist
2018-10-11 18:16:08 +02:00
Lorenzo Alberto Maria Ambrosi
abf1e4a8ac fix: Correct 1.4.5 release date & remove checklist
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-10-11 16:15:08 +02:00
Lorenzo Alberto Maria Ambrosi
f9dfb2d0c7 Merge pull request #2441 from resin-io/release-1.4.5
Release v1.4.5
2018-10-11 16:10:54 +02:00
Lorenzo Alberto Maria Ambrosi
da23740f17 v1.4.5
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
2018-10-10 21:29:34 +02:00
Lorenzo Alberto Maria Ambrosi
47f81251d7 Merge pull request #2496 from resin-io/remove-libudev-dependency
Use fork of node-usb to disable libudev
2018-10-09 11:42:17 +02:00
Lorenzo Alberto Maria Ambrosi
7e01eca7f5 Use fork of node-usb to disable libudev
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
2018-10-05 18:43:29 +02:00
Lorenzo Alberto Maria Ambrosi
941b5c9e45 Merge pull request #2495 from resin-io/fix-analytics-in-sdk
Add 'debug' in place of 'logException'
2018-10-04 23:21:35 +02:00
Lorenzo Alberto Maria Ambrosi
207c0d612d Add 'debug' in place of 'logException'
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
2018-10-04 21:20:39 +02:00
Lorenzo Alberto Maria Ambrosi
4035176d88 Merge pull request #2491 from resin-io/warn-if-cant-require-usb
fix(GUI): Warn when requiring usb fails
2018-10-02 17:23:35 +02:00
Alexis Svinartchouk
b9f9968f84 fix(GUI): Warn when requiring usb fails
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2018-10-02 16:17:58 +02:00
Lorenzo Alberto Maria Ambrosi
7a2dac8d5b Merge pull request #2443 from resin-io/2442-update-package-repo-info
2442 update package repo info
2018-09-28 08:37:16 +02:00
Lorenzo Alberto Maria Ambrosi
2fb8ad146f Change spectron port to run tests
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
2018-09-27 19:21:54 +02:00
Michael Angelos Simos
2f4a7352d9 makefile: Update etcher deb/rpm publishing
Change-type: patch
Signed-off-by: Michael Angelos Simos <michalis@resin.io>
2018-09-27 16:19:25 +02:00
Michael Angelos Simos
c3ff030542 doc: Update etcher package repo installation and publishing info
Change-type: patch
Signed-off-by: Michael Angelos Simos <michalis@resin.io>
2018-09-27 16:19:25 +02:00
Lorenzo Alberto Maria Ambrosi
aa05cd1449 Merge pull request #2467 from resin-io/add-missing-store-require
fix(GUI): Add missing 'store' require
2018-09-27 13:52:51 +02:00
Alexis Svinartchouk
31cd33f86c fix(GUI): Add missing 'store' require
Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2018-09-27 12:51:32 +02:00
Lorenzo Alberto Maria Ambrosi
9abca204e3 Merge pull request #2469 from resin-io/fix-double-flash
fix(sudo-prompt): Use a fork of sudo-prompt
2018-09-27 12:49:58 +02:00
Alexis Svinartchouk
e9760c2100 update(sudo-prompt): Update sudo-prompt to 8.2.3
This is to avoid running the child-writer twice when the hostname isn't
set in /etc/hosts. See https://github.com/jorangreef/sudo-prompt/pull/76

Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2018-09-27 11:37:50 +02:00
Alexis Svinartchouk
1c5bab63a5 Merge pull request #2470 from resin-io/fix-blacklist-setting
gui: Also blacklist match against device & raw path
2018-09-26 10:41:49 +02:00
Jonas Hermsmeier
0d80957639 gui: Also blacklist match against device & raw path
This fixes device blacklist handling to also match against
`drive.device` and `drive.raw`, in order to be able to specify devices
lacking a `devicePath`.

Change-type: patch
Signed-off-by: Jonas Hermsmeier <jhermsmeier@gmail.com>
2018-09-25 23:59:55 +02:00
Lorenzo Alberto Maria Ambrosi
6c73ddcaca Merge pull request #2466 from resin-io/update-drivelist-6.4.2
chore: Update drivelist to v6.4.2
2018-09-25 19:58:53 +02:00
Lorenzo Alberto Maria Ambrosi
1bb86fe4a8 Update drivelist to v6.4.2
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
2018-09-25 18:47:03 +02:00
Lorenzo Alberto Maria Ambrosi
6b7be7a82d Merge pull request #2489 from resin-io/dont-use-tilde-in-rpm
Makefile: Don't use tilde in rpm versions
2018-09-25 17:27:25 +02:00
Lorenzo Alberto Maria Ambrosi
37b25d8422 Change port so not to overlap with other builds
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
Signed-off-by: Juan Cruz Viotti <juan@resin.io>
2018-09-25 15:22:42 +01:00
Juan Cruz Viotti
49edd1a6dc Makefile: Don't use tilde in rpm versions
The tilde is not a valid version character in RPM packages, according to
the RPM source code.

Change-type: patch
Signed-off-by: Juan Cruz Viotti <juan@resin.io>
2018-09-24 16:42:14 +01:00
Jonas Hermsmeier
a338c6e60a Merge branch 'salvozappa-fix-travis-build' 2018-09-10 16:45:53 +02:00
Salvatore Zappalà
f9805f3bc7 minifix: add "make webpack" to travis-ci build script
Currently, the Travis CI build is failing due to the fact that
the folder 'generated/etcher' is empty.

The folder is missing because the "make webpack" step is missing
from the travis CI build.

This commit amends that by adding the "make webpack" build step
after linting.

Change-type: patch
Signed-off-by: Salvatore Zappalà <salvatore@salvatorezappala.info>
2018-08-22 10:21:23 +01:00
Lorenzo Alberto Maria Ambrosi
b24c4ea030 Merge pull request #2448 from resin-io/fix-flash-cancel
fix(GUI): Remove results data from cancel event
2018-08-14 23:35:34 +02:00
Lorenzo Alberto Maria Ambrosi
0cabac1eed fix(GUI): Remove results data from cancel event
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
2018-08-14 21:20:00 +02:00
Lorenzo Alberto Maria Ambrosi
7c08dbfbd2 Merge pull request #2445 from resin-io/fix-webpack-electron-main
fix(webpack): Add etcher.js to webpack build
2018-08-14 20:37:35 +02:00
Lorenzo Alberto Maria Ambrosi
c0ec74bbb7 fix(webpack): Add etcher.js to webpack build
Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@resin.io>
2018-08-14 19:04:13 +02:00
Lorenzo Alberto Maria Ambrosi
ea834f6778 Merge pull request #2420 from resin-io/better-analytics
fix(GUI): Additional data on events
2018-08-07 19:40:53 +02:00
Lorenzo Alberto Maria Ambrosi
2271f32140 fix(GUI): Add data on events
Application session UUID for global app events
Flashing workflow UUID for every flashing session
Flash instance UUID for every flashing session

Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
2018-08-07 18:56:14 +02:00
Lorenzo Alberto Maria Ambrosi
93906b9b17 Merge pull request #2433 from resin-io/fix-cli-settings
fix(cli): Don't use electron to get USER_DATA_DIR in CLI
2018-08-07 18:42:04 +02:00
Jonas Hermsmeier
40d84b7a82 fix(cli): Don't use electron to get USER_DATA_DIR in CLI
A previous change erronously relied solely on `electron` to determine
the user's data directory, which of course, isn't available when
running in the CLI. So this adds a fallback to the same mechanic
for CLI should this code not be loaded in Electron.

Change-type: patch
Signed-off-by: Jonas Hermsmeier <jhermsmeier@gmail.com>
2018-08-07 17:14:53 +02:00
Alexis Svinartchouk
d0ee569989 Merge pull request #2439 from resin-io/fix-shared-tests
fix(test): Move available-drives, flash-state and selection-state tests to gui tests
2018-08-07 13:51:47 +02:00
Alexis Svinartchouk
92d969b075 fix(test): Move tests to correct scope
Move available-drives, flash-state and selection-state tests to gui
tests. These files only test gui code and make `make test-cli` fail.

Change-type: patch
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2018-08-07 09:22:29 +02:00
Lorenzo Alberto Maria Ambrosi
49b70d0efd Merge pull request #2296 from resin-io/fix-usbboot-on-linux
fix(sdk): load usbboot adapter on start
2018-08-07 04:36:39 +02:00
Alexis Svinartchouk
26779ef1fb fix(sdk): Load usbboot adapter on start
Change-type: patch
Changelog-entry: Load usbboot adapter on start on GNU/Linux if running as root.
Signed-off-by: Alexis Svinartchouk <alexis@resin.io>
2018-08-07 04:01:13 +02:00
Lorenzo Alberto Maria Ambrosi
fd19af23a6 Merge pull request #2436 from resin-io/update-mountutils-1.3.15
upgrade(package): Bump mountutils to v1.3.15
2018-08-07 03:59:54 +02:00
Jonas Hermsmeier
f798fef212 upgrade(package): Bump mountutils to v1.3.15
Change-type: patch
Signed-off-by: Jonas Hermsmeier <jhermsmeier@gmail.com>
2018-08-07 03:11:10 +02:00
Lorenzo Alberto Maria Ambrosi
c74eab4fb5 Merge pull request #2435 from resin-io/update-drivelist-6.4.0
upgrade(package): Bump drivelist to v6.4.0
2018-08-07 01:53:29 +02:00
Lorenzo Alberto Maria Ambrosi
6a0198639f Merge branch 'master' into update-drivelist-6.4.0 2018-08-06 18:04:51 +02:00
Lorenzo Alberto Maria Ambrosi
8c870f2db8 Merge pull request #2430 from resin-io/fix-blockmap-checksum-error
fix(writer): Set EVALIDATION on blockmap checksum errors
2018-08-06 17:58:42 +02:00
Jonas Hermsmeier
73d287e7ee upgrade(package): Bump drivelist to v6.4.0
Change-type: patch
Signed-off-by: Jonas Hermsmeier <jhermsmeier@gmail.com>
2018-08-02 22:40:25 +02:00
Jonas Hermsmeier
9eb3eea3f1 fix(writer): Set EVALIDATION on blockmap checksum errors
This patches validation errors coming form the `blockmap` module to have
the `EVALIDATION` error code, in order to trigger the appropriate code
paths and analytics.

Change-type: patch
Signed-off-by: Jonas Hermsmeier <jhermsmeier@gmail.com>
2018-08-01 20:54:08 +02:00
Jonas Hermsmeier
df769396b1 Merge pull request #2422 from Jacalz/solus-instructions
doc(README): add install and uninstall instructions for Solus
2018-07-31 21:30:33 +02:00
Jacob
c2e47ca9dc doc(README): add install and uninstall instructions for Solus
This adds the required steps to installing and uninstalling Etcher on Solus Linux.

Change-Type: patch
Changelog-Entry: Add instructions for installing and uninstalling on Solus.
2018-07-21 15:30:53 +02:00
Jonas Hermsmeier
b348159e0e Merge pull request #2418 from resin-io/private-module
resinci: Set private: true in package.json to avoid running npm builds
2018-07-18 17:54:37 +02:00
John (Jack) Brown
45b62f0e77 resinci: Set private: true in package.json to avoid running npm builds
Change-type: patch
Signed-off-by: Jack Brown <jack@resin.io>
2018-07-18 07:25:33 -07:00
Jonas Hermsmeier
1fb420c2fc Merge pull request #2416 from resin-io/enable-production-react
chore(webpack): Set NODE_ENV to production for React / WebPack
2018-07-10 17:08:12 +02:00
Jonas Hermsmeier
b4f2bc1cb3 chore(webpack): Set NODE_ENV to production
This enables production builds for React

Change-Type: patch
2018-07-09 17:34:03 +02:00
Jonas Hermsmeier
d6cc182da2 Merge pull request #2412 from resin-io/update-winusb-driver
upgrade(package): Update winusb-driver-generator
2018-07-09 17:30:13 +02:00
Jonas Hermsmeier
9d7baa86aa Merge pull request #2413 from resin-io/fix-fs-promisify
fix(gui): Fix missing promisify in file picker model
2018-07-05 20:14:36 +02:00
Jonas Hermsmeier
872cd90dc6 fix(gui): Fix missing promisify in file picker model
Change-Type: patch
2018-07-05 18:52:04 +02:00
Jonas Hermsmeier
00ab816791 upgrade(package): Update winusb-driver-generator
This updates `winusb-driver-generator` to the latest version,
which supports building under VS 2015 and running under Electron 2.0+

Change-Type: patch
2018-07-04 15:12:45 +02:00
Jonas Hermsmeier
2a9e9962e8 Merge pull request #2405 from resin-io/file-selection-constraint
feat(gui): Enable device specific constraints for file selection
2018-07-03 17:08:39 +02:00
Jonas Hermsmeier
ed25dd931e feat(gui): Enable device specific constraints for file selection
This adds the ability to restrict the file selection to a given device,
only making its mountpoints accessible.

Change-Type: patch
2018-07-03 15:39:49 +02:00
Jonas Hermsmeier
66031f1bc2 Merge pull request #2402 from resin-io/fix-missing-settings
fix(app): Fix settings being unavailable when packaged
2018-06-20 20:46:30 +02:00
Jonas Hermsmeier
a902872880 fix(app): Fix settings being unavailable when packaged
This fixes an issue where the settings model would be missing
from Etcher when packaged, as it's used in two different contexts;
namely the webpack bundle and the main process.

Change-Type: patch
2018-06-20 20:05:56 +02:00
Jonas Hermsmeier
4c2d440871 Merge pull request #2401 from resin-io/file-picker-separators
refactor(gui): Add separating borders to file selector
2018-06-20 20:01:07 +02:00
Jonas Hermsmeier
0da17de422 refactor(gui): Add separating borders to file selector
This adds thin gray borders to the control surfaces in
the file selector for better visual distinction

Change-Type: patch
2018-06-20 19:03:40 +02:00
Jonas Hermsmeier
07025ae76b Merge pull request #2400 from resin-io/file-picker-path
feat(gui): Add full filename to file selector
2018-06-20 19:01:38 +02:00
Jonas Hermsmeier
d99fe944f3 feat(gui): Add full filename to file selector
This adds the display of the full filename to the file selector.

Change-Type: minor
2018-06-20 18:31:09 +02:00
Jonas Hermsmeier
408b2a473e Merge pull request #2388 from resin-io/refactor-file-picker
refactor(gui): Refactor file picker fs I/O
2018-06-12 21:15:07 +02:00
Jonas Hermsmeier
fc22e9e28a refactor(gui): Refactor file picker fs I/O
This refactors the experimental file picker to avoid fs i/o
in as many places as possible to improve performance.
Further, rendering performance is improved by avoiding unnecessary
element state changes invalidating components.
Also, recent files & favorites have been temporarily disabled
due to lack of need for Etcher Pro.

Change-Type: patch
2018-06-12 18:51:58 +02:00
Jonas Hermsmeier
d1c44ab7b1 Merge pull request #2383 from resin-io/webpack-exclude-node
fix(webpack): Exclude all node externals / node_modules
2018-06-08 17:36:29 +02:00
Jonas Hermsmeier
4ddac50d9b fix(webpack): Exclude all node externals / node_modules
This adds `webpack-node-externals` to exclude node_modules,
immensely reducing bundle size and avoiding complex exclusion rules
for the etcher-sdk

Change-Type: patch
2018-06-08 16:56:21 +02:00
Jonas Hermsmeier
7208ad67f1 Merge pull request #2376 from resin-io/fix-infinite-digest
fix(gui): Fix an inifinite digest loop trigger
2018-05-31 15:01:27 +02:00
Jonas Hermsmeier
fffdeb1320 fix(gui): Fix an inifinite digest loop trigger
This fixes a guard against infinite digest loop triggering
that was erronously dropped during a rebase.

Change-Type: patch
2018-05-30 20:34:38 +02:00
Jonas Hermsmeier
e8fa7d8812 Merge pull request #2375 from resin-io/update-lodash
upgrade(package): Update lodash to 4.17.10
2018-05-30 16:49:36 +02:00
Jonas Hermsmeier
dfdb92957e Merge pull request #2362 from resin-io/file-picker-performance
fix(GUI): file-picker performance and design improvements
2018-05-30 14:18:17 +02:00
Jonas Hermsmeier
441069f04b Merge pull request #2373 from resin-io/fix-drive-blacklist
fix(gui): Fix error with empty drive blacklist
2018-05-30 13:37:45 +02:00
Jonas Hermsmeier
201995eb90 upgrade(package): Update lodash to 4.17.10
This updates `lodash` to mitigate a prototype pollution vulnerability.
See https://nodesecurity.io/advisories/577

Change-Type: patch
2018-05-30 13:17:20 +02:00
Benedict Aas
5863319c0b fix(GUI): file-picker performance and design improvements
- Replace onClick arrow functions in all components that use them for
  efficiency reasons: 300-500% speed-up
- Sort by folders and ignore case for better UX
- Remove use of `rendition.Button` in files, leading to a 10-20%
  performance increase when browsing files
- Proper sidebar width and spacing
- Recents and favorites are now filtered by existence async for a tiny
  performance improvement
- Make Breadcrumbs and Icon pure components to stop frequent re-rendering
- Initial support for array constraints
- Use first constraint as initial path instead of homedir if a
  constraint is set
- Use correct design height on modal, `calc(100vh - 20px)`
- Reset scroll position when browsing a new folder
- Fuse Bluebird `.map()` and `.reduce()` in
  `files.getAllFilesMetadataAsync`.
- Use `localeCompare`'s own case-insensitive option instead of calling
  `.toLowerCase()` twice on `n-2` files compared.
- Use 16px font sizes in sidebar and files to match design.
- Disable `$locationProvider.html5Mode.rewriteLinks`, which seemed to
  take 50ms of the directory changing time.
- Leave file extension as-is in `files.getFileMetadataSync` and the
  async counterpart for a very minor performance improvement.

Change-Type: patch
2018-05-30 12:39:59 +02:00
Jonas Hermsmeier
2986d85b26 fix(gui): Fix error with empty drive blacklist
This fixes an error occuring if the drive blacklist
is empty, and not split correctly

Change-Type: patch
2018-05-30 12:33:12 +02:00
Jonas Hermsmeier
f312457f35 Merge pull request #2372 from resin-io/file-picker-drag-fix
fix(GUI): restrict webkit drag to header
2018-05-30 12:12:45 +02:00
Jonas Hermsmeier
de501f5ba3 Merge pull request #2369 from resin-io/feature-settings
feat: Use settings for feature control
2018-05-29 23:47:58 +02:00
Jonas Hermsmeier
c5e5141b21 refactor(local-settings): Log JSON parse errors 2018-05-29 22:06:41 +02:00
Jonas Hermsmeier
c08cf61d0c chore(app): Use settings instead of env vars
Change-Type: patch
2018-05-29 22:06:41 +02:00
Jonas Hermsmeier
6728382141 feat: Use settings for feature control
Change-Type: minor
2018-05-29 22:06:40 +02:00
Jonas Hermsmeier
7c3f104d1b Merge pull request #2368 from resin-io/refactor-settings
feat(gui): Persist local settings to config file
2018-05-29 22:06:02 +02:00
Jonas Hermsmeier
ad6be11bbc refactor(store): Return unsubscribe directly 2018-05-29 17:36:51 +02:00
Benedict Aas
f09faf6645 minifix(GUI): move success banner back down (#2367)
Change-Type: patch
2018-05-29 12:56:54 +01:00
Benedict Aas
117a7762e1 fix(GUI): restrict webkit drag to header
We ensure that the `-webkit-app-region` attribute is only set to `drag`
on the header element and we explicitly disable it on modals, as this
has unintended behaviour on a non-draggable window with touch-screens.

Change-Type: patch
2018-05-29 11:23:54 +01:00
Jonas Hermsmeier
3d47f494a8 fix(app): Fix config path on Windows, typos 2018-05-28 17:25:22 +02:00
Jonas Hermsmeier
e0ebdc9045 fix(test): Fix lint errors & tests 2018-05-25 20:35:59 +02:00
Jonas Hermsmeier
53f8e9328d feat(app): Make store change-observable
This adds true change observability to the store,
as the `.subscribe()` callback triggers with every dispatch,
even if the data didn't change.

Now `store.observe(onChange)` can be used to only be notified
once the state data actually changes

Change-Type: minor
2018-05-25 20:35:59 +02:00
Jonas Hermsmeier
687e0b563b refactor(gui): Move shared models to app/models 2018-05-25 20:35:59 +02:00
Jonas Hermsmeier
6232cc7d49 test(settings): Update test specs accordingly
Change-Type: patch
2018-05-25 20:35:59 +02:00
Jonas Hermsmeier
2a6670a404 refactor: Remove use of localStorage for local settings
Change-Type: minor
2018-05-23 21:20:51 +02:00
Jonas Hermsmeier
447efc7096 refactor: Move shared/store.js -> gui/app/models/store.js 2018-05-23 21:20:50 +02:00
Benedict Aas
c47878202d feat(GUI): center content independent to window resolution (#2299)
We pave way for different sizes of Etcher windows by dynamically
centering the content with flexbox.

Connects-To: #2263
Closes: #2241
Change-Type: patch
Changelog-Entry: Center content independent to window resolution.
2018-05-23 20:10:02 +01:00
Jonas Hermsmeier
349076bf34 Merge pull request #2353 from resin-io/webber-packer
chore(package): Add npm run script for webpack
2018-05-23 19:43:22 +02:00
Jonas Hermsmeier
1748bf2e2a chore(package): Add npm run script for webpack
Make life simpler

Change-Type: patch
2018-05-22 18:44:59 +02:00
Jonas Hermsmeier
d9a7730511 test(eslint): Fix JSX not being linted (#2358)
Change-Type: patch
2018-05-21 11:28:22 +01:00
Jonas Hermsmeier
4a239cc217 upgrade(package): Update React to v16 (#2355)
Change-Type: patch
2018-05-21 11:23:42 +01:00
Benedict Aas
ce2534c5b7 minifix(GUI): resolve react missing key field warning (#2354)
We attach key fields where necessary to make the warnings go away.

Change-Type: patch
2018-05-21 11:23:20 +01:00
Jonas Hermsmeier
3083f5fd55 Merge pull request #2351 from resin-io/fix-username-spaces-diskpart
fix(diskpart): Fix diskpart argv when tmpdir contains spaces
2018-05-18 17:46:42 +02:00
Jonas Hermsmeier
2045066b16 fix(diskpart): Fix diskpart argv when tmpdir contains spaces
This escapes the diskpart script filename when shelling out,
to avoid failure when the username and thus the `os.tmpdir()` path
contains spaces.

Change-Type: patch
2018-05-17 18:03:41 +02:00
Jonas Hermsmeier
995177498f Merge pull request #2349 from resin-io/add-files-module
fix: add missing files module
2018-05-17 18:02:55 +02:00
Benedict Aas
c00b7b62d6 fix: add missing files module
We add a convenience module for file and path operations.
Tests included.

Change-Type: patch
2018-05-17 15:34:34 +01:00
Benedict Aas
93b772f197 fix: ensure file-picker is slicing arrays (#2350)
We ensure the file-picker is slicing arrays when the localStorage values
aren't available.

Change-Type: patch
2018-05-17 10:40:19 +01:00
Benedict Aas
7782f94daa feat(GUI): add electron-native file-picker component (#2333)
We add a file-picker written with Rendition/React. It is activated with
the `ETCHER_EXPERIMENTAL_FILE_PICKER` environment variable. Further
customisation can be done with the `ETCHER_FILE_BROWSER_CONSTRAIN_FOLDER`
variable that takes a path and allows one to constrain the file-picker to
a folder.

Related: https://github.com/resin-io/etcher/issues/2238
Related: https://github.com/resin-io/etcher/issues/2285
Change-Type: patch
Changelog-Entry: Add electron-native file-picker component.
2018-05-16 20:34:04 +01:00
Jonas Hermsmeier
7c97dc8004 Merge pull request #2346 from CherryDT/master
Fix devtools key binding for Windows in SUPPORT.md
2018-05-16 21:10:25 +02:00
Benedict Aas
34ce00e2d5 feat(GUI): hide unsafe mode option with env var (#2347)
We hide the unsafe mode option toggle with an env var
`ETCHER_HIDE_UNSAFE_MODE` that also enables unsafe mode.

Closes: https://github.com/resin-io/etcher/issues/2243
Change-Type: patch
Changelog-Entry: Hide unsafe mode option toggle with an env var.
2018-05-16 19:52:55 +01:00
CherryDT
702658cca5 Fix devtools key binding for Windows in SUPPORT.md 2018-05-16 16:39:33 +02:00
Benedict Aas
e472fe0276 feat: blacklist devices by device path (#2345)
We use `devicePath` instead of `device` to blacklist drives using the
`ETCHER_BLACKLISTED_DRIVES` environment variable.

Closes: https://github.com/resin-io/etcher/issues/2264
Change-Type: patch
2018-05-16 15:28:10 +01:00
Jonas Hermsmeier
fb1c381ab7 Merge pull request #2343 from resin-io/disable-notifications
feat(gui): Add desktop notification setting
Close #2254
2018-05-16 00:51:49 +02:00
Jonas Hermsmeier
03c7998c11 feat(gui): Add desktop notification setting
This adds a setting to disable desktop notifications, to be controlled
via configuration file

Change-Type: feat
2018-05-15 18:58:10 +02:00
Benedict Aas
35729fc36b feat(GUI): use design background and drive size ordering (#2341)
We use the new design background color, and order the drive step size in
accordance with the new design as well.

Related: https://github.com/resin-io/etcher/issues/2310
Change-Type: patch
Changelog-Entry: Use new design background color and drive step size
ordering.
2018-05-15 14:23:33 +01:00
Benedict Aas
f6ce603e45 feat(GUI): add convenience localstorage class (#2276)
* feat(GUI): add convenience localstorage class

We add a class `Storage` and accompanying helper methods that makes
localStorage usage easier.

Change-Type: patch
Changelog-Entry: Add a convenience Storage class on top of localStorage.
2018-05-15 11:59:36 +01:00
Benedict Aas
81a75ca955 feat(GUI): use new design blue and spacing (#2327)
We use the new design blue, spacing, and order of step buttons.

Closes: https://github.com/resin-io/etcher/issues/2310
Change-Type: patch
2018-05-14 15:58:45 +01:00
Jonas Hermsmeier
b57c9a51f8 Merge pull request #2331 from resin-io/env-analytics
feat(gui): Add ability to set analytics tokens via env
Close #2329
2018-05-11 20:04:21 +02:00
Jonas Hermsmeier
df396966b0 Merge pull request #2332 from resin-io/disable-update-notify
minifix(gui): Don't check for updates when in resin
2018-05-11 20:03:45 +02:00
Jonas Hermsmeier
b8897e0193 minifix(gui): Don't check for updates when in resin
This disabled Etcher checking for updates & showing update notifications
if running under resinOS with update locks enabled

Change-Type: patch
2018-05-11 16:36:14 +02:00
Jonas Hermsmeier
150e8112ea feat(gui): Add ability to set analytics tokens via env
This adds the ability to set the Sentry & Mixpanel API tokens
via environment variables.

Change-Type: patch
2018-05-11 16:25:11 +02:00
Jonas Hermsmeier
196f16b941 Merge pull request #2326 from resin-io/resin-update-lock
feat(gui): Add resin update lock based on inactivity
2018-05-10 21:07:01 +02:00
Benedict Aas
21cb7a4847 feat(GUI): env var toggle autoselecting all valid drives (#2306)
We introduce an environment variable
`ETCHER_DISABLE_EXPLICIT_DRIVE_SELECTION` that both enables
autoselection of drives and disables explicit drive selection by hiding
the buttons allowing this. All valid drives are autoselected, i.e. any
drive-image pair that does not result in an error, however warnings are
accepted.

Closes: https://github.com/resin-io/etcher/issues/2262
Change-Type: patch
Changelog-Entry: Introduce env var to toggle autoselection of all
drives.
2018-05-10 18:53:53 +01:00
Jonas Hermsmeier
bb2dac7504 feat(gui): Add resin update lock based on inactivity
This adds functionality to acquire & release the update lock
when running under resinOS, re-using the `ELECTRON_RESIN_UPDATE_LOCK`
environment variable from `resin-electronjs`.

Further this adds the `ETCHER_INTERACTION_TIMEOUT_MS` env var, to
facilitate adjusting the inactivity period required to release the lock.

Change-Type: minor
2018-05-10 19:15:31 +02:00
Jonas Hermsmeier
f5fd2f2be3 Merge pull request #2325 from resin-io/update-drivelist
upgrade(package): Bump drivelist 6.1.7 -> 6.2.2
Close #2235
2018-05-10 14:20:38 +02:00
Jonas Hermsmeier
e6ea3879c3 upgrade(package): Bump drivelist 6.1.7 -> 6.2.2
This will enable use of unique device paths on Linux

Change-Type: patch
2018-05-10 13:33:50 +02:00
Jonas Hermsmeier
c07895d418 Merge pull request #2319 from resin-io/update-keyserver
doc(README): Use ubuntu keyserver for apt-key
2018-05-09 21:04:49 +02:00
Jonas Hermsmeier
58fb1cf4c3 Merge pull request #2318 from resin-io/kiosk
minifix(gui): Only enable Kiosk Mode when FULLSCREEN is set
2018-05-09 20:09:29 +02:00
Jonas Hermsmeier
52cc8cb8fc doc(README): Use ubuntu keyserver for apt-key
As pgp.mit.edu has become extremely unreliable, this switches to
keyserver.ubuntu.com for retrieval of package keys

Change-Type: patch
2018-05-09 17:30:40 +02:00
Benedict Aas
1b30dab8eb fix(webpack): don't rewrite import paths inside node_modules (#2195)
We ensure that paths inside node_modules files are kept untouched, as
currently the RegExp can match 'shared' folders inside those and rewrite
paths, breaking them.

Change-Type: patch
2018-05-09 16:09:17 +01:00
Jonas Hermsmeier
40df4a94a7 minifix(gui): Only enable Kiosk Mode when FULLSCREEN is set
This fixes the `kiosk` setting always being true, and causing
the operating system's desktop to disappear.

Change-Type: patch
2018-05-09 17:04:38 +02:00
Jonas Hermsmeier
262d06f035 Merge pull request #2311 from resin-io/config-file
feat(gui): Add ability to read settings from a config file
Close #1356
2018-05-09 17:00:36 +02:00
Jonas Hermsmeier
408ab99774 Merge pull request #1921 from resin-io/link-to-windows-usbboot-drivers
feat(GUI): link to drivers when clicking a driverless usbboot device
2018-05-09 16:48:00 +02:00
Jonas Hermsmeier
28cb21db13 Merge pull request #2292 from resin-io/bench-verify
feat(writer): Use xxHash instead of SHA512 for verification
2018-05-09 16:46:02 +02:00
Benedict Aas
7f37f4ca41 feat(GUI): add font-awesome (#2177)
We add font-awesome icons as this is more in-line with the designs.

Change-Type: patch
Changelog-Entry: Add font-awesome.
2018-05-09 15:44:03 +01:00
Jonas Hermsmeier
5f85258e84 feat(gui): Add ability to read settings from a config file
This adds the capability to configure settings via a `.etcher.json` file,
either in the user's home directory, or the current working directory.
In the case of the home directory, the config file is `$HOME/.config/etcher/config.json`,
while on Windows `$HOME/.etcher.json` is used.
The defined settings are merged with localStorage settings, and preceding
configuration files.
If both are present, the current working directory takes precedence.

Change-Type: minor
Changelog-Entry: Add support for configuration files
2018-05-09 16:22:07 +02:00
Benedict Aas
cde1776a2d feat(GUI): use gtk3 dark theme mode (#2314)
We enable the `darkTheme` mode for GTK-3 applications (mainly Linux)
that suits Etcher's dark theme better, making the window title bar dark.

Change-Type: patch
Changelog-Entry: Use GTK-3 darkTheme mode.
2018-05-09 11:13:14 +01:00
Benedict Aas
7f6303391a feat(GUI): add env var to toggle fullscreen (#2313)
We add an environment variable to toggle Etcher in fullscreen.

Closes: https://github.com/resin-io/etcher/issues/2307
Change-Type: patch
Changelog-Entry: Add environment variable to toggle fullscreen.
2018-05-09 11:08:15 +01:00
Benedict Aas
66c7806cfa feat(GUI): blacklist drives with an env var (#2315)
We add an environment variable `ETCHER_BLACKLISTED_DRIVES` that allows
us to filter certain drives from ever showing up in Etcher with comma
separated device paths, e.g. `/dev/sda,/dev/sdb,/dev/mmcblk0`.

Closes: https://github.com/resin-io/etcher/issues/2264
Change-Type: patch
Changelog-Entry: Allow blacklisting of drives through and environment
variable ETCHER_BLACKLISTED_DRIVES.
2018-05-09 11:06:18 +01:00
Benedict Aas
2cdb6945ba feat(GUI): show selected drives below drive step (#2309)
We add a list of selected drives below the drive selection step, able to
accommodate four lines of drives before scrolling occurs.

Closes: https://github.com/resin-io/etcher/issues/2263
Change-Type: patch
Changelog-Entry: Show selected drives below drive selection step.
2018-05-08 17:45:27 +01:00
Benedict Aas
ca45855ed7 feat(GUI): add drive quantity to flash analytics (#2298)
We add a field `driveCount` to the flash analytics events in the image
writer.

Change-Type: patch
2018-05-08 10:56:15 +01:00
Benedict Aas
07ed90ed11 minifix: add jsx files to gitattributes and attribute jviotti (#2302)
Change-Type: patch
2018-05-04 14:46:27 +01:00
Benedict Aas
c1b97b1b44 minifix(GUI): negate predicate to show help icon (#2300)
Change-Type: patch
2018-05-03 11:00:37 +01:00
Benedict Aas
674019ea75 feat(GUI): add button to cancel flash process (#2301)
We add a cancel button next to the flash progress bar that gracefully
aborts the flash process.

Closes: https://github.com/resin-io/etcher/issues/1791
Closes: https://github.com/resin-io/etcher/issues/2234
Closes: https://github.com/resin-io/etcher/issues/2245
Change-Type: patch
Changelog-Entry: Add a button to cancel the flash process.
2018-05-03 10:58:15 +01:00
Jonas Hermsmeier
8f762484f2 feat(gui): Add CTA in drivelist, update drive download modal 2018-05-02 23:37:15 +02:00
Jonas Hermsmeier
4174991345 feat(gui): Add simple confirmation modal 2018-05-02 23:21:02 +02:00
Benedict Aas
71064cc760 fix(GUI): fix multi-writes analytics (#2295)
We make the analytics block into a function `handleErrorLogging` and
use it in the fail event that happens during multi-writes. Previously
error events would be handled when single drives were flashed on Promise
rejection, instead we now only handle the Promise rejection when all
devices fail as a special event.

Change-Type: patch
Changelog-Entry: Fix multi-writes analytics by reusing existing logic in
multi-write events.
2018-05-02 22:02:31 +01:00
Juan Cruz Viotti
4c40c8ff30 feat(GUI): link to drivers when clicking a driverless usbboot device
Step 2 until we support installing the drivers from within Etcher. This
also introduces an "Open drive link" Mixpanel event.

See: https://www.raspberrypi.org/documentation/hardware/computemodule/cm-emmc-flashing.md
See: https://github.com/resin-io/etcher/pull/1892
Change-Type: patch
Changelog-Entry: Download usbboot drivers installer when clicking a driverless usbboot device on Windows.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-05-02 22:10:49 +02:00
Benedict Aas
d7211b130b feat(GUI): allow disabling links and hiding help link (#2290)
We allow users to pass an env var `ETCHER_DISABLE_EXTERNAL_LINKS` to
disable external links and hide links rendered useless by the change
such as the help icon.

Closes: https://github.com/resin-io/etcher/issues/2246
Closes: https://github.com/resin-io/etcher/issues/2247
Change-Type: patch
Changelog-Entry: Allow disabling links and hiding help link with an env var.
2018-05-02 17:29:08 +01:00
Jonas Hermsmeier
e40d5a0a5d Merge pull request #2291 from resin-io/publish-symantec
doc: Update MAINTAINERS.md with Symantec Whitelisting
2018-04-28 00:27:34 +02:00
Jonas Hermsmeier
553fbf1a77 minifix(writer): Increase HWM for verification readstream
Change-Type: patch
2018-04-27 22:29:03 +02:00
Jonas Hermsmeier
d3a4753b79 feat(writer): Use xxHash instead of SHA512 for verification
This switches from SHA512 to xxHash for verification hashing,
as xxHash provides more throughput.

Change-Type: patch
2018-04-27 21:51:05 +02:00
Jonas Hermsmeier
12cc0de571 doc: Update MAINTAINERS.md with Symantec Whitelisting
This adds instructions for submitting Etcher for false positive detection
to Symantec Endpoint Protection.

Change-Type: patch
2018-04-27 21:09:28 +02:00
Jonas Hermsmeier
cbd531e161 Merge pull request #2269 from resin-io/release-1.4.4
Release v1.4.4
2018-04-26 19:06:43 +02:00
Jonas Hermsmeier
a8bbe02e21 v1.4.4 2018-04-25 20:58:17 +02:00
Jonas Hermsmeier
6605d5ee63 Merge pull request #2275 from resin-io/revert-image-data
fix(tests): Revert unintended change to raspberrypi-raw.dmg
2018-04-25 17:36:36 +02:00
Jonas Hermsmeier
df8bacd82e fix(tests): Revert unintended change to raspberrypi-raw.dmg
This file was accidentally changed due to a globally executed search & replace

Change-Type: patch
2018-04-25 16:34:12 +02:00
Benedict Aas
ee831da52d minifix: replace succeeded with successful in messages (#2273)
Change-Type: patch
2018-04-25 15:08:46 +01:00
Jonas Hermsmeier
8f969374c7 Merge pull request #2272 from resin-io/fix-store-warning-deselect
fix(store): keep single warning-drives selected
2018-04-25 14:39:58 +02:00
Benedict Aas
5a788b04b5 fix(store): keep single warning-drives selected
We ensure that drive-image pairs with warnings don't get deselected when
there is only one drive available. This happenened because there was no
check for any previous selected devices. Comes with a test case.

Fixes: https://github.com/resin-io/etcher/issues/2267
Change-Type: patch
Changelog-Entry: Keep single warning-drive-image pairs selected.
2018-04-25 00:49:42 +01:00
Benedict Aas
b88a45aa79 refactor(GUI): make the finish notification message concise (#2268)
We make the finish notification message print the device name as usual
when there's one target, and instead list quantity of successful and
failed devices when there are multiple. Previously it would list all
device names, and wouldn't specify how many were successful or failures.

Change-Type: patch
2018-04-24 22:04:36 +01:00
Jonas Hermsmeier
3c20a056e6 Merge pull request #2228 from resin-io/change-succeeded-successful
refactor: use word successful instead of succeeded
2018-04-24 18:24:05 +02:00
Benedict Aas
82a57d34b8 fix(GUI): remove success screen dots with a quantity of zero (#2227)
We remove success screen dots that are zero, which mainly means that the
error dot disappears as it shouldn't currently be possible to end up
with zero successful devices on that screen.

Change-Type: patch
2018-04-23 18:33:31 +01:00
Benedict Aas
c4d7076fe8 refactor: use word successful instead of succeeded
We replace 'succeeded' with 'successful' throughout the codebase.

Change-Type: patch
2018-04-23 18:31:44 +01:00
Jonas Hermsmeier
00b11157b2 Merge pull request #2217 from resin-io/release-1.4.3
Release v1.4.3
2018-04-20 21:22:11 +02:00
Jonas Hermsmeier
b63bb1ac0c v1.4.3 2018-04-20 15:46:38 +02:00
Jonas Hermsmeier
882d0ecba8 Merge pull request #2219 from resin-io/fix-zero-zero
fix(gui): Fix zero-zero devices when verify is disabled
2018-04-20 15:45:47 +02:00
Jonas Hermsmeier
963f1a11eb fix(gui): Fix zero-zero devices when verify is disabled
This fixes a state where the success screen would display
zero succeeded and zero failed devices if verification was
turned off. This could occur due to the "done" event being
emitted before the next progress event could set the relevant data.

Change-Type: patch
2018-04-20 01:04:30 +02:00
Jonas Hermsmeier
ba8acb40ec Merge pull request #2218 from resin-io/fix-flash-result-errors
fix(gui): De-serialize errors from flashResults
2018-04-19 22:56:34 +02:00
Jonas Hermsmeier
1d4ea2164f fix(gui): De-serialize errors from flashResults
Change-Type: patch
2018-04-19 21:46:03 +02:00
Jonas Hermsmeier
0199243ce9 Merge pull request #2216 from resin-io/fix-usbboot-blobs
fix(usbboot): Move blob handling to SDK
2018-04-19 17:46:35 +02:00
Jonas Hermsmeier
4c8b97afb3 fix(usbboot): Move blob handling to SDK
This moves the usbboot blob handling into the SDK to avoid
root dirname conflicts through shimmed __dirname in bundled UI
and different contexts of execution.

Change-Type: patch
2018-04-19 16:54:23 +02:00
Jonas Hermsmeier
3bac0225e5 refactor(usbboot): Move lib/blobs/usbboot/ -> lib/sdk/adapters/usbboot/blobs 2018-04-19 15:48:59 +02:00
Jonas Hermsmeier
7d13c8d9be Merge pull request #2213 from resin-io/release-1.4.2
Release v1.4.2
2018-04-19 00:34:03 +02:00
Jonas Hermsmeier
4190a87171 v1.4.2 2018-04-18 23:09:49 +02:00
Jonas Hermsmeier
69e719c4c7 Merge pull request #2215 from resin-io/revert-diskclean
Revert "feat(lib): Use win-drive-clean instead of diskpart"
2018-04-18 23:07:49 +02:00
Jonas Hermsmeier
c5df8742c5 Merge pull request #2214 from resin-io/fix-usbboot-macos
fix(drive-scanner): Fix usbboot blob path when bundled
2018-04-18 22:48:25 +02:00
Jonas Hermsmeier
5867edcc70 Revert "feat(lib): Use win-drive-clean instead of diskpart"
This reverts commit 47fc1b7357
in order to prevent a possible regression, until properly investigated
and fixed.

Change-Type: patch
Changelog-Entry: Revert using native binding to clean disks on Windows
2018-04-18 21:55:08 +02:00
Jonas Hermsmeier
b3a7255eed fix(drive-scanner): Fix usbboot blob path when bundled
This fixes the usbboot blobs path when the application is bundled & packaged.

Change-Type: fix
Changelog-Entry: Fix usbboot blob loading
2018-04-18 21:42:53 +02:00
Jonas Hermsmeier
4179def119 Merge pull request #2211 from resin-io/remove-iserror
fix(image-writer): Remove use of _.isError
2018-04-18 19:12:47 +02:00
Jonas Hermsmeier
ef9b897394 Merge pull request #2198 from resin-io/drive-label-fallback
fix(GUI): display untitled device when device lacks description
2018-04-18 18:37:26 +02:00
Jonas Hermsmeier
c225dd89c6 fix(image-writer): Remove use of _.isError
`_.isError()` returns `true` for anything that has a `name` and `message`
property, causing the check here to always keep the plain object as error.

Change-Type: patch
2018-04-18 17:44:14 +02:00
Benedict Aas
d59ebad167 fix(GUI): display untitled device when device lacks description
We fallback to `'Untitled Device'` when the device lacks a
`.description` field.

Change-Type: patch
Changelog-Entry: Display Untitled Device when the device lacks a
description field.
2018-04-18 16:33:39 +01:00
Jonas Hermsmeier
347932b213 Merge pull request #2209 from resin-io/filter-raid-devices
fix(adapters): Always ignore RAID attached devices
2018-04-17 20:09:31 +02:00
Benedict Aas
32bc615e78 feat(GUI): display succeeded and failed devices on finish screen (#2206)
We display the quantity of succeeded and failed devices using status
dots on the finish screen.

Change-Type: patch
Changelog-Entry: Display succeeded and failed device quantities on the
finish screen.
2018-04-17 15:52:02 +01:00
Jonas Hermsmeier
355373f24d fix(adapters): Always ignore RAID attached devices
Change-Type: patch
Changelog-Entry: Exclude RAID devices from drive selection list
2018-04-17 16:14:05 +02:00
Jonas Hermsmeier
a044d2fe86 Merge pull request #2207 from resin-io/update-drivelist
upgrade(package): Update drivelist 6.1.5 -> 6.1.7
2018-04-17 13:12:38 +02:00
Jonas Hermsmeier
1d44eff896 upgrade(package): Update drivelist 6.1.5 -> 6.1.7
This fixes a ReferenceError that could occur when the DeviceNode was null,
as well as devices being null when run after the system recovers from sleep / standby.

Change-Type: patch
2018-04-17 00:36:54 +02:00
Jonas Hermsmeier
c1b746ed51 Merge pull request #2205 from resin-io/fix-ci-python
fix(ci): Fix pip installation
2018-04-16 22:35:27 +02:00
Jonas Hermsmeier
3381ad042b Merge pull request #2199 from resin-io/fix-ipc-user-error
fix(child-writer): Fix handling of user errors over IPC
2018-04-16 22:34:57 +02:00
Benedict Aas
a1b5766a71 minifeat(GUI): prefix multiple devices label with quantity (#2204)
Change the `Multiple Devices (n)` label on selected devices to a
quantity-prefixed form `n Devices`.

Change-Type: patch
2018-04-16 20:11:44 +01:00
Benedict Aas
aeeb1d4294 feat(GUI): remove unnecessary status dots (#2202)
We remove usage of the status dots except when failed devices occur, in
which case we still display the red failed dot and quantity. We also use
singular and plural depending on the quantity of failed devices.

Change-Type: patch
2018-04-16 20:11:19 +01:00
Benedict Aas
7ceec47246 feat(GUI): make the progress button blue on verification (#2203)
We make the progress button blue on verification.

Change-Type: patch
Changelog-Entry: Make the progress button blue on verification.
2018-04-16 20:06:40 +01:00
Jonas Hermsmeier
ede510139f fix(ci): Fix pip installation
The pip tarball URL now redirects to another location, which
caused `curl` to fail, as the follow-redirects option wasn't specified.

Change-Type: patch
2018-04-16 20:53:36 +02:00
Jonas Hermsmeier
cc848ef9f2 fix(child-writer): Fix handling of user errors over IPC
This fixes transmission of user errors over IPC, as the `report`
property was previously missing. Further it also adds more properties
to `errors.toJSON`, like `syscall`, `errno`, etc. and re-uses the method
for failure signalling.

Change-Type: patch
2018-04-13 18:36:29 +02:00
Jonas Hermsmeier
1c43ee1b18 Merge pull request #2192 from resin-io/release-1.4.1
Release v1.4.1
2018-04-11 00:14:21 +02:00
Jonas Hermsmeier
741f540f77 v1.4.1 2018-04-10 18:31:06 +02:00
Jonas Hermsmeier
fdd26ba8f1 Merge pull request #2190 from resin-io/webpack-exclude-package
fix(webpack): Exclude package.json from UI bundle
2018-04-10 17:42:38 +02:00
Jonas Hermsmeier
bec61f4ce7 fix(webpack): Exclude package.json from UI bundle
Change-Type: patch
2018-04-10 16:47:55 +02:00
Jonas Hermsmeier
2af1496f11 Merge pull request #2186 from resin-io/fix-readme-ci-badge
doc(README): Remove Mac OS from Travis CI badge label
2018-04-10 15:45:26 +02:00
Jonas Hermsmeier
f9e23a17d9 Merge pull request #2189 from resin-io/enable-node-gyp-rebuild
Enable nodeGypRebuild for Etcher builds
2018-04-09 19:31:39 +02:00
John (Jack) Brown
8050fa58a5 Enable nodeGypRebuild for Etcher builds
This will ensure we have all bindings built, even when using cached
modules.

Change-Type: patch
2018-04-09 09:20:58 -07:00
Jonas Hermsmeier
e04023bdfc Merge pull request #2138 from resin-io/release-1.4.0
Release v1.4.0
2018-04-07 00:05:14 +02:00
Jonas Hermsmeier
950f853fa3 v1.4.0 2018-04-06 20:59:56 +02:00
Jonas Hermsmeier
c3c15e222d Merge pull request #2183 from resin-io/fix-ui-writer-errors
fix(writer): Fix erronous event handling in write pipeline
2018-04-06 20:59:34 +02:00
Jonas Hermsmeier
3906816e67 doc(README): Remove Mac OS from Travis CI badge label
This removes the "mac" from the Travis CI badge label, as we're not
running Mac OS builds on Travis CI anymore.

Change-Type: none
2018-04-06 20:53:51 +02:00
Jonas Hermsmeier
fe43e21484 fix(writer): Fix erronous event handling in write pipeline
This fixes the use and handling of events in the write pipeline,
such that the pipeline would not be prematurely stalled or terminated.
Also, a new `fail` event is introduced, to signal non-fatal errors.

Change-Type: patch
2018-04-06 20:26:01 +02:00
Jonas Hermsmeier
5f7fd506a3 Merge pull request #2181 from resin-io/fix-menu-about
fix(gui): Fix "about" menu entry
2018-04-06 14:51:31 +02:00
Jonas Hermsmeier
65a3e51ff9 Merge pull request #2180 from resin-io/fix-writer-progress-state
fix(writer): Fix writer progress state values
2018-04-05 23:44:48 +02:00
Jonas Hermsmeier
722c1c6257 Merge pull request #2179 from resin-io/update-drivelist
upgrade(package): Bump drivelist to v6.1.5
2018-04-05 23:26:56 +02:00
Jonas Hermsmeier
2f872375ef fix(gui): Fix "about" menu entry
This fixes the capitalization of the "About Etcher" entry in the application menu

Change-Type: patch
2018-04-05 21:56:33 +02:00
Jonas Hermsmeier
f119ca683e fix(writer): Fix writer progress state values
This force-defaults the individual stream speeds to zero,
in order to avoid null values when not available yet.

Change-Type: patch
2018-04-05 21:51:00 +02:00
Jonas Hermsmeier
176c6b76cd upgrade(package): Bump drivelist to v6.1.5
Change-Type: patch
2018-04-05 21:35:30 +02:00
Jonas Hermsmeier
64604dbcc6 Merge pull request #2156 from resin-io/fix-store-quantity-guards
fix: ensure flash quantity fields are finite
2018-04-05 18:54:05 +02:00
Jonas Hermsmeier
0344a3f104 Merge pull request #2173 from resin-io/label-size-newline
fix(gui): Ensure image/drive size displayed on new line
2018-04-05 18:53:34 +02:00
Benedict Aas
c17247da58 feat(GUI): move drive selector warning to flash step (#1917)
We move the drive selector warning to the flash step, and concatenate
warning messages when more than one needs to be displayed at once.

Change-Type: patch
Changelog-Entry: Move the drive selector warning dialog to the flash step.
2018-04-05 17:26:16 +01:00
Jonas Hermsmeier
9601daedb7 Merge pull request #2174 from resin-io/update-codespell
test(lint): Update codespell 1.11.0 -> 1.12.0
2018-04-05 17:18:03 +02:00
Jonas Hermsmeier
f958f3751d fix(gui): Ensure image/drive size displayed on new line
This forces the image and device size to always be displayed on the
second line for visual consistency.

Change-Type: patch
2018-04-05 16:52:26 +02:00
Jonas Hermsmeier
0d1b9641c7 Merge pull request #2172 from resin-io/fix-inherit-env-windows
fix(image-writer): Don't inherit environment on Windows
2018-04-05 16:43:13 +02:00
Jonas Hermsmeier
9a9dd43646 Merge pull request #2175 from resin-io/fix-succeeded-count
fix(writer): Fix succeeded flash count in progress state
2018-04-05 16:42:50 +02:00
Jonas Hermsmeier
222257d25d fix(writer): Fix succeeded flash count in progress state
This fixes a bug where succeeded flashes could become negative due to
improper math

Change-Type: patch
2018-04-04 21:03:48 +02:00
Jonas Hermsmeier
dd961ad30b test(lint): Update codespell 1.11.0 -> 1.12.0
This updates codespell, and fixes new spelling error detections

```
lib/shared/models/selection-state.js:377: Unselect  ==> Deselect
lib/gui/app/components/modal/styles/_modal.scss:72: programatically  ==> programmatically
tests/shared/errors.spec.js:88: prioritise  ==> prioritize
tests/shared/errors.spec.js:94: prioritise  ==> prioritize
tests/shared/errors.spec.js💯 prioritise  ==> prioritize
tests/gui/components/svg-icon.spec.js💯 prioritise  ==> prioritize
docs/MAINTAINERS.md:19: artefacts  ==> artifacts
docs/MAINTAINERS.md:21: artefacts  ==> artifacts
docs/MAINTAINERS.md:25: artefacts  ==> artifacts
docs/MAINTAINERS.md:36: artefacts  ==> artifacts
docs/MAINTAINERS.md:96: artefacts  ==> artifacts
docs/MAINTAINERS.md:147: artefacts  ==> artifacts
CHANGELOG.md:492: interferring  ==> interfering
```

Change-Type: patch
2018-04-04 21:00:34 +02:00
Jonas Hermsmeier
abf2dc3efc fix(image-writer): Don't inherit environment on Windows
Due to improper command escaping, cmd metacharacters lead to failure
in spawning the child writer process on Windows when the entire environment
is passed through the command line. The user's environment will still
be inherited by default on Windows.

Change-Type: patch
2018-04-04 20:23:33 +02:00
Benedict Aas
99f819dfbf minifix: add spacing to drive warning icon (#2169)
Change-Type: patch
Changelog-Entry: Add spacing to the drive warning icon.
2018-04-04 14:53:20 +01:00
Benedict Aas
dc484d79ed fix: ensure flash quantity fields are finite
We replace the `_.identity` predicate with `_.isFinite` to ensure
the flash quantity fields are numbers.

Change-Type: patch
Changelog-Entry: Ensure flash quantity fields are finite.
2018-04-03 21:25:49 +01:00
Jonas Hermsmeier
42f522532e Merge pull request #2171 from resin-io/electron-1.7.13
upgrade(package): Bump Electron to v1.7.13
2018-04-03 22:00:04 +02:00
Benedict Aas
f97b439bc0 minifix: use multi-drive methods with drive-list warning button (#2170)
Change-Type: patch
Changelog-Entry: Use multi-drive methods with drive-list warning button.
2018-04-03 20:33:20 +01:00
Benedict Aas
65a4a959bb feat: expose all flash state fields to the store (#2153)
We expose all the flash state fields to the store, and mirror
`speed`'s format with `totalSpeed` with MB as the size unit.
We also format the progress state messages to use information
available with multiwrites.

Change-Type: patch
Changelog-Entry: Expose all flash state fields to the store.
2018-04-03 20:32:38 +01:00
Jonas Hermsmeier
07d6fde34e upgrade(package): Bump Electron to v1.7.13
This updates Electron to v1.7.13 in order to mitigate 2 vulnerabilities:
[CVE-2018-1000136] and [CVE-2018-1000118]

[CVE-2018-1000136]: https://nvd.nist.gov/vuln/detail/CVE-2018-1000136
[CVE-2018-1000118]: https://nvd.nist.gov/vuln/detail/CVE-2018-1000118

Change-Type: patch
Changelog-Entry: Update Electron to v1.7.13
2018-04-03 20:49:52 +02:00
Jonas Hermsmeier
b1dfbcbceb Merge pull request #2166 from resin-io/fix-html-lint
fix(lint): Fix html-lint error about "lang" attr
2018-04-02 18:24:15 +02:00
Jonas Hermsmeier
5e6f7e41e6 fix(lint): Fix html-lint error about "lang" attr
This avoids a new error from `html-lint` about the "lang" attr
on `<html>` tags, which isn't applicable to templates.

Change-Type: patch
2018-04-02 17:37:40 +02:00
Jonas Hermsmeier
df95ab1217 Merge pull request #2167 from resin-io/replace-ascii-only-check
test(lint): Replace ASCII-only check with ESLint rule
2018-04-02 17:37:12 +02:00
Jonas Hermsmeier
edf924d012 test(lint): Replace ASCII-only check with ESLint rule
This replaces the `ensure-all-text-files-only-ascii` sanity-check
with an ESLint rule to only check identifiers in code against being
printable ASCII, as there are places where UTF-8 in content is required,
which would make the previous check fail.

Change-Type: patch
2018-04-02 17:10:23 +02:00
Jonas Hermsmeier
8886732b21 Merge pull request #2163 from resin-io/update-resinci-copyright
chore(ci): Update copyright years in .resinci.json
2018-03-30 16:29:28 +02:00
Jonas Hermsmeier
543098cba3 chore(ci): Update copyright years in .resinci.json
Change-Type: patch
2018-03-30 00:12:59 +02:00
Jonas Hermsmeier
8bb20de912 Merge pull request #2161 from resin-io/local-test-blobs
test(image-stream): Use local dir instead of tmpdir
2018-03-30 00:02:52 +02:00
Jonas Hermsmeier
7f118c9841 Merge pull request #2162 from resin-io/refactor-spectron-tests
test(spectron): Refactor tests, dereference app after use
2018-03-30 00:02:18 +02:00
Jonas Hermsmeier
73155cca66 Merge pull request #2159 from resin-io/hide-size-multiple-devices
fix(GUI): hide the size label given multiple devices
2018-03-29 22:55:03 +02:00
Jonas Hermsmeier
267ccf6f97 Merge pull request #2160 from resin-io/wrap-button-sizes-cleanly
fix(GUI): line wrap selector size subtitles wholly
2018-03-29 22:53:55 +02:00
Jonas Hermsmeier
1f8e09868d upgrade(package): Bump spectron 3.7.2 -> 3.7.3
Change-Type: patch
2018-03-29 19:46:38 +02:00
Jonas Hermsmeier
c9a2a47ee1 test(spectron): Refactor tests, dereference app after use
Change-Type: patch
2018-03-29 19:45:54 +02:00
Jonas Hermsmeier
58f7811c7d Merge pull request #2148 from resin-io/webpack-progress
chore(webpack): Enable realtime progress display
2018-03-29 19:28:11 +02:00
Jonas Hermsmeier
a32ecb032e Merge pull request #2158 from resin-io/utils-middle-ellipses
refactor: inline middle-ellipsis package as util
2018-03-29 18:32:27 +02:00
Jonas Hermsmeier
bc2ad581ba test(image-stream): Use local dir instead of tmpdir
This changes the image-stream tests to use a local directory,
instead of the OS's tmpdir to avoid issues with sandboxing on Concourse CI.

Change-Type: patch
2018-03-29 17:22:52 +02:00
Benedict Aas
3498d59258 fix(GUI): line wrap selector size subtitles wholly
We line wrap the main-page image and drive size labels as a whole
instead of partially, if the drive or image title is long enough for a
line wrap.

Change-Type: patch
Changelog-Entry: Line wrap selector size subtitles wholly
2018-03-29 15:45:38 +01:00
Benedict Aas
f8accd62ed fix(GUI): hide the size label given multiple devices
We hide the size label when there are multiple selected devices, as this
doesn't make sense because you could only logically show the sum size,
which isn't very helpful on its own.

Change-Type: patch
Changelog-Entry: Hide the size label given multiple devices.
2018-03-29 15:36:18 +01:00
Jonas Hermsmeier
25b10490a1 chore(webpack): Enable realtime progress display
This enables realtime progress display for webpack, which can be
governed by setting WEBPACK_PROGRESS to various values.
See https://github.com/dominique-mueller/simple-progress-webpack-plugin

Change-Type: patch
2018-03-29 16:35:00 +02:00
Jonas Hermsmeier
800f0f45e5 Merge pull request #2155 from resin-io/dont-lint-frontend-files-cli
chore: don't lint frontend files (ie HTML) on the Node CLI pipeline
2018-03-29 16:34:25 +02:00
Benedict Aas
57c4a285d8 refactor: inline middle-ellipsis package as util
We remove our dependency on the `middle-ellipses` package and include
and expose the function in `lib/shared/utils`, alongside the regular
Angular filter it exposes. This allows use of the middle ellipsis
method in React.

Change-Type: patch
Changelog-Entry: Inline middle-ellipsis package as util.
2018-03-29 15:25:55 +01:00
Jonas Hermsmeier
1104987b9b Merge pull request #2157 from resin-io/replace-require-deps-check
chore(package): Replace custom missing require check
2018-03-29 16:08:48 +02:00
Jonas Hermsmeier
3dd646485f chore(package): Replace custom missing require check
This replaces the custom bash script with rules from the eslint-node plugin
to check for `require()`d modules that don't exist.
This will also check requires of local modules, and installed packages,
yielding a more thorough check.

Change-Type: patch
2018-03-28 18:49:32 +02:00
Juan Cruz Viotti
13eb1718aa chore: don't lint frontend files (ie HTML) on the Node CLI pipeline
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-03-27 17:16:58 -04:00
Jonas Hermsmeier
e41d4dad3c Merge pull request #2152 from resin-io/fix-concourse-symlinks
fix(webpack): Use fixed enhanced-resolve
2018-03-27 20:21:02 +02:00
Juan Cruz Viotti
9c1e32d4ba fix(webpack): Use fixed enhanced-resolve
This diverts to using a custom webpack branch to resolve
cyclic symlink issues with `enhanced-resolve` on Concourse.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
Change-Type: patch
2018-03-27 20:20:10 +02:00
Jonas Hermsmeier
ce71b81dbe Merge pull request #2140 from resin-io/fix-usbboot-appimages
fix: use correct usbbot blob path in appimages
2018-03-27 19:48:36 +02:00
Jonas Hermsmeier
62cc2201b0 Merge pull request #2154 from resin-io/disable-builder-rebuild
fix(windows): Disable rebuilding bindings in electron-builder
2018-03-27 19:46:38 +02:00
Jonas Hermsmeier
831c9aee2a fix(windows): Disable rebuilding bindings in electron-builder
We disable `npm rebuild` and `node-gyp rebuild` being run through
`electron-builder`, as we already rebuild native bindings against
the respective CPU arch through `make electron-develop`, and
electron-builder doesn't appear to respect package's install / rebuild scripts.

Change-Type: patch
2018-03-27 19:27:25 +02:00
Benedict Aas
cd697d7205 fix: use correct usbbot blob path in appimages
We use the `app.asar` relative path to read the usbboot blob files
instead of relative to the normal project root.

Change-Type: patch
Changelog-Entry: Use correct usbboot blob path in AppImages.
2018-03-26 18:18:05 +01:00
Jonas Hermsmeier
4be22e9ece Merge pull request #2134 from resin-io/support-forums
docs: point users to forums instead of Gitter
2018-03-26 15:26:42 +02:00
Jonas Hermsmeier
482ea6d8f9 Merge pull request #2135 from resin-io/fix-status-dots-position
fix(GUI): fix status dots to their position
2018-03-26 14:28:56 +02:00
Jonas Hermsmeier
bcf0d80c47 doc(PUBLISHING): Remove link to Gitter channel
Change-Type: patch
2018-03-26 14:13:24 +02:00
Jonas Hermsmeier
9bb292f38e doc(cli): Replace Gitter with forums link in CLI help
Change-Type: patch
2018-03-26 14:11:33 +02:00
Jonas Hermsmeier
1d89cf2b75 chore(ci): Remove Gitter.im webhooks from CI services
This removes notification webhook configurations from
our CI services, in anticipation of shutdown of the Gitter channel.

Change-Type: patch
2018-03-26 14:10:04 +02:00
Jonas Hermsmeier
8afc872252 doc(README): Replace Gitter badge with Discourse
This replaces the Gitter.im badge with a Discourse badge pointing
to the Etcher topics in the Resin.io Forums.

Change-Type: patch
2018-03-26 14:08:06 +02:00
Jonas Hermsmeier
559036518c Merge pull request #2121 from resin-io/update-winusb-driver
upgrade(package): Update winusb-driver-generator to v1.1.7
2018-03-26 13:52:57 +02:00
Jonas Hermsmeier
b0562f79d2 Merge pull request #2137 from resin-io/update-drivelist
upgrade(package): Bump drivelist 6.0.4 -> 6.1.3
2018-03-26 13:50:02 +02:00
Jonas Hermsmeier
f57df3f2c1 upgrade(package): Bump drivelist 6.0.4 -> 6.1.3
Change-Type: patch
2018-03-23 22:28:46 +01:00
Jonas Hermsmeier
0da123265c upgrade(package): Update winusb-driver-generator to v1.1.7
Change-Type: patch
2018-03-23 21:58:44 +01:00
Benedict Aas
cf340f48c3 fix(GUI): fix status dots to their position
We ensure the status dots don't move about and stick to their position
by using absolute positioning relative to its parent element.

Change-Type: patch
Changelog-Entry: Fix status dots to their position.
2018-03-23 17:33:32 +00:00
Juan Cruz Viotti
f0e0eaace4 docs: point users to forums instead of Gitter
We plan to shut down Gitter soon.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-03-23 12:40:54 -04:00
Benedict Aas
4140d49db3 refactor: multi-writes preparatory changes (#2124)
We add some preparatory changes including new utility functions, as well
as changes throughout the codebase that reflect the change from single
drives to a list of drives, given multi-writes is coming.

Change-Type: patch
Changelog-Entry: Various preparatory changes to account for
multi-writes.
2018-03-23 14:36:39 +00:00
Jonas Hermsmeier
8bd9ff58c4 Merge pull request #2131 from resin-io/fix-device-pass
fix(gui): Fix devices passed to writer
2018-03-22 18:12:53 +01:00
Jonas Hermsmeier
fecccb0b28 fix(gui): Fix devices passed to writer
Change-Type: patch
2018-03-22 16:52:01 +01:00
Jonas Hermsmeier
43d79ebd05 Merge pull request #2084 from resin-io/sdk-multiwrite
feat(writer): Impl multi-writes in writer modules
2018-03-22 00:12:02 +01:00
Jonas Hermsmeier
ad7c8760eb Merge pull request #1807 from resin-io/patch-1136
feat(gui): Display image size when drive too small

Close #1136
Close #2004
2018-03-21 23:37:22 +01:00
Jonas Hermsmeier
22f6cc1c6f Merge pull request #2118 from resin-io/fix-linux-usbboot
fix(scanner): Enable usbboot on Linux if run as root
2018-03-21 22:56:15 +01:00
Jonas Hermsmeier
98dcb13201 Merge pull request #2112 from resin-io/store-fix-autoselect-stale
fix: stop autoselecting empty value in store
2018-03-21 22:52:20 +01:00
Jonas Hermsmeier
497e8b5f28 Merge pull request #2095 from resin-io/update-packaging-deps
upgrade(package): Update release packaging deps
2018-03-21 22:39:01 +01:00
Jonas Hermsmeier
4108979b65 feat(gui): Display image size when drive too small
This adds a display of the determined image size to the
drive label when the drive has been determined to be too small.

Change-Type: patch
Changelog-Entry: Display image size for comparison if drive is too small
2018-03-21 20:35:47 +01:00
Jonas Hermsmeier
e01aec7b52 Merge pull request #2100 from resin-io/disable-timer-throttle
fix(gui): Disable throttling timers when in background
2018-03-21 20:34:31 +01:00
Jonas Hermsmeier
c5b311359a Merge pull request #2111 from resin-io/store-efficient-plainify
minifix: remove stale json object plainifying in store
2018-03-21 20:32:45 +01:00
Jonas Hermsmeier
624b95921a Merge pull request #2123 from lurch/etcher-2120
chore: Allow namespaced requires to be sanity-checked
2018-03-21 20:27:26 +01:00
Jonas Hermsmeier
69c35f7f79 fix(drive-scanner): Warn on usbboot load error on Linux
Change-Type: patch
2018-03-21 20:21:24 +01:00
Jonas Hermsmeier
3424b996c8 fix(writer): Fix state verification count
Change-Type: patch
2018-03-21 19:52:37 +01:00
Jonas Hermsmeier
ef634227aa feat(cli): Display number of active cards
Change-Type: patch
2018-03-21 18:42:34 +01:00
Jonas Hermsmeier
c724e4cb20 feat(writer): Impl multi-writes in writer modules
Implement writing to multiple destinations simultaneously

Change-Type: minor
Changelog-Entry: Implement writing to multiple destinations simultaneously
2018-03-20 22:21:01 +01:00
Jonas Hermsmeier
936142cf7e fix(gui): Fix usbboot blob dir path
Change-Type: patch
2018-03-15 16:42:34 +01:00
Jonas Hermsmeier
2aa37571f0 fix(gui): Fix usbboot drive icon path
Change-Type: patch
2018-03-15 16:41:38 +01:00
Jonas Hermsmeier
9b42960b2f fix(scanner): Enable usbboot on Linux if run as root
This re-enables the usbboot scanner dynamically if Etcher
is run as root on Linux.

Change-Type: patch
2018-03-15 14:45:04 +01:00
Andrew Scheller
6647167d02 chore: Allow namespaced requires to be sanity-checked
Fixes #2120

Change-type: patch
2018-03-15 01:41:34 +00:00
Benedict Aas
835f2cf769 feat(GUI): add colorised multi-writes progress status dots (#2115)
We add colorised progress status dots with quantities of `flashing`,
`validating`, `succeeded`, and `failed` devices.

Change-Type: patch
Changelog-Entry: Add colorised multi-writes progress status dots.
2018-03-14 17:05:01 +00:00
Benedict Aas
3fe5d7711f minifix: use svg contents list in main template (#2113)
We use a list instead of element with `svg-icon` in `main.tpl.html`, as
required by the `svg-icon` component and will return an error
otherwise.

Fixes: https://github.com/resin-io/etcher/issues/2078
Change-Type: patch
Changelog-Entry: Use SVG contents list in main template.
2018-03-14 17:03:31 +00:00
Benedict Aas
faf9b113a9 feat(CSS): use roboto font instead of helvetica (#2114)
We replace Helvetica with Roboto as the main font.

Change-Type: patch
Changelog-Entry: Replace Helvetica as the main font with Roboto.
2018-03-12 16:38:01 +00:00
Jonas Hermsmeier
f72cc6bbbc Merge pull request #2108 from resin-io/switch-chksm-algo
fix(perf): Remove support for CRC32 checksumming

Close #643
2018-03-09 15:11:32 +01:00
Benedict Aas
69e85a7ac6 fix: stop autoselecting empty value in store
We fix store autoselection, which selects an empty value when one
drive is selected and then ejected, leaving one drive that is
supposed to be autoselectable. Now it instead properly autoselects the
last drive.

Change-Type: patch
Changelog-Entry: Stop store autoselection from selecting empty values on
drive ejection.
2018-03-09 13:52:38 +00:00
Benedict Aas
82b65399af minifix: remove stale json object plainifying in store
Change-Type: patch
Changelog-Entry: Remove stale JSON object plainifying in store
2018-03-09 13:20:38 +00:00
Benedict Aas
a83e397643 refactor: move memoize function to shared utils (#2090)
We move the memoize function to `lib/shared/utils.js` and expose it to
modules across the project.

Change-Type: patch
Changelog-Entry: Move memoize function to shared utils.
2018-03-09 12:12:34 +00:00
Jonas Hermsmeier
f02c090b8d fix(package): Fix extraneous dependencies 2018-03-08 22:53:22 +01:00
Jonas Hermsmeier
49dd6553fb chore(package): Remove crc32-stream dependency 2018-03-08 22:14:03 +01:00
Jonas Hermsmeier
d116cd7e90 upgrade(package): Update asar 0.10.0 -> 0.14.2
Change-Type: patch
2018-03-08 22:00:31 +01:00
Jonas Hermsmeier
ed18842281 upgrade(package): Update bindings 1.2.1 -> 1.3.0
Change-Type: patch
2018-03-08 21:58:51 +01:00
Jonas Hermsmeier
4a3bd5fe7a upgrade(package): Update nan 2.3.5 -> 2.9.2
Change-Type: patch
2018-03-08 21:58:51 +01:00
Jonas Hermsmeier
8a70cb59d1 upgrade(package): Update pkg 4.1.1 -> 4.3.0
Change-Type: patch
2018-03-08 21:58:51 +01:00
Jonas Hermsmeier
35772b0370 fix(perf): Remove support for CRC32 checksumming
As crc32-stream was identified as a massive performance bottleneck,
we remove it, and default to Node's crypto API with md5 instead.

Change-Type: minor
2018-03-08 20:33:00 +01:00
Jonas Hermsmeier
68b33fcfb9 Merge pull request #2096 from resin-io/update-test-deps
upgrade(package): Update test related dependencies
2018-03-08 17:21:52 +01:00
Jonas Hermsmeier
0b306219c1 Revert "upgrade(package): versionist 2.8.1 -> 2.13.0"
This reverts commit 2604da104d.
2018-03-05 22:15:14 +01:00
Jonas Hermsmeier
bdd05a3f71 upgrade(package): Update electron-mocha 6.0.0 -> 6.0.1
See https://github.com/jprichardson/electron-mocha/issues/123

Change-Type: patch
2018-03-05 16:38:53 +01:00
Jonas Hermsmeier
c11205f3cd fix(shrinkwrap): Fix resolved URL of git repo
Change-Type: patch
2018-03-05 16:38:53 +01:00
Jonas Hermsmeier
11a0aa322f test(available-drives): Fix set expected set property
Change-Type: patch
2018-03-05 16:38:53 +01:00
Jonas Hermsmeier
a12bb4ee7c upgrade(package): mochainon 1.0.0 -> 2.0.0
Change-Type: patch
2018-03-05 16:38:52 +01:00
Jonas Hermsmeier
1cc5422557 upgrade(package): eslint-plugin-import 2.8.0 -> 2.9.0
Change-Type: patch
2018-03-05 16:38:52 +01:00
Jonas Hermsmeier
55ed4dbc51 upgrade(package): eslint-plugin-jsdoc 3.3.1 -> 3.5.0
Change-Type: patch
2018-03-05 16:38:52 +01:00
Jonas Hermsmeier
201b8dccaa upgrade(package): eslint-plugin-node 6.0.0 -> 6.0.1
Change-Type: patch
2018-03-05 16:38:52 +01:00
Jonas Hermsmeier
544cd96e3d upgrade(package): html-angular-validate 0.1.9 -> 0.2.3
Change-Type: patch
2018-03-05 16:38:52 +01:00
Jonas Hermsmeier
2604da104d upgrade(package): versionist 2.8.1 -> 2.13.0
Change-Type: patch
2018-03-05 16:38:51 +01:00
Jonas Hermsmeier
a392d3b1b4 upgrade(package): sass-lint 1.10.2 -> 1.12.1
Change-Type: patch
2018-03-05 16:38:51 +01:00
Jonas Hermsmeier
b7ef95f68c upgrade(package): nock 9.0.9 -> 9.2.3
Change-Type: patch
2018-03-05 16:38:51 +01:00
Jonas Hermsmeier
d12166a872 upgrade(package): mocha 3.2.0 -> 5.0.1
Change-Type: patch
2018-03-05 16:38:51 +01:00
Jonas Hermsmeier
74d9fcdbbc upgrade(package): electron-mocha 5.0.0 -> 6.0.0
Change-Type: patch
2018-03-05 16:38:51 +01:00
Jonas Hermsmeier
3e9536cef8 Merge pull request #2099 from resin-io/update-cli-visuals
upgrade(package): Update resin-cli-visuals to 1.4.1
2018-03-05 05:52:30 -08:00
Jonas Hermsmeier
95c2c25f1b Merge pull request #2098 from resin-io/update-contributing
doc(CONTRIBUTING): Add webpack step to instructions

Close #2079
2018-03-02 05:10:46 -08:00
Jonas Hermsmeier
81932e5d9f Merge pull request #2097 from resin-io/fix-error-image-writer
fix(image-writer): Fix missing error argv
2018-03-02 05:09:52 -08:00
Jonas Hermsmeier
d91d957777 fix(gui): Disable throttling timers when in background
This disables Electron throttling timers when not in the foreground.

Change-Type: patch
2018-03-01 20:04:34 +01:00
Jonas Hermsmeier
804ac8b4dc upgrade(package): Update resin-cli-visuals to 1.4.1
This updates `resin-cli-visuals` in order to fix drive selection in
the CLI, which was caused by incompatibility of two different `drivelist` versions

Change-Type: patch
2018-03-01 19:12:29 +01:00
Jonas Hermsmeier
bde1e32e29 doc(CONTRIBUTING): Add webpack step to instructions
Change-Type: patch
2018-03-01 18:50:45 +01:00
Jonas Hermsmeier
cb25db2556 fix(image-writer): Fix missing error argv
This fixes a missing error argument being passed in .emit()

Change-Type: patch
2018-03-01 18:12:38 +01:00
Jonas Hermsmeier
1536e62734 Merge pull request #2093 from resin-io/fix-about-copyright
chore(package): Update copyright years
2018-02-28 11:32:00 -08:00
Jonas Hermsmeier
401c2c7cc1 chore(package): Update copyright years
Change-Type: patch
2018-02-28 18:18:35 +01:00
Jonas Hermsmeier
d0faf9bc2f Merge pull request #2091 from resin-io/webpack-json
fix(webpack): Fix not resolving .json
2018-02-27 13:19:59 -08:00
Jonas Hermsmeier
81b5016168 fix(webpack): Fix not resolving .json
Change-Type: patch
2018-02-27 18:26:05 +01:00
Andrew Scheller
dcbe41bc40 fix(scripts): Add missing types to architecture-convert.sh usage (#2089)
Change-type: patch
2018-02-26 18:37:54 +00:00
Benedict Aas
4e112dc98c minifix: add missing parameter to verifyNoNilFields example (#2081)
We add the missing `name` parameter to the `verifyNoNilFields` JSDoc
example.

Change-Type: patch
Changelog-Entry: Add missing name param to verifyNoNilFields JSDoc example.
2018-02-26 11:34:46 +00:00
Jonas Hermsmeier
d233558b44 Merge pull request #2080 from resin-io/sdk-write-prepare
feat(sdk): Move CLI writer logic into SDK writer
2018-02-23 10:26:36 -08:00
Benedict Aas
207c2ef5b6 feat: add drive multi-selection in store (#1736)
We lay the foundation for multi-selecting drives by implementing it into
the `store` and relevant modules interacting with the `store`.

Change-Type: patch
Changelog-Entry: Add drive multi-selection to the store.
2018-02-23 17:45:49 +00:00
Jonas Hermsmeier
d9ccc43d15 feat(sdk): Move CLI writer logic into SDK writer
This moves the preparation logic from the CLI into the SDK
in preparation for further SDK rearchitecturing, and to allow
standalone usage of SDK.

Change-Type: minor
Changelog-Entry: Move CLI write preparation logic into SDK
2018-02-23 16:06:07 +01:00
Andrew Scheller
ee93013220 chore: fixup 'distclean' rule to also delete generated directory (#2077)
Change-type: patch
2018-02-23 12:43:13 +00:00
Juan Cruz Viotti
677fc5aa68 chore: only publish production packages to Bintray (#2076)
The devel channels will be completely deprecated. The deb/rpm snapshot
builds will still be accessible through GitHub Releases as part of Resin
CI builds.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-02-23 11:47:11 +00:00
Juan Cruz Viotti
8a86d0e655 chore: add "make webpack" as a Concourse build step (#2070)
We also have to add the generated directory to the final package.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-02-21 19:06:35 +00:00
Jonas Hermsmeier
27c4c0c749 fix(package): Add fsevents to platform specific deps (#2065)
This adds `fsevents` to the platform specific dependencies,
in order to avoid shrinkwrap disagreements between platforms.

Change-Type: patch
2018-02-21 17:45:47 +00:00
Benedict Aas
2c0cdcf947 refactor(GUI): remove selection-state clear options to simplify (#2043)
We refactor and simplify the selection-state `.clear()` by removing the
options argument.

Change-Type: patch
Changelog-Entry: Remove `selectionState.clear()` options argument to
simplify.
2018-02-21 15:56:42 +00:00
Benedict Aas
a56755e2c6 feat(GUI): add spacing to drive-selector labels (#2059)
We add a right margin to the drive-selector labels so they look nicer
when there are multiple.

Change-Type: patch
Changelog-Entry: Add spacing to the drive-selector warning/error labels.
2018-02-20 21:07:13 +00:00
Benedict Aas
765de94ca3 refactor: consolidate store-state nil-checking (#2062)
We make the nil-checking of store state fields generic through a
`verifyNoNilFields` function that throws an error if any fields are
nil.

Change-Type: patch
Changelog-Entry: Consolidate store state nil-checking with helper
function.
2018-02-20 13:13:29 +00:00
Benedict Aas
f060dc896f feat: resolve jsx files (#2063)
We resolve `.jsx` files such that they get handled by babel and bundled
with webpack.

Change-Type: patch
Changelog-Entry: Resolve JSX files
2018-02-20 13:03:47 +00:00
Jonas Hermsmeier
1dcbcef705 Merge pull request #2054 from resin-io/fix-debug-namespaces
fix(lib): Fix debug namespaces
2018-02-20 04:37:37 -08:00
Jonas Hermsmeier
5be64e124b Merge pull request #2023 from resin-io/drive-clean
feat(lib): Use win-drive-clean instead of diskpart
2018-02-20 03:40:10 -08:00
Jonas Hermsmeier
f70df03b1a Merge pull request #2056 from resin-io/fix-debug-enable
fix(app): Fix enabling debug output
2018-02-20 03:35:08 -08:00
Benedict Aas
8b577ca12f feat(GUI): separate svg path and content attributes (#1677)
We separate the SVG component path and content into attributes
`paths` and `contents` which take lists of strings that are
tried until one succeeds. `contents` takes precedence over `paths`,
i.e. it is tried first.

Change-Type: patch
Changelog-Entry: Separate SVG component's path and content attributes.
2018-02-20 09:51:13 +00:00
Benedict Aas
91719435d9 feat(GUI): warn the user on large drive selection (#2045)
We warn the user when they select a large drive to confirm they want to
flash in case the device is important.

Fixes: https://github.com/resin-io/etcher/issues/1916
Change-Type: patch
Changelog-Entry: Warn the user on selection of large drives.
2018-02-19 19:12:48 +00:00
Benedict Aas
b1b82301d9 fix(GUI): make all class label text bold (#2060)
We make all tags with `.label` have bold text and remove the need for
`<b>` tags.

Change-Type: patch
Changelog-Entry: Make all `.label` tags' text bold and remove need for `<b>` tags.
2018-02-19 18:38:03 +00:00
Benedict Aas
fdf15f53d7 feat(GUI): warning makes drive-selector button orange (#2044)
We make the drive-selector button orange when there is a warning attached
to the image-drive pair.

Change-Type: patch
Changelog-Entry: Make the drive-selector button orange on warnings.
2018-02-19 11:27:30 +00:00
Jonas Hermsmeier
4802854cff Merge pull request #2055 from resin-io/remove-direct-io
fix(cli): Remove O_DIRECT & O_EXCL
2018-02-16 10:53:28 -08:00
Jonas Hermsmeier
b0538099cf fix(lib): Fix debug namespaces
This fixes some debug namespaces not being prefixed with `etcher:`
and their respective subsystems.

Change-Type: patch
2018-02-16 19:01:26 +01:00
Jonas Hermsmeier
1fa9d7d7d7 Merge pull request #2052 from resin-io/sdk-refactor
feat(sdk): Consolidate low-level components into SDK
2018-02-16 09:59:32 -08:00
Jonas Hermsmeier
2b66762dec fix(app): Fix enabling debug output
This fixes enabling debug output via the DEBUG env var

Change-Type: patch
2018-02-16 18:21:17 +01:00
Jonas Hermsmeier
7063f254c6 fix(cli): Remove O_DIRECT & O_EXCL
This removes O_DIRECT and O_EXCL flags from the writer,
as O_DIRECT can lead to EINVAL under quite a few circumstances,
and O_EXCL has proven to be useless.

Change-Type: patch
2018-02-16 18:00:10 +01:00
Jonas Hermsmeier
7c9f15d8a9 feat(sdk): Consolidate low-level components into SDK
Changes:

- Split out scanner into own file
- Move `lib/shared/sdk` -> `lib/sdk`
- Move `lib/image-stream` -> `lib/sdk/image-stream`
- Move `lib/writer` -> `lib/sdk/writer`
- Rename `sdk/standard` -> `sdk/blockdevice`
- Move adapters into `sdk/adapters` subdirectory

Change-Type: minor
Changelog-Entry: Consolidate low-level components into Etcher SDK
2018-02-16 17:15:28 +01:00
Jonas Hermsmeier
2982dc478c Merge pull request #2042 from resin-io/fix-arm-build
fix(Makefile): Support arm64 / armv8 / aarch64
2018-02-16 08:10:37 -08:00
Jonas Hermsmeier
47fc1b7357 feat(lib): Use win-drive-clean instead of diskpart
This replaces shelling out to `diskpart` on Windows to clear
the partition table with `win-drive-clean`, which does so via DeviceIoControl.

Change-Type: minor
Changelog-Entry: Use native code to clean drives on Windows
2018-02-16 15:57:34 +01:00
Jonas Hermsmeier
6990d7632a fix(Makefile): Support arm64 / armv8 / aarch64
This adds support for 64bit arm cpu architectures.

Change-Type: patch
Changelog-Entry: Support building Etcher on armv8
2018-02-16 15:29:47 +01:00
Juan Cruz Viotti
4fa0f990e5 feat(GUI): bundle the GUI code with Webpack (#1943)
This commit introduces a Webpack configuration file that bundles the GUI
code along with its dependencies (except the Etcher SDK and its own
dependencies), and uses Babel to add support for JSX (required by the
Rendition library).

The GUI code that goes into the bundle was moved to `lib/gui/app` so we
can easily ignore the whole subdirectory when creating production
distributable packages.

We now have a new make target called `webpack` that can be used to
create the GUI bundle. Such target will be called everytime a package is
generated.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-02-15 17:39:15 +00:00
Benedict Aas
e0f789bc14 refactor: remove stale invalid key check in store (#2050)
We remove a piece of code checking whether `_.keys` returns any non-string
values in its array, but per the Lodash documentation `_.keys` always returns an
array of strings.

Change-Type: patch
Changelog-Entry: Remove stale `invalidKey` check in store.
2018-02-15 17:23:11 +00:00
Jonas Hermsmeier
b93dabd670 Merge pull request #2047 from resin-io/update-sass
upgrade(package): Update node-sass 4.5.3 -> 4.7.2
2018-02-15 03:55:36 -08:00
Jonas Hermsmeier
83528df18b upgrade(package): Update node-sass 4.5.3 -> 4.7.2
Change-Type: patch
2018-02-14 20:38:00 +01:00
Jonas Hermsmeier
1e65a09e8e Merge pull request #2012 from resin-io/use-template-contents
feat: replace template paths with contents
2018-02-14 06:54:54 -08:00
Benedict Aas
34b4f65c20 feat: log the event status of the banner (#2013)
We add log the banner HTTP load event object to the analytics.

Change-Type: patch
Changelog-Entry: Log the banner load event to analytics.
2018-02-14 12:03:40 +00:00
Jonas Hermsmeier
de4f9e4257 Merge pull request #2039 from resin-io/uv-threadpool-size
feat(writer): Increase UV_THREADPOOL_SIZE
2018-02-13 10:55:07 -08:00
Jonas Hermsmeier
dc2c16d6b5 Merge pull request #2031 from resin-io/remove-unnecessary-deps
chore(package): Remove unnecessary deps
2018-02-13 10:54:44 -08:00
Jonas Hermsmeier
fbb175608d feat(writer): Increase UV_THREADPOOL_SIZE
This increases the UV_THREADPOOL_SIZE to CPUs * 4 to
facilitate full write speeds when writing to multiple destinations,
in preparation for integrating multi-writes.

Change-Type: patch
Changelog-Entry: Increase UV_THREADPOOL_SIZE to allocate 4 threads per CPU
2018-02-13 17:31:59 +01:00
Jonas Hermsmeier
ab026b1635 test(image-stream): Fix lint error in tester 2018-02-13 17:15:39 +01:00
Jonas Hermsmeier
0bc09defa7 chore(package): Remove unused dependency trackjs 2018-02-13 16:13:49 +01:00
Jonas Hermsmeier
04352494a0 test: Remove unnecessary file-exists dependency
Change-Type: patch
2018-02-13 16:13:49 +01:00
Benedict Aas
96c76177af fix sanity-checks 2018-02-13 11:19:59 +00:00
Benedict Aas
d5a14031c6 pass linter 2018-02-13 11:19:59 +00:00
Benedict Aas
ad0b5e7583 test modal 2018-02-13 11:19:59 +00:00
Benedict Aas
f2424095e0 test other pages 2018-02-13 11:19:59 +00:00
Benedict Aas
db2bed896a feat: replace template paths with contents
We replace the `templateUrl` fields with `template` fields and thus
switch from template paths to template contents in preparation for the
Webpack PR.

Changelog-Entry: Replace template paths with template contents.
Change-Type: patch
2018-02-13 11:19:59 +00:00
Benedict Aas
c3600ee8fc refactor: rename selection state and store functions (#2037)
We rename functions in `selection-state` and the `store`.

Change-Type: patch
Changelog-Entry: Rename selection-state and store functions.
2018-02-13 11:15:22 +00:00
Benedict Aas
bb5efb3450 feat(GUI): add descriptive name to modals (#2036)
We add a descriptive name to modals for analytics and debugging.

Change-Type: patch
Changelog-Entry: Add descriptive name to modals for analytics and
debugging.
2018-02-13 11:13:48 +00:00
Jonas Hermsmeier
2e1764af82 Merge pull request #2029 from resin-io/remove-unused-robot
refactor(lib): Remove unused robot protocol
2018-02-12 04:58:52 -08:00
Jonas Hermsmeier
a0c704cd94 Merge pull request #2030 from resin-io/update-eslint-plugins
upgrade(package): Update eslint plugins
2018-02-09 12:28:42 -08:00
Jonas Hermsmeier
76f537a636 upgrade(package): Update eslint plugins
This updates outdated eslint plugins:

- eslint-plugin-import 2.7.0 -> 2.8.0
- eslint-plugin-jsdoc 3.1.1 -> 3.3.1
- eslint-plugin-lodash 2.3.6 -> 2.6.1
- eslint-plugin-node 5.1.1 -> 6.0.0
- eslint-plugin-promise 3.5.0 -> 3.6.0

Change-Type: patch
2018-02-09 19:34:53 +01:00
Jonas Hermsmeier
fdd0d781ca refactor(lib): Remove unused robot protocol
This removes the remnants of the unused "robot protocol",
which was previously used by the CLI, but has been superseded by IPC.

Change-Type: minor
Changelog-Entry: Remove unused robot protocol
2018-02-09 19:25:36 +01:00
Benedict Aas
47338cf07b upgrade(package): Update eslint 3.19.0 -> 4.17.0 (#2026)
We upgrade eslint for better support of the object-curly-newline
options, and change the quantity of elements required before the linter
enforces newlines on objects, in addition we apply `consistent` to avoid
errors when there are newlines in objects with less than 2 elements.

```
const { field } = object

const {
  field
} = object

const {
  field1,
  field2
} = object
````

Change-Type: patch
Changelog-Entry: Upgrade eslint to use object-curly-newline options.
2018-02-09 15:30:43 +00:00
Jonas Hermsmeier
4c1884fc95 Merge pull request #1998 from resin-io/update-udif
upgrade(package): Update udif 0.10 -> 0.13
2018-02-09 07:10:18 -08:00
Jonas Hermsmeier
c2ba053737 Merge pull request #2021 from resin-io/use-ng-if
feat(GUI): replace ng-show and ng-hide with ng-if
2018-02-09 03:41:53 -08:00
Jonas Hermsmeier
4cd16a40d0 Merge pull request #1743 from Lin-Buo-Ren/patch-1
docs: Add WoeUSB as an alternative tool to burn Windows USB images
2018-02-09 03:40:10 -08:00
Jonas Hermsmeier
0038c6c65a Merge pull request #2010 from resin-io/menu-link-ref
feat(gui): Add ref params to homepage links in menu
2018-02-09 03:39:22 -08:00
Jonas Hermsmeier
56b0f13525 Merge pull request #2027 from resin-io/remove-tmp
refactor(test): Remove dependency on `tmp`
2018-02-08 10:33:06 -08:00
Jonas Hermsmeier
974315868d Merge branch 'master' into patch-1 2018-02-08 09:52:12 -08:00
Jonas Hermsmeier
5634954b7e refactor(test): Remove dependency on tmp
This removes the dependence on `tmp`, as this module has been known
to cause problems, while also being unnecessary for what it's being used for.

Change-Type: minor
2018-02-08 18:43:48 +01:00
Benedict Aas
dab1eece4c feat: add icon next to drive on warnings (#2014)
We add an icon next to the drive size that is displayed when there is a
drive-image compatibility status message available. We display the first
one in the list and importance is then enforced by the order they are
added to the list in `drive-constraints`.

Change-Type: patch
Changelog-Entry: Add icon next to drive size when compatibility warnings exist.
2018-02-08 16:43:34 +00:00
Jonas Hermsmeier
d01b73a661 upgrade(package): Update udif 0.10 -> 0.13
This updates `udif` to 0.13.0:

**v0.13.0:**

- fix(readstream): Use strict mode for compat with Node 4
- refactor(lib): Improve & fix zerofill streaming
- test: Add passthrough to check for read/push after EOD
- test: Add compression method tests
- feat(udif): Add LZFSE compression type constant
- fix(readstream): Fix passing on readable stream options

**v0.12.0:**

- feat(image): Support use of custom `fs` instances
- feat(readstream): Stream ZEROFILL & FREE blocks

Fixes a buffer allocation failure on large zerofill ranges.

Change-Type: patch
Changelog-Entry: Fix "Array buffer allocation failed" when flashing some .dmg images
2018-02-08 16:11:56 +01:00
Jonas Hermsmeier
5754b4c6af feat(gui): Add ref params to homepage links in menu
This adds a `ref` param to the URLs in the menu,
in order to see where page views are coming from.

Change-Type: patch
2018-02-08 13:42:53 +01:00
Benedict Aas
e769ef7d0b feat(GUI): replace ng-show and ng-hide with ng-if
We replace `ng-show/hide` with `ng-if` on the main page in order to
remove unnecessary calls and become more efficient.

Changelog-Entry: Replace ng-show/hide with ng-if on main page.
Change-Type: patch
2018-02-07 17:53:17 +00:00
Jonas Hermsmeier
41a694e4a4 Merge pull request #2022 from resin-io/fix-linter-tabindex-button
fix: move tabindex attrs to button from within
2018-02-07 09:24:13 -08:00
Benedict Aas
76a05d2dc9 fix: move tabindex attrs to button from within
We move the `tabindex` attributes to the button element directly from
elements contained within the button element – this is to satisfy the
HTML linter.

Changelog-Entry: Move tabindex attributes to button elements from
contained elements.
Change-Type: patch
2018-02-07 16:06:07 +00:00
Jonas Hermsmeier
1895601198 Merge pull request #2008 from resin-io/update-issue-template
doc(github): Update instructions in ISSUE_TEMPLATE
2018-01-31 07:58:28 -08:00
Jonas Hermsmeier
f6bfdb2ced doc(github): Update instructions in ISSUE_TEMPLATE
This updates the instructions to open the Developer Tools in the issue template,
as the keyboard shortcuts have changed to their defaults on Linux & Windows
from [Ctrl]+[Alt]+[I] to [Ctrl]+[Shift]+[I].

Further, the editor config is updated to allow trailing spaces in Markdown
files to add trailing spaces to the list items in the issue template, in
order to avoid people not putting whitespace in between, causing the formatting
to not be parsed properly.

Change-Type: patch
2018-01-30 22:30:01 +01:00
Jonas Hermsmeier
1eb7ce8741 Merge pull request #1997 from resin-io/fix-devtools-detach
fix(gui): Fix DevTools opening in docked mode
2018-01-30 08:37:01 -08:00
Jonas Hermsmeier
a5aaf760d0 fix(gui): Fix DevTools opening in docked mode
This fixes the Developer Tools opening in docked mode by default.

Change-Type: patch
2018-01-29 21:59:46 +01:00
Benedict Aas
df2ebf93b6 refactor: replace lodash templates #1810 (#2006)
We replace the lodash templates with arrow-functions and change the
single-argument object into multiple arguments.

Fixes #1810 
Closes #2006 

Change-Type: patch
Changelog-Entry: Replace Lodash templates with arrow-functions.
2018-01-29 12:46:13 -08:00
Benedict Aas
4dc64ee15b feat(GUI): add app to gui folder structure (#2002)
* feat(GUI): add app to gui folder structure

We add a `lib/gui/app/` folder to help transition to Webpack usage.

Change-Type: patch
Changelog-Entry: Add `lib/gui/app` folder to ease into Webpack usage.
2018-01-29 18:34:21 +00:00
Jonas Hermsmeier
a83ae05316 upgrade(package): Update yargs 4.7.1 -> 11.0.0 (#1995)
This updates `yargs` to 11.0.0

Change-Type: patch
2018-01-29 06:25:50 -08:00
Benedict Aas
b0e6170d93 fix: specify utf-8 encoding with meta tag (#2003)
We specify the encoding to be UTF-8 with a meta tag such that Electron
won't get confused and try any other encodings.

Change-Type: patch
Changelog-Entry: Specify UTF-8 encoding with meta tag.
2018-01-26 10:45:49 -08:00
Jonas Hermsmeier
890122894f fix(gui): Fix menu's application name (#1996)
This replaces use of `electron.app.getName()` with the package.json's `.displayName`
property to ensure the correct application name is displayed when packaged.

Change-Type: patch
2018-01-26 07:04:54 -08:00
Jonas Hermsmeier
9c019cafd5 upgrade(package): Bump debug 2.6.8 -> 3.1.0 (#1994)
This updates `debug` to 3.1.0 due to a RegExp DOS vulnerability.

Change-Type: patch
2018-01-24 14:48:34 -08:00
Juan Cruz Viotti
b357047e3a chore: encode complete paths to patched file in patches/ (#1987)
So that the build system doesn't need to know in advance at which
directory the paths needs to be applied.

This will make it easier to add patches support to the Concourse
pipelines.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-23 18:48:35 -04:00
Juan Cruz Viotti
f932e947e0 chore: declare Concourse node-cli pipeline's entrypoint (#1988)
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-23 17:56:57 -04:00
Jonas Hermsmeier
c21baeda7a v1.3.1 2018-01-23 11:39:33 -08:00
Juan Cruz Viotti
4d5c372832 chore: revise Concourse CI related npm scripts (#1977)
- The `concourse-dependencies` and `concourse-build-installers` scripts
are not necessary anymore, given that the Electron pipeline already
knows how to perform these tasks

- The `concourse-test` script will be renamed to
`concourse-test-electron` to include the pipeline name (electron), so a
single project can be served by more than one pipeline. I'll keep the
old `concourse-test` for a bit for backwards compatibility until all
Etcher PRs are rebased

- There is a new `concourse-test-node-cli` script that will be used by
the Node.js CLI pipeline

- There is a new `test-cli` target that is supposed to host CLI tests.
For now, it just runs the SDK tests in a Node.js environment (instead of
in Electron)

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-23 14:43:41 -04:00
Jonas Hermsmeier
9b46587b73 upgrade(package): Update electron 1.7.10 -> 1.7.11 (#1985)
This updates Electron to v1.7.11, mitigating CVE-2018-1000006.

See: https://electronjs.org/blog/protocol-handler-fix
Change-Type: patch
Changelog-Entry: Update Electron to v1.7.11
2018-01-23 06:31:19 -08:00
Jonas Hermsmeier
38ff0e39d6 fix(lib): Fix readonly property typo (#1986)
This fixes the camelcasing of the `.isReadOnly` property
of detected storage devices.

Change-Type: patch
2018-01-23 06:30:06 -08:00
Jonas Hermsmeier
1f838b4b25 upgrade(package): Bump mountutils 1.3.8 -> 1.3.10 (#1983)
This updates `mountutils` from 1.3.8 -> 1.3.10;

- fix(linux): Fix partial unmounts on Linux
- fix(windows): Link to appropriate libraries

Change-Type: patch
Changelog-Entry: Fix incomplete unmounts after flashing on Linux
Fixes #1911
2018-01-23 03:30:12 -08:00
Juan Cruz Viotti
ffbb62a280 chore: add node-cli.node Resin CI option (#1978)
This represents the Node.js version that will be used to compile the
Etcher CLI.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-22 08:18:06 -08:00
Juan Cruz Viotti
b0831f0b9d chore: stop testing macOS on Travis CI (#1979)
We will rely on our Concourse instance for that.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-22 07:37:24 -08:00
Jonas Hermsmeier
e1ddbd300d fix(gui): Allow selection of images in folders with extension (#1976)
This fixes selection of images contained in directories with a file extension
(i.e. "openSUSE-Leap-42.3-DVD-x86_64.iso") in the open file dialog.

Change-Type: patch
Changelog-Entry: Fix selection of images in folders with file extension on Mac OS
2018-01-19 06:27:07 -08:00
Jonas Hermsmeier
fa4d6e9ef4 upgrade(package): Bump drivelist 6.0.0 -> 6.0.4 (#1975)
This updates `drivelist` to v6.0.4, fixing a crash on Windows 7,
among other things:

- Fix(windows): Impl IsSystemDevice()
- Fix crash on Windows 7
- Fix(darwin): Use proper flag to enable extended regexes in `sed`
- Fix(darwin): Allow mountpoints containing space characters

Change-Type: patch
Changelog-Entry: Fix Etcher not working / crashing on older Windows systems
2018-01-19 06:26:28 -08:00
Jonas Hermsmeier
61a6f9d556 doc(MAINTAINERS): Elaborate on the process of releasing (#1876)
This updates the maintainers' doc with a little more detail
regarding the release process, to avoid it staying tribal knowledge.

Change-Type: patch
2018-01-18 09:29:37 -08:00
Benedict Aas
1ae40c7b15 feat: test that ipc verbosity is off (#1963)
feat: test that ipc verbosity is off

We test that `ipc.config.silent` is set to `true` so that it doesn't
spam `stdout` for users.

Changelog-Entry: Test that IPC verbosity is off
Change-Type: patch
2018-01-18 09:14:09 -08:00
Jonas Hermsmeier
45c72f0c28 fix(usb): Ignore errors if winusb doesn't load (#1970)
Due to some Windows systems missing certain C runtime libraries
(Visual C/C++ 2012 / 2015 Redistributables), we ignore errors when loading
this module until we can ensure distribution of those along with it.

Change-Type: patch
Changelog-Entry: Fix "The specified module could not be found" on Windows
Fixes #1956
2018-01-18 09:11:46 -08:00
Juan Cruz Viotti
8d863638cc upgrade: electron-mocha to v5.0.0 (#1973)
Looks like this will fix an issue where the `electron-mocha` main
process fails with an EPERM error on Windows, which we've been
experiencing on our Concourse setup.

See: https://github.com/jprichardson/electron-mocha/issues/119
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-16 15:34:22 +01:00
Juan Cruz Viotti
759004e2b2 chore: add .resinci.json builder configuration object (#1965)
This object will eventually replace the `electron-builder.yml` file
that's currently present in the root of the project.

For now, it contains the `electron-builder` options that are project
specific (all the generic bits live in the Electron Concourse pipeline),
but in the future we might want to decouple how users configure packages
from the `electron-builder` project, instead making the user provide
Resin Concourse specific options that are then translated to
`electron-builder` (or any other packaging technology we might decide to
use) under the hood.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>

Trigger Concourse CI

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-12 13:25:24 -04:00
Jonas Hermsmeier
36d163e464 fix(shrinkwrap): Update unbzip2-stream branch commit (#1968)
The shrinkwrap still contained the commit hash of a commit
previous to an npm install bugfix

Change-Type: patch
2018-01-11 19:34:49 +01:00
Jonas Hermsmeier
96dddecd4d fix(writer): Silence IPC output on stdout (#1961)
This was causing the stdout maxBuffer size to be exceeded
when flashing larger images (or having flashes that took a while).

Fixes #1955 

Change-Type: patch
Changlog Entry: Fix "stdout maxBuffer exceeded" error on Linux
2018-01-08 23:09:55 +01:00
Jonas Hermsmeier
ece9a5666e v1.3.0
Features:

- Display connected Compute Modules even if Windows doesn't have the necessary drivers to act on them
- Add read/write retry delays with backoff to ...
- Add native application menu (which fixes OS native window management shortcuts not working)

Fixes:

- Fix "Couldn't scan drives" error
- Ensure the writer process dies when the GUI application is killed
- Run elevated writing process asynchronously on Windows
- Fix trailing space in environment variables during Windows elevation
- Don't send analytics events when attempting to toggle a disabled drive
- Fix handling of transient write errors on Linux (EBUSY)
- Fix runaway perl process in drivelist on Mac OS

Misc:

- Update Electron from v1.7.9 to v1.7.10
- Remove Angular dependency from image-writer

Change-Type: minor
2018-01-05 18:59:33 +01:00
Jonas Hermsmeier
9b721d83dc upgrade(package): Update drivelist 5.2.12 -> 6.0.0 (#1953)
* upgrade(package): Update drivelist 5.2.12 -> 6.0.0

This updates `drivelist` to incorporate the new native
bindings rewrite on Windows, fixing scanning errors.

Change-Type: patch
Changelog Entry: Fix "Couldn't scan drives" error

* test(drive-selection): Adjust to breaking drivelist changes

* fix(drivelist): Correct conditions in standard adapter

* refactor(usbboot): Adjust readonly & system flags

* doc(drive-constraints): protected -> isReadonly
2018-01-05 17:22:00 +01:00
Juan Cruz Viotti
9c624e8e52 chore: move updates disabling logic out of the Makefile (#1939)
The Makefile current has logic to disable updates when building deb or
rpm packages. To make the Concourse pipeline transition easier, the
logic that disables updates on deb and rpm has been moved to the main
application code.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-05 11:51:33 -04:00
Juan Cruz Viotti
a7ff5c4583 chore: re-organize files inside assets/ (second try) (#1952)
Change-Type: patch
See: https://github.com/resin-io/etcher/pull/1941
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-05 11:45:07 -04:00
Juan Cruz Viotti
2291321b46 refactor(GUI): remove the intermediate child writer proxy process (#1910)
Etcher currently elevates a child writer proxy that itself spawns the
Etcher CLI in robot mode, parses the output, and proxies those messages
to the GUI application over IPC.

After these set of changes, Etcher elevates a single child writer
process that directly communicates back with the GUI using IPC. The main
purpose behind these changes is to simplify the overall architecture and
fix various issues caused by the current complex child process tree.

Here's a summary of the changes:

- Stop wrapping the Etcher CLI to perform writing
- Remove the robot option from the Etcher CLI (along with related
  documentation)
- Elevate a new `child-write.js` standalone executable
- Move the relevant bits of `lib/child-writer` to the `image-writer` GUI
  module
- Remove the `lib/child-writer` directory
- Add a new "Child died unexpectedly" Mixpanel event
- Floor state percentage in the flash state model

The above changes made is possible to tackle all the remaining issues
where the writer process would remain alive even if the parent died.

Change-Type: patch
Changelog-Entry: Ensure the writer process dies when the GUI application is killed.
See: https://github.com/resin-io/etcher/pull/1873
See: https://github.com/resin-io/etcher/pull/1843
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-04 20:46:09 +01:00
Juan Cruz Viotti
0ce2fca40a minifix(GUI): run elevated process asynchronously on Windows (#1950)
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-04 14:17:38 -04:00
Jonas Hermsmeier
4a6955c173 fix(gui): Re-enable application menu (#1888)
* fix(gui): Re-enable application menu

This re-enables the application menu to allow for OS native shortcuts
to work again (i.e. hide/minimize window), which also allows us to
get rid of the global-shortcuts hack to prevent window reloads.

Change-Type: patch
Changelog-Entry: Fix disabled native OS window shortcuts

* refactor(gui): Update kbd shortcut comment to be less specific
2018-01-04 18:07:10 +01:00
Jonas Hermsmeier
fdfdcf915c upgrade(package): Bump mountutils 1.2.2 -> 1.3.8 (#1946)
Change-Type: patch
2018-01-04 15:47:25 +01:00
Jonas Hermsmeier
222fd9de62 upgrade(package): Bump electron 1.7.9 -> 1.7.10 (#1947)
Electron changelog:

- Fixed crash in custom protocols
- Fixed webrtc crash
- Linux: Fixed subpixel font rendering with freetype
- Mac OS: Fixed rendering issues with Nvidia GPU on High Sierra
- Mac OS: Fixed incorrectly cropped TouchBar items

Change-Type: patch
2018-01-04 13:09:46 +01:00
Jonas Hermsmeier
1093881149 upgrade(package): Bump drivelist 5.2.4 -> 5.2.12 (#1945)
Change-Type: patch
2018-01-04 13:08:55 +01:00
Juan Cruz Viotti
cb876436d4 fix(shared): trailing space in Windows elevation env vars (#1949)
This is a strange one. On Windows, putting a space before the
double-ampersand command concatenator makes the environment variable
value contain a trailing space. So for something like `set foo=bar &&
...` the variable `foo` will be `'bar '` instead of `'bar'`.

Change-Type: patch
Changelog-Entry: Fix trailing space in environment variables during Windows elevation.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-04 12:47:10 +01:00
Benedict Aas
13758c9568 feat(GUI): remove angular from image-writer (#1680)
* feat(GUI): remove angular from image-writer

We remove Angular from the `image-writer` module by using Redux store
updates, subscribing to them while flashing.

Changelog-Entry: Remove Angular dependency from image-writer.
Change-Type: minor
2018-01-04 11:12:08 +00:00
Juan Cruz Viotti
52af3e8aa8 chore: re-organize files inside assets/ (#1941)
This is the file convention that Resin Concourse will use. I flattened
the directory for simplicity.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2018-01-02 08:11:43 -04:00
Juan Cruz Viotti
aeb850f4fb chore: declare Concourse dependencies in package.json (#1938)
Resin Concourse will make sure to provide these during build time.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-29 09:51:38 -04:00
林博仁(Buo-Ren Lin)
3249af4eaa docs: Add WoeUSB as an alternative tool to burn Windows USB images(2)
Performing requested change, this commit is supposed to be squashed with the previous one.

Signed-off-by: 林博仁 <Buo.Ren.Lin@gmail.com>
2017-12-28 20:25:16 +08:00
林博仁
737b3be5be docs: Add WoeUSB as an alternative tool to burn Windows USB images
By far WoeUSB is one of the few applications that support Windows image
and runs on GNU/Linux so I assume it is worth to mention it.  Additional
line wrapping is made to comply to the code conventions.

Signed-off-by: 林博仁 <Buo.Ren.Lin@gmail.com>
2017-12-28 05:26:50 +08:00
Juan Cruz Viotti
3537848d3d chore: make test npm script run everything we run on the CI services (#1937)
The idea is that the `test` command will replace the recently introduced
`concourse-test` script.

`concourse-test` will become simply a call to `test` for now to ensure
backwards compatibility while we update Resin Concourse.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-27 13:29:55 -04:00
Jonas Hermsmeier
5387bf19d9 fix(writer): Add EBUSY to transient errors on Linux (#1918)
Change-Type: patch
2017-12-21 18:06:25 +01:00
Juan Cruz Viotti
357f2183b5 chore: add Concourse related NPM scripts (#1933)
Our Electron Concourse pipeline is completely independent from the
application its testing (ie we can apply it to any other Electron app we
build with ease).

In order to keep such genericity, the application under test should
provide certain npm scripts that tell Concourse how to do specific tasks
on the repo, like install dependencies, in a build-system independent
fashion.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-20 16:06:09 -04:00
Juan Cruz Viotti
c586d9f54c chore: get rid of npx (#1929)
We can live without it with a simple `PATH` trick at the top of the
Makefile (thanks @lurch!).

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-19 16:08:37 -04:00
Jonas Hermsmeier
abfa44a088 upgrade(package): Bump electron-builder 19.9.1 -> 19.40.0 (#1905)
Change-Type: patch
Connects To: #1914
2017-12-19 13:53:26 -04:00
Jonas Hermsmeier
5517beff80 fix(package): Fix noodled merge of shrinkwrap file (#1924)
Out of order squash merging resulted in some from-lines
not being removed in the npm-shrinkwrap.

Change-Type: patch
2017-12-15 22:32:36 +01:00
Jonas Hermsmeier
74c0c13fbd feat(writer): Add read/write retry delays (#1919)
Change-Type: minor
2017-12-15 16:09:11 +01:00
Jonas Hermsmeier
b086e4c2a1 refactor(scripts): Update clean-shrinkwrap script (#1816)
* refactor(scripts): Update clean-shrinkwrap script

This updates the `postshrinkwrap` script to traverse the dependency tree
and remove all `from` fields to avoid inconsistent diffs across platforms,
environments and installs when shrinkwrapping anew.

* chore(shrinkwrap): Update npm-shrinkwrap.json

* fix(scripts): Ensure `resolved` field in shrinkwrap is HTTPS

* fix(scripts): Only strip "from" of registry packages

* fix(clean-shrinkwrap): Fix linter errors

* chore(shrinkwrap): Update npm-shrinkwrap.json

* fix(scripts): fix spelling typo

Change-Type: patch
2017-12-15 16:08:33 +01:00
Andrew Scheller
b45306487b Fix small docs typo 2017-12-15 12:01:17 +00:00
Juan Cruz Viotti
f2c9404fc4 chore: setup a Spectron integration test suite (#1884)
- Add a `make test-spectron` target

- Install `spectron` and `mocha` (since we don't need to run the tests
  inside an Electron instance like in the case of `electron-mocha`)

- Add some example tests

Fixes: https://github.com/resin-io/etcher/issues/1870
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-13 13:51:16 -04:00
Juan Cruz Viotti
b703a6f5fb feat(SDK): display Compute Modules even if host OS has no drivers (#1892)
This is the first step towards full usbboot Windows support. The driver
selector dialog will now display disabled devices to represent Compute
Modules even when Windows drivers are not installed to act on them.
These drives will state "Missing drivers."

Change-Type: minor
Changelog-Entry: Display connected Compute Modules even if Windows doesn't have the necessary drivers to act on them.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-13 13:37:34 -04:00
Juan Cruz Viotti
f8c3faec79 fix(GUI): only emit toggle drive event if drive is selectable (#1913)
Right now we emit "Toggle drive" analytics events even when clicking on
disable/unselectable drives.

The fix is to move the `analytics.logEvent` inside the code path that
applies if a drive selection is considered valid.

Change-Type: patch
Changelog-Entry: Don't send analytics events when attempting to toggle a disabled drive.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-09 16:57:12 -04:00
Juan Cruz Viotti
5432363aa1 chore(appveyor): build x86 on real x86 machines (#1912)
We do this by using Appveyor's `platform` configuration variable instead
of always running on x64 and cross-compiling to x86.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-08 09:57:16 -04:00
Juan Cruz Viotti
85c8cd6340 docs: add high level manual testing script (#1874)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-08 13:55:17 +01:00
Jonas Hermsmeier
4c00a25968 v1.2.1 (#1906) 2017-12-07 16:43:58 +01:00
Juan Cruz Viotti
b74347d21f chore: pass a dictionary to codespell.py (#1717)
The `-` option loads the default dictionary.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-06 12:58:30 +00:00
Jonas Hermsmeier
657142716c fix(writer): Add missing read/write-retry handling (#1885)
This adds read- & write-retry handling of potentially temporary errors,
as well as errors due to device disconnection.

Change-Type: patch
Changelog-Entry: Fix handling of temporary read/write errors
2017-12-06 13:58:03 +01:00
Juan Cruz Viotti
618440e38f fix(GUI): ensure settings are loaded before bootstrapping application (#1879)
We load localStorage settings into the Redux store in an asynchronous
way. This means that user settings might not be loaded by the time the
application starts, resulting in Mixpanel sending a few tracking events
before Etcher realises that the user opted out from anonoymous analytics
and error reporting.

In order to fix that, we remove `ng-app` and we manually bootstrap the
Angular.js application *after* the local settings are loaded.

Change-Type: patch
Changelog-Entry: Don't send initial Mixpanel events before "Anonymous Tracking" settings are loaded.
Fixes: https://github.com/resin-io/etcher/issues/1772
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-05 11:04:52 -04:00
Juan Cruz Viotti
19b7ce0668 upgrade: resin-corvus to v1.0.0-beta.31 (#1902)
This version contains a couple of patches to ensure that the Mixpanel
library doesn't send any HTTP request to api.mixpanel.com unless the
user enabled analytics.

- https://github.com/resin-io-modules/resin-corvus/pull/35
- https://github.com/resin-io-modules/resin-corvus/pull/36

See: https://github.com/resin-io/etcher/issues/1772
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-12-05 11:04:23 -04:00
Jonas Hermsmeier
39401b3bfa fix(versionist): Ignore case of Change-Type value (#1847)
There's a commit that slipped in (sorry) with a capitalised
Change-Type value of "Patch". This avoids versionist erroring,
by always lowercasing that value.

Change-Type: PATCH
2017-12-05 09:40:32 -04:00
Benedict Aas
f22938030d minifix: hide drive selector hyphen when no size info (#1900)
We hide the separator hyphen between the name and size when there is no
size information available, in the drive selector modal.

Change-Type: patch
Changelog-Entry: Hide the drive-selector separator hyphen when no drive
size is available.
2017-12-04 19:11:07 -04:00
Andrew Scheller
a70935586b chore(ci): Attempt to fix TravisCI OSX builds (#1897)
The `pip` command is now `pip2`

Change-Type: patch
2017-12-04 14:37:27 +00:00
Jonas Hermsmeier
b1abc79942 v1.2.0 (#1846) 2017-11-27 15:37:48 +01:00
Jonas Hermsmeier
69c3d61c28 fix(writer): Set flags manually to avoid verifying cache (#1875)
We change from using `rs+` to a composition of read/write,
exlusive, sync & direct i/o flags, in order to avoid reading
stale data from the cache during verification.

Change-Type: patch
Changelog-Entry: Fix verification step reading from the cache
2017-11-23 14:42:11 +01:00
Jonas Hermsmeier
4e891151f4 feat(writer): Display actual write speed (#1863)
As we've actually been displaying the read-speed in various
forms during the flashing process, this is a venture into
displaying the actual write-speed from the end of the pipeline.

Change-Type: minor
Changelog-Entry: Display actual write speed
2017-11-22 21:12:38 +01:00
Jonas Hermsmeier
8e79e9e459 upgrade(package): Bump sudo-prompt 6.1.0 -> 8.0.0 (#1861)
This updates `sudo-prompt` from v6.1.0 to v8.0.0

Changes:

- v8.0.0:
  - Breaking: Windows: Set code page of command batch script to UTF-8
- v7.1.1:
  - readme: explicitly mention that no child process is returned
- v7.1.0:
  - Detect when PowerShell fails to launch command
  - Escape ampersand and other characters special to PowerShell
- v7.0.0:
  - Add status code to error on Windows and macOS
- v6.2.0:
  - Rename OS X to macOS

Change-Type: patch
2017-11-22 21:12:04 +01:00
Jonas Hermsmeier
f9085667d1 fix(child-writer): Reduce env vars passed during elevation (#1872)
As we're not escaping env vars properly in `permissions.getEnvironmentCommandPrefix()`,
passing the entire environment along can cause another instance of the "stuck at starting"
problem, thus we limit the vars explicitly passed along again, keeping PATH and DEBUG.

Change-Type: patch
2017-11-22 17:56:10 +01:00
Jonas Hermsmeier
a35ac7613e fix(writer): Use a core streams variant of unbzip2-stream (#1862)
This fixes pipage blowing up on unbzip2-stream because it's
based on through streams (which don't implement `.unpipe()`),
by utilizing a custom version based on core streams.

Change-Type: patch
Changelog-Entry: Fix bzip2 streaming with the new pipelines
2017-11-20 22:32:34 +01:00
Jonas Hermsmeier
ecedff2cdf fix(writer): Fix verify size for unaligned images (#1868)
Change-Type: patch
2017-11-20 19:28:20 +01:00
Andrew Scheller
500af07689 chore: add some more typos to the dictionary (#1864)
As spotted in #1858 and #1717

Change-type: patch
2017-11-18 16:09:32 +00:00
Jonas Hermsmeier
6779e15872 fix(writer): Emit checksum event when verifying bmaps (#1859)
Due to the Blockmap.FilterStream not emitting a "checksum"
event (as it individually verifies specified ranges), the
flashing process would get stuck on finish.

This emits a "checksum" event on "finish" when blockmapping,
averting this issue.

Change-Type: patch
2017-11-17 22:56:25 +01:00
Jonas Hermsmeier
b3b52fce62 fix(writer): Don't calculate checksum before block-stream (#1858)
The checksum-stream being situated in front of the block-stream, which
ensures block size alignment to multiples of 512, and pads the last block,
caused the checksum to be incorrectly calculated for images where the last
block needed to be padded.

Change-Type: patch
2017-11-17 21:37:49 +01:00
Jonas Hermsmeier
0e02998faf fix(gui): Re-enable printing progress in console (#1853)
Change-Type: patch
2017-11-17 14:36:21 +01:00
Jonas Hermsmeier
19275a5ba4 fix(gui): Disable outlines (#1854)
For the time being, the focus outlines are removed, until
we can improve the UX on this.

Change-Type: patch
2017-11-17 13:33:19 +01:00
Andrew Scheller
701893b472 fix(s3): Fix EAI_AGAIN error at startup with no internet connection (#1855)
Change-type: patch
2017-11-17 11:22:22 +00:00
Jonas Hermsmeier
66cb7293e7 fix(drive-scanner): Dynamically get unsafe mode setting (#1852)
Due to the SDK keeping it's options once initialized,
the unsafe mode setting change was not reflected on subsequent scans.

Change-Type: patch
2017-11-17 03:28:32 +01:00
Jonas Hermsmeier
773ddb6e9e fix(child-writer): Pass parent env during elevation (#1851)
Change-Type: patch
2017-11-17 02:56:42 +01:00
Jonas Hermsmeier
7ebff68506 fix(store): Fix "Missing state eta" error on Infinity/NaN (#1850)
If the speed is zero, the eta becomes Infinity, which isn't transmitted
properly over IPC for at this time unknown reasons.
To prevent the "Missing state eta" error from popping up when the speed is
zero, we set the eta to zero as well in those cases.

Change-Type: Patch
2017-11-16 17:58:58 -04:00
Jonas Hermsmeier
9e75547166 upgrade(ipc): Update node-ipc 8.9.2 -> 9.1.1 (#1836)
Change-Type: patch
2017-11-16 21:12:36 +01:00
Jonas Hermsmeier
bb4e6c74e0 fix(child-writer): Ensure tmpdir path has trailing slash (#1849)
There's a bug in node-ipc which doesn't allow it to handle
tmpdirs without trailing slashes; this works around this bug.

Change-Type: patch
2017-11-16 15:04:50 -04:00
Jonas Hermsmeier
55d043a626 doc(MAINTAINERS): Fix changelog make target, reword screenshot (#1848)
Change-Type: none
2017-11-16 16:18:13 +01:00
Jonas Hermsmeier
5046af5313 fix(child-writer): Handle exits due to a signal (#1843)
This adds handling for cases where the writer child process
exits due to reception of a signal, while also adjusting some peripherals,
like the IPC socket directory and inherited process environment.

Another addition is that the child process is explicitly killed
should an error arise on the IPC.

Change-Type: patch
2017-11-15 15:52:57 +01:00
Jonas Hermsmeier
5e77958106 feat(writer): Implement streaming pipelines (#1671)
This implements a new way of image write streaming under use of pipage and blockmap, which paves the way for a few things like using network locations as sources, and imaging of storage devices (aka backups). As it allows for mutation of the streaming pipeline while it's writing, it also facilitates the development of dynamic block-mapping.

Change-Type: minor
2017-11-14 19:54:10 +01:00
Juan Cruz Viotti
63528ce8f3 fix(SDK): disable usbboot adapter on GNU/Linux (#1841)
Various GNU/Linux distributions require root access to be able to open
USB devices. This means that Etcher would need to be ran as root, which
is now not possible on Wayland based systems.

We declare usbboot as unsupported on GNU/Linux from the time being, but
we are currently working on a solution.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-11-14 18:00:01 +01:00
Juan Cruz Viotti
856f53067b chore: revert "chore: don't zip AppImages" (#1842)
For usability purposes. We get a high volume of support requests from
GNU/Linux newbies that get deeply confused about setting execution
permissions.

This reverts commit b2d3d0ecb8.
2017-11-14 13:51:01 +01:00
Sven Dowideit
58a89ad182 docs: etcher-image-stream was moved to the main etcher repo (#1830)
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2017-11-14 13:49:13 +01:00
Josh Leeb-du Toit
e815d97265 fix(CLI): add check for drive flag with yes flag (#1753)
Add an options check for the `drive` flag to appear with the `yes` flag.
If the `yes` flag appears without the `drive` flag then a user error
will be thrown.

Change-Type: patch
Link: https://github.com/resin-io/etcher/pull/1753
Fixes: https://github.com/resin-io/etcher/issues/1454
2017-11-14 11:02:43 +00:00
Benedict Aas
33db722f68 docs: add python version to contributing (#1838)
Change-Type: patch
Changelog-Entry: Add the Python version (2.7) to the CONTRIBUTING doc.
2017-11-14 10:58:16 +00:00
Benedict Aas
0058919a8e feat(GUI): add progress and status to window title (#1438)
* feat(GUI): add progress and status to window title

We add the progress percentage to the window alongside the status
(validating, flashing).

Closes: https://github.com/resin-io/etcher/issues/1427
Fixes: https://github.com/resin-io/etcher/issues/1439
Changelog-Entry: Add the progress and status to the window title.
2017-11-14 09:23:41 +00:00
Benedict Aas
5771c0f56e fix: rid linux startup elevation (#1831)
We remove the Linux elevation meant for usbboot device access.

Reverts: https://github.com/resin-io/etcher/pull/1708
See: https://github.com/resin-io/etcher/issues/1819
Change-Type: minor
Changelog-Entry: Remove Linux elevation meant for usbboot.
2017-11-13 15:34:20 -04:00
Jonas Hermsmeier
8b13a23117 fix(sdk): Remove event listeners on unsubscribe (#1834)
Change-Type: patch
2017-11-09 14:44:42 +01:00
Benedict Aas
08b6397a9a minifix: remove duplicate debug enable in usbboot (#1835)
Changelog-Entry: Remove duplicate debug enabling in usbboot module.
Change-Type: patch
2017-11-09 12:05:55 +00:00
Jonas Hermsmeier
66441e28cb fix(sdk): Correct "subscribe" typos (#1832)
* fix(sdk): Correct "subscribe" typos
* test(dictionary): Add subsribe -> subscribe

Change-Type: Patch
2017-11-08 18:06:00 +00:00
Andrew Scheller
26b521411f fix: Correct image.size usage in tests and code-comments (#1833)
image.size is always an object, never a plain number

Change-type: patch
2017-11-08 16:53:57 +00:00
Jonas Hermsmeier
03b252024e fix(gui): Don't check elevation on start on Windows (#1822)
This fixes Electron startup on Windows

Change-Type: patch
2017-10-31 20:20:27 +01:00
Jonas Hermsmeier
68f3f695cd feat(sdk): Implement continuous scanning (#1814)
This implements an SDK.Scanner which handles any given
adapters and manages the scans. This change enables continuous
scanning without the need to `.scan()` scheduling in other places.

Change-Type: minor
2017-10-31 18:05:32 +01:00
Jonas Hermsmeier
c0d25786ef fix(scripts): Fix pip install in docker (#1818)
This works around the "Cannot fetch index base URL http://pypi.python.org/simple/"
error by installing pip==9.0.1 directly from the pypi.python.org/packages/

Change-Type: patch
2017-10-31 14:04:00 +01:00
Juan Cruz Viotti
8caf03327c fix(usbboot): increase device reboot delay a little bit (#1815)
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-27 16:32:20 -04:00
Benedict Aas
9815f9a5a1 fix: set debug env variable on remote electron process (#1789)
We fix the DEBUG environment variable by setting it on the `electron.remote`
instead, and we also move the code to `lib/gui/app.js` and away from
`lib/gui/index.html`.

Changelog-Entry: Set the DEBUG environment variable on the remote
electron process.
Change-Type: patch

* use debug.enabled, fix drivelist env setting
* fix: set debug env variable on remote electron process
2017-10-27 20:42:57 +02:00
Benedict Aas
f2f5955264 feat(GUI): use tabindex and focus to navigate (#1745)
* feat(GUI): use tabindex and focus to navigate

We make navigating with the tab key easier by highlighting focused
elements more visibly, adding `tabindex` attributes to elements, and
making `open-external` links respond to keyboard events.

Change-Type: minor
Changelog-Entry: Improve tab-key navigation through tabindex and visual improvements.
Connects-To: https://github.com/resin-io/etcher/issues/1734

* outline with 10s timeout

* use orange "warning colour" as outline

* smaller outline on settings buttons, fix order on settings page

* allow selection in drive-selector

* fix typo, better tabindexes
2017-10-27 20:41:47 +02:00
Jonas Hermsmeier
e5d69465ab test(Makefile): Update codespell excludes (#1811)
This adds excludes for .dtb, .dtbo, .dat, .elf, .bin, .foo, and xz-without-extension
to reduce unnecessary warning output in `make lint`.

```
WARNING: Binary file: lib/blobs/usbboot/bcm2709-rpi-2-b.dtb
WARNING: Binary file: lib/blobs/usbboot/bcm2710-rpi-cm3.dtb
WARNING: Binary file: lib/blobs/usbboot/bcm2708-rpi-cm.dtb
WARNING: Binary file: lib/blobs/usbboot/bcm2708-rpi-b.dtb
WARNING: Binary file: lib/blobs/usbboot/bcm2710-rpi-3-b.dtb
WARNING: Binary file: lib/blobs/usbboot/bcm2708-rpi-0-w.dtb
WARNING: Binary file: lib/blobs/usbboot/bcm2708-rpi-b-plus.dtb
WARNING: Binary file: lib/blobs/usbboot/overlays/dwc2.dtbo
WARNING: Binary file: lib/blobs/usbboot/raspberrypi/fixup_cd.dat
WARNING: Binary file: lib/blobs/usbboot/raspberrypi/start_cd.elf
WARNING: Binary file: lib/blobs/usbboot/raspberrypi/bootcode.bin
WARNING: Binary file: tests/image-stream/data/unrecognized/xz-without-extension
WARNING: Binary file: tests/image-stream/data/unrecognized/xz-with-invalid-extension.foo
```

Change-Type: patch
2017-10-26 19:21:56 +02:00
Juan Cruz Viotti
eba06a2139 style(usbboot): wait before scanning drives after the file server phase (#1799)
This is a workaround to prevent the USB device from disappearing after
the file server phase, until the resulting block device comes up.

By adding a delay after the file server phase, we prevent the USB
scanner from getting triggered again, therefore keeping the current USB
device visible in the drive selector modal.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-26 12:05:59 -04:00
Juan Cruz Viotti
daa847d29b feat(usbboot): add progress property to usbboot scanned drives (#1803)
This commit re-architects the usbboot adapter to prepare the drives in
the background, while emitting scan results every 2s, where each drive
has a `progress` percentage property.

Change-Type: minor
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-25 14:03:30 -04:00
Benedict Aas
433b2734bb feat: add sudo-prompt to start on linux (#1708)
We prompt the user with a sudo-prompt upon launch on Linux-based systems
to ensure the program has enough permissions for features needed
throughout the program's runtime.

Changelog-Entry: Add a sudo-prompt upon launch on Linux-based systems.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-25 11:27:40 -04:00
Juan Cruz Viotti
02f7a5f55b refactor(SDK): make adapter scan functions event based (#1781)
* refactor(SDK): make adaptor scan functions event based

This change will allow us to start emitting progress events out of the
adaptors scan functions.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>

* refactor(sdk): Make adapters event emitters
2017-10-25 13:26:43 +02:00
Benedict Aas
2556807166 feat(GUI): add optional progress bars to drive-selector drives (#1800)
We show a progress bar for any drive objects with a `progress` field
that isn't falsy, e.g. `undefined` or `0`.

Changelog-Type: minor
Changelog-Entry: Add optional progress bars to drive-selector drives.
2017-10-24 14:43:43 -04:00
Juan Cruz Viotti
5bf6633cbe refactor(sdk): add bus number, device address, and ids in usb devices (#1802)
The combination of bus number and device address is the only way to
uniquely identify a USB device, so we'll use that for the `device` and
`raw` properties.

Also, we store the USB vendor and product IDs as properties of the
drives, since they will be handy when implementing the prepare function.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-24 14:32:33 -04:00
Jonas Hermsmeier
acb4271833 doc(CONTRIBUTING): Add note about msvs_version on Windows (#1794)
This adds a small note about setting the `msvs_version`
in the npm config on Windows.

Change-Type: patch
2017-10-20 22:11:31 +02:00
Jonas Hermsmeier
dd0bb43616 upgrade(package): Bump resin-corvus to beta.30 (#1795)
This updates resin-corvus to v1.0.0-beta.30, fixing an issue
with attempting to use https transport in browserland.

Change-Type: patch
2017-10-20 22:11:13 +02:00
Juan Cruz Viotti
a11a22453a fix(usbboot): handle LIBUSB_ERROR_NO_DEVICE when claiming a USB interface (#1796)
Consider the following scenario:

- Usbboot runs successfully on a device
- Before the block device gets a chance to appear, we run usbboot again

If we're fast enough, usbboot will try to claim the device interface,
but then the drive might not be there anymore, causing a
`LIBUSB_ERROR_NO_DEVICE`.

This commit addresses that scenario, and simply ignores the drive.

Change-Type: patch
Changelog-Entry: Fix `LIBUSB_ERROR_NO_DEVICE` error at the end of usbboot.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-20 11:10:12 -04:00
Juan Cruz Viotti
39e6207183 feat(usbboot): add new files that provide better speed (#1775)
We currently ship with `bootcode.bin` and `start.elf` from the Raspberry
Pi Foundation, which provide a writing speed of about 6 MB/s. This PR
includes new boot files by resin.io that boost the speed to ~20 MB/s.

Change-Type: minor
Changelog-Entry: Increase the flashing speed of usbboot discovered devices.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-20 10:36:35 -04:00
Juan Cruz Viotti
88ef235987 fix(usbboot): handle device disconnections (#1798)
This commit handles errors that can come up when unplugging the drive
halfway through the process. After tons of experimentation, the errors
than seem to occur are:

- `LIBUSB_TRANSFER_CANCELLED`
- `LIBUSB_ERROR_NO_DEVICE`

When these errors happen, we can omit the drive, and also not try to
close it, since given the device is no longer there, the close operation
bails out with a strange error message.

Change-Type: patch
Changelog-Entry: Gracefully handle scenarios where a USB drive is disconnected halfway through the usbboot procedure.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-20 08:50:58 -04:00
Jonas Hermsmeier
32399ba8a1 upgrade(package): Update Electron v1.6.6 -> v1.7.9 (#1784)
This updates Electron from v1.6.6 to v1.7.9

Change-Type: patch
Changelog-Entry: Update Electron to v1.7.9
2017-10-18 21:19:23 +02:00
Jonas Hermsmeier
42052dde9f doc(CONTRIBUTING): Remove refence to "install script" (#1790)
This removes a confusing reference to an "install script"
in the dependency section.

Change-Type: patch
2017-10-18 17:43:07 +02:00
Jonas Hermsmeier
ea686ee8e2 doc(CONTRIBUTING): Add libudev requirement to docs (#1787)
Closes #1771
Change-Type: patch
2017-10-18 14:20:47 +02:00
Juan Cruz Viotti
df05d4cc08 fix(usbboot): opening device debug message prints undefined (#1776)
We have a debug message that prints `device.name`, which is not a valid
property, and therefore the debug logs show `undefined` instead of the
USB id pair.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-17 10:47:34 +01:00
Juan Cruz Viotti
e54a8ae92b fix(GUI): improve usbboot USB device branding (#1780)
- Add a loading SVG icon while usbboot is running
- Make the device description more user friendly

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-17 10:47:14 +01:00
Juan Cruz Viotti
0f8043b35b fix(GUI): don't show the "too small" badge if the size is null (#1779)
Some devices don't have a size, like USB devices in the usbboot adaptor.
The `.isDriveLargeEnough()` correctly returns `false` in this case,
however we don't want to show the `TOO SMALL` badge for aesthetics
purposes.

So if a drive has a size that equals `null`, we don't allow such drive
to be selected, and we don't show a badge for it.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-16 17:51:55 +01:00
Juan Cruz Viotti
ec1f3665eb fix(GUI): don't display hyphen in drive selection entry if no size (#1778)
Some drives, like usbboot USB devices, don't have a size associated with
them, which results in the drive selection widget showing a hyphen with
nothing at the side, which looks a bit weird.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-16 16:07:48 +01:00
Juan Cruz Viotti
444072db13 refactor(GUI): generalize the concept of a "pending" drive (#1777)
This commit introduces a boolean `disabled` property rather than a
`pending` flag. Making this distinction clearer means that we can now
treat pending drives in different ways needed to improve the usbboot
experience.

Also, for usbboot, this commit removes the "pending" badge and uses a
more descriptive drive description instead.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-16 12:09:38 +01:00
Niklas Higi
6acfcfd23c fix(GUI): make sure progress button is always rounded (#1768)
At the moment the progress button which has slightly rounded corners
allows the "__bar" to overflow. This causes the corners to become
angular again which looks weird. I set the button's "overflow" to
"hidden" to fix this issue.

Changelog-Entry: Make sure the progress button is always rounded.
Change-Type: patch
2017-10-14 14:41:00 +02:00
Juan Cruz Viotti
78fdc5b07e feat(GUI): add some branding to usbboot-discovered devices (#1764)
- Add a nice icon in the drive selector dialog when a device has been
  discovered through usbboot

- Change the name of usbboot-initialized devices to "Compute Module"

Change-Type: minor
Changelog-Entry: Add eye candy to usbboot initialized devices.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-11 03:53:34 +01:00
Juan Cruz Viotti
f5fcdf4acb fix(sdk): increase bulk transfer usb timeouts (#1759)
We experienced timeouts when sending big files (ie ~14 MBs). Setting the
timeout to 0 makes the timeout infinite.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-10 23:59:49 +01:00
Juan Cruz Viotti
8aa58a722b fix(sdk): set usbboot control transfer timeout to infinite (#1760)
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-10 21:35:59 +01:00
Gergely Imreh
f7b0291bf8 fix(sdk): usbboot command typos (#1758)
Change-type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-10 19:06:00 +01:00
Juan Cruz Viotti
179597b86f upgrade: drivelist to v5.2.4 (#1755)
See: https://github.com/resin-io-modules/drivelist/pull/229
Change-Type: patch
Changelog-Entry: Fix permission denied issues when XDG_RUNTIME_DIR is mounted with the `noexec` option.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-09 10:47:56 +01:00
Juan Cruz Viotti
f6a7b2add6 feat: implement usbboot adapter (#1686)
This commit installs `node-usb` v1.3.0 from GitHub, since that version
was never published to NPM, and is the only one that works with Visual
Studio 2015 (see https://github.com/tessel/node-usb/issues/109).

The usbboot communicates with a Raspberry Pi / Amber through USB and
eventually mounts it as a block device we can write to.

This feature bundles bootcode.bin and start.elf from the original
usbboot implementation.

The flow is the following:

- On each scan, the usbboot scanner will try to get a usbboot compatible
  USB device to the next "phase", until they are all transformed to
  block devices the user can flash to as usual

Change-Type: minor
Changelog-Entry: Integrate Raspberry Pi's usbboot technology.
Fixes: https://github.com/resin-io/etcher/issues/1541
See: https://github.com/raspberrypi/usbboot
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-10-06 14:19:35 +01:00
Jonas Hermsmeier
3147a93ca6 feat(image-stream): Support .bin image extension (#1750)
This adds support for selecting images with a `.bin` file extension.

Change-Type: minor
Closes #1739
2017-10-03 18:13:02 +02:00
Jonas Hermsmeier
cb7117a36b upgrade(node-stream-zip): 1.3.4 -> 1.3.7 (#1730)
This fixes RangeErrors occurring with some zip files.

**Changes:**

- Fixed compatibility with node.js v0.10
- Fix error unpacking archives with a special comment
- Fix descriptive error messages

Change-Type: patch
Changelog-Entry: Fix Etcher being unable to read certain zip files
2017-09-22 20:15:29 +03:00
Jonas Hermsmeier
b5912eb9f6 fix: Support raw images without secondary file extension (#1724)
This allows selection of images without a secondary file extension
(i.e. `example.gz`, compared to `example.img.gz`) by defaulting to `img`
in the image-stream handlers, should no secondary extension be found.

Further this adjusts `.getPenultimateFileExtension()` to return `null`
if the detected penultimate extension is not a known file extension.

Change-Type: patch
2017-09-13 18:34:26 +02:00
Jonas Hermsmeier
a3c54f22c8 refactor(image-stream): Remove Promise props resolve (#1726)
This removes `Bluebird.props()` from the image type handlers,
as it's just a remnant when some properties in the return value
were Promises that needed resolving.

Change-Type: patch
Connects To: #1724
2017-09-13 13:56:51 +02:00
Juan Cruz Viotti
70edfa384b chore: fix CLI packaging snapshot relative directory (#1713)
The current CLI releases are broken. Seems that `pkg` creates the
application snapshot based on the current working directory, so at the
moment, the snapshot gets created based on the root of the project,
rather than based on the dist/Etcher-cli-* directories, causing the
native add-ons to not be resolved correctly.

Fixes: https://github.com/resin-io/etcher/issues/1706
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-09-11 10:45:28 -04:00
Juan Cruz Viotti
077eb5b079 upgrade: mountutils to v1.2.2 (#1712)
See: https://github.com/resin-io-modules/mountutils/pull/45
Change-Type: patch
Changelog-Entry: Retry ejection various times before giving up on Windows.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-09-08 15:43:46 +02:00
Jonas Hermsmeier
e654311997 chore(package): Bump resin-corvus to 1.0.0-beta.29 (#1720)
This updates `resin-corvus` to version 1.0.0-beta.29, switching
Mixpanel and Sentry analytics to HTTPS transports.

Changes:

- fix(sentry): Default to HTTPS transport
- fix(mixpanel): Use HTTPS transport
- test: Use standardjs for linting
- doc(README): Add CI & npm badges
- fix(ci): Fix Appveyor Node version matrix
- refactor: Ensure Node 4 compatibility

Change-Type: patch
Connects To: #1718
2017-09-06 11:12:18 +02:00
Juan Cruz Viotti
0d0ddd549b upgrade: drivelist to v5.1.8 (#1714)
Fixes: https://github.com/resin-io/etcher/issues/1699
Change-Type: patch
Changelog-Entry: Try to use `$XDG_RUNTIME_DIR` to extract temporary scripts on GNU/Linux.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-09-04 09:56:41 -04:00
Juan Cruz Viotti
ce466bd6ad docs(README): execution -> executable (#1715)
See: https://github.com/resin-io/etcher/pull/1703
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-09-04 09:56:29 -04:00
Juan Cruz Viotti
f67f25bcdc chore: don't zip AppImages (#1703)
See: https://github.com/AppImage/AppImageKit/wiki/Creating-AppImages#common-mistake
See: https://github.com/resin-io/etcher/pull/772
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-28 11:27:01 -04:00
Juan Cruz Viotti
488f281ec7 chore: build armhf on GNU/Linux (#1482)
This commit makes use of the `resin/armv7hf-debian` Docker image to
test and generate armhf builds.

We needed to add a slash before `build` in `.gitignore` given that git
was refusing to include any changes on `scripts/build` otherwise.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-28 11:26:36 -04:00
Juan Cruz Viotti
7b791d622f feat(GUI): support new "pending" drive flag (#1709)
We recently added a "pending" flag to all drives that represents whether
the drive is ready for selection or not. This flag will be used by the
"usbboot" flashing adaptor, which will emit various "pending" USB
devices while it converts them to block devices that can actually be
flashed.

In terms of the GUI, the following visible changes were made:

- Drives with a `pending: true` property will be disabled in the drive
  selector window
- Drives with a `pending: true` property have a "PENDING" red badge

See: https://github.com/resin-io/etcher/pull/1707
See: https://github.com/resin-io/etcher/pull/1686
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-24 19:56:12 -04:00
Juan Cruz Viotti
f3c8ec496a test(shared): ensure drive objects can contain extra properties (#1705)
The usbboot integration will bring in drive objects that include a lot
more properties than the current drive objects. This commit ensures that
the redux store can handle those extra properties.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-24 19:27:38 -04:00
Juan Cruz Viotti
9f4712f1f8 refactor: use an SDK orchestrator to implement drive scanning (#1707)
This is a major first step towards adopting an SDK architecture. This
commit creates an SDK adaptor with a `.scan()` function that uses
`drivelist` under the hood. Then, an SDK orchestrator is used to provide
drive scanning capabilities to the GUI.

Here's a list of some particularly interesting changes:

- The drives returned by the SDK adaptor now have a "pending" and an
  "adaptor" property. The "pending" property is a boolean flag that
  determines if the drive is ready to be used (this will come handy for
  usbboot), while the "adaptor" property simply contains the name of the
  adaptor that drive came from

- The GUI drive scanner Rx implementation was replaces with a "promise
  loop." Before, the drive scanning routine would be called every 2
  seconds (without waiting for the previous scan to complete), while
  now, the next scan happens *after* the previous scan completes. For
  this reason, I reduced the drive scanning interval timeout to match
  the timing we had before

Change-Type: patch
See: https://github.com/resin-io/etcher/pull/1686
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-24 17:24:48 -04:00
Juan Cruz Viotti
f9d7dd2977 upgrade: drivelist to v5.1.5 (#1692)
See https://github.com/resin-io-modules/drivelist/pull/206

Change-Type: patch
Changelog-Entry: Fix "Couldn't scan the drives: An unknown error occurred" error when there is a drive locked with BitLocker.
Fixes: https://github.com/resin-io/etcher/issues/1687
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-21 17:59:16 -04:00
Juan Cruz Viotti
63d030d4c9 Revert "chore: cache Travis CI docker builds (#1694)"
This reverts commit 5e13be92f5.
2017-08-15 17:49:30 -04:00
Juan Cruz Viotti
7b308b0e50 chore: fix build system (#1695)
- Bintray deployments are broken because of some bash nested quoting
  issue
- Travis CI will attempt to cache Docker layers on macOS
- Docker caches from different architectures will override each other

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-15 15:07:15 -04:00
Juan Cruz Viotti
5e13be92f5 chore: cache Travis CI docker builds (#1694)
Let's see if we can reduce the time it gets to build and test Etcher on
GNU/Linux.

See: https://giorgos.sealabs.net/docker-cache-on-travis-and-docker-112.html
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-15 13:58:35 -04:00
Juan Cruz Viotti
325fc22a3b docs: add chocolatey install instructions (#1685)
Fixes: https://github.com/resin-io/etcher/issues/1155
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-10 17:25:07 -07:00
Juan Cruz Viotti
5196ac8d32 refactor: simplify release type handling within the app (#1667)
As another step towards moving to GitHub Releases, this commit makes the
application care much less about the actual release type of the current
version, instead checking if the application is stable or not, which is
more aligned to what GitHub provides us.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-09 08:43:19 -07:00
Juan Cruz Viotti
79a7a03d03 chore: enforce single quotes in ESLint (#1679)
We recently adopted the standardjs guidelines ESLint, which doesn't seem
to enforce single quotes, even though the guidelines mention it.

See: https://github.com/resin-io/etcher/pull/1663#discussion_r131623802
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-08 08:42:04 -07:00
Juan Cruz Viotti
b97d7080e5 v1.1.2 2017-08-07 11:26:15 -04:00
Juan Cruz Viotti
b8709d10c7 upgrade: drivelist to v5.1.4 (#1675)
Change-Type: patch
Changelog-Entry: Improve Windows drive detection error codes.
See: https://github.com/resin-io-modules/drivelist/pull/204
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-07 08:10:38 -07:00
Jonas Hermsmeier
762d570f8b refactor(gui): Only enable full debug output on demand (#1600)
This disables full wildcard debug output by default now,
leave the possibility to manually enable selective debug output
via the `DEBUG` environment variable.

Change-Type: patch
2017-08-07 07:56:28 -07:00
Jonas Hermsmeier
a2f1ddddb5 fix(svg-icon): Handle DOMParser parsererrors (#1663)
This checks for `parsererror`s in the DOMParser's returned document,
to prevent re-use of the previous image and avoid displaying an error
document in the SVG icon slot.

Change-Type: patch
Changelog-Entry: Avoid "broken" icon when selecting a zip image archive with invalid SVG.
2017-08-07 07:29:30 -07:00
Juan Cruz Viotti
b5b98cf392 chore: add type option to bintray publish script (#1670)
Used to not hardcode the architecture type, and to be able to
conditionally set the Bintray Debian headers.

See: https://github.com/resin-io/etcher/pull/1611#discussion_r131349440
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-06 19:56:17 -07:00
Juan Cruz Viotti
4827267af6 chore: add a publish-all make target (#1666)
The CI servers currently call `installers-all` to deploy snapshot
builds, however that target builds the installers, but doesn't call the
phony rules that actually publishes them.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-03 18:13:50 -04:00
Benedict Aas
de63d534c5 fix(GUI): make disabled svgs work in img tags (#1661)
SVGs are displayed through IMG tags, but these do not support CSS
`fill`, and as such we work around it with `opacity`.
2017-08-03 12:30:00 -04:00
Juan Cruz Viotti
269aafd625 fix(GUI): log known user errors when querying S3 for updates (#1655)
We send an HTTP request to S3 to determine the latest available version.
There are various error that can happen that we don't have control over
(like `ETIMEDOUT`).

The current approach is to whitelist certain errors and pretend there is
no update available, however this commit improves that whole situation.

Instead of swallowing these errors, we throw a user error from the
function that determines the latest available version. From the
application code, we check if that function throws a user error, and if
so, instead of showing it to the user, we log a mixpanel event and carry
on.

This change is motivated by the latest reporter error we can't do
anything about: `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`.

Fixes: https://github.com/resin-io/etcher/issues/1525
Change-Type: patch
Changelog-Entry: Fix `UNABLE_TO_GET_ISSUER_CERT_LOCALLY` error at startup when behind certain proxies.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-03 10:23:34 -04:00
Juan Cruz Viotti
d8e31665a0 chore: follow standardjs guidelines (#1664)
- Extend the `standard` ESLint configuration
- Remove ESLint rules that are defined in the `standard` configuration
- Get rid of semi-colons

See: https://github.com/resin-io/etcher/pull/1657
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-03 09:01:54 -04:00
Juan Cruz Viotti
5c19b70e83 refactor: adhere mostly to StandardJS guidelines (#1657)
This commit changes the whole codebase to adhere to all StandardJS
guidelines rules except semicolons, since the removal of semicolons
affect pretty much all lines, and the final diff is very hard to follow
(and to assess other more involved changes).

In a nutshell:

- When using `function`, we now require a space before the opening
  parenthesis
- If a line with operators is broken into multiple lines, the operator
  should now go after the line break
- Unnecessary padding lines are now forbidden

There were also some minor things that the `standard` CLI caught that I
updated here.

See: https://standardjs.com
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-03 06:59:02 -04:00
Dhruv Paranjape
064c741e3f docs(README): Add documentation for rpm packages. (#1652) 2017-08-02 10:14:25 -04:00
Juan Cruz Viotti
f05b28218c fix: ignore EHOSTDOWN errors when querying S3 (#1654)
There's not much we can do if we can't connect to S3 to determine the
latest available versions when checking if we should show an update
notification dialog or not.

As with similar errors, lets swallow this particular one, and try again
the next time Etcher runs.

Change-Type: patch
Changelog-Entry: Fix `EHOSTDOWN` error at startup.
Fixes: https://github.com/resin-io/etcher/issues/1645
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-02 10:12:45 -04:00
Juan Cruz Viotti
4b4e6ea035 upgrade: drivelist to v5.1.3 (#1653)
This version contains the following fixes:

- Fix "Couldn't initialize the scanner: An unknown error occurred" error
- Fix "Couldn't scan the drives: An unknown error occurred" where there
  is a mounted virtual drive

See: https://github.com/resin-io-modules/drivelist/blob/master/CHANGELOG.md
Change-Type: patch
Changelog-Entry: Fix various drive scanning Windows errors.
Fixes: https://github.com/resin-io/etcher/issues/1646
Fixes: https://github.com/resin-io/etcher/issues/1639
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-02 10:12:27 -04:00
Juan Cruz Viotti
861b8a4450 fix(GUI): throw a user error if the user is not in the sudoers file (#1620)
Change-Type: patch
Changelog-Entry: Display a user-friendly error message if the user is not in the sudoers file.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-01 17:35:45 -04:00
Benedict Aas
70ad86534d feat(GUI): make size units closest relative (#1539)
We make the size units used the closest relative unit through a new
filter `closestUnit` replacing the old `gigabyte` filter.

Changelog-Entry: Round byte sizes to the more appropriate unit.

* remove filters folder

* new shrinkwrap, add to package.json

* test
2017-08-01 17:34:13 -04:00
Benedict Aas
7714e8b50a fix(GUI): make archive-embedded svgs work again (#1642)
We make the svg-icon component accept XML in its path argument to handle
archive-embedded SVG icons.

Changelog-Entry: Make archive-embedded SVG icons work again.
Fixes: https://github.com/resin-io/etcher/issues/1636
2017-08-01 12:34:06 -04:00
Juan Cruz Viotti
a63b6bf18c fix(CLI): pass required arguments to flashComplete message (#1630)
The `flashComplete` message takes the drive object and the image
basename as arguments. This was updated on the GUI, but causes the CLI
to throw an error upon completion.

Change-Type: patch
Changelog-Entry: Fix "imageBasename is not defined" error on the CLI.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-01 12:32:50 -04:00
moragues
70c79f6127 feat: support rpi-sdcard image file type (#1648)
Support the rpi-sdcard image file type output by Yocto for
the Raspberry Pi device.

Change-Id: Ia7e3aef0d90fdf21d373a560e6dd2b96e6b51da8
Changelog-Entry: Add support for `.rpi-sdcard` images.
2017-08-01 10:34:25 -04:00
Juan Cruz Viotti
de62b2e65c chore: publish development Bintray packages (#1611)
This commit includes several changes to adapt the CI configuration files
and Bintray publish script to perform development deployments.

- Move our Bintray details to the Makefile
- Deploy to a new Bintray component if `RELEASE_TYPE` is `snapshot`
- Call `publish-bintray-debian` and `publish-bintray-redhat` in the CI
  deployment script
- Call the Bintray deployment scripts for RPMs

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-01 10:29:09 -04:00
Juan Cruz Viotti
1103492193 refactor: address review comments from #1625 (#1647)
That PR was merged in a rush, so this is the follow-up commit addressing
the review comments made there.

See: https://github.com/resin-io/etcher/pull/1625
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-01 10:27:59 -04:00
Juan Cruz Viotti
fc3eeff1c9 refactor(GUI): make settings model setter asynchronous (#1597)
This is part of the process of implementing support for a configuration
file. We previously decoupled the Redux store from localStorage by
moving the logic that actually persists the data to localStorage to a
local-settings.js file, however the localStorage API is synchronous, so
it follows that at the moment, all functions that interact with are also
synchronous.

Moving to storing the settings to a file means turning all these
functions to promises, which we do in this commit, in order to not mix
the addition of the configuration file feature with the huge amount of
refactoring it requires.

See: https://github.com/resin-io/etcher/issues/1356
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-01 10:27:15 -04:00
Juan Cruz Viotti
205711da7e refactor(image-stream): parse xz and gzip metadata using a custom read function (#1590)
This commit refactors the xz and gzip image handlers to pass/use a
custom read function to be able to determine the uncompressed size, and
other needed metadata.

By using this function (which currently only uses the `fs` module), we
can implement support for getting the uncompressed size of compressed
files using HTTP Ranges.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-08-01 10:24:19 -04:00
Lucas Rangit MAGASWERAN
57709942a0 docs(README): add debian repository in one line (#1649)
For convenience, create the apt source file and add the repository in one line.

Signed-off-by: Lucas Magasweran <lucas.magasweran@ieee.org>
2017-07-31 16:06:25 -03:00
Juan Cruz Viotti
5e582ceb98 chore: use electron-builder default package names (#1609)
We're currently manually changing the names of the final packages
created by `electron-builder`. This commit makes Etcher use the default
package names that `electron-builder` picks for us.

The Windows final package names contain spaces, so I did keep the
`artifactName` entries for them, which now basically use what
`electron-builder` recommends, but use hyphens instead of spaces.

Change-Type: minor
See: https://github.com/resin-io/etcher/pull/1555
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-31 16:04:10 -03:00
Jonas Hermsmeier
25d50fed74 doc: Merge running locally into contributing guide (#1640)
As recently several people have been asking for things
that are described in `RUNNING-LOCALLY.md`, but couldn't be
found in the `CONTRIBUTING.md`, this consilidates the two into
one single resource to look for on how to get started developing.

Change-Type: patch
2017-07-31 17:24:33 +02:00
Jonas Hermsmeier
07ac2ecf4c doc: Add link to commit guidelines to contributing guide (#1641)
This adds a reference to the commit guidelines to the contributing guide.
Fixes #1494

Change-Type: patch
2017-07-28 12:44:15 +02:00
Juan Cruz Viotti
7908c39ef4 v1.1.1
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-25 09:50:24 -03:00
Juan Cruz Viotti
b64ef705e8 chore: use old custom build system to create AppImages (#1625)
electron-builder seems to ship with an older AppImages version that
doesn't play very well with the custom AppImages elevation system we
created.

More particularly, we can't execute custom binaries inside the mounted
AppImage given that the mount point seems to lose permissions, owner,
and group file information.

This commit goes back to our old custom build system just for AppImages,
until we properly solve the problem, which will likely involve updating
the AppImages version in electron-builder.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-25 09:47:33 -03:00
Jonas Hermsmeier
36664fb251 fix(writer): Use final size if it's not an estimation (#1587)
This avoids running into the "flashstate percentage above 100%" error again.

Change-Type: patch
Changelog-Entry: Prevent "percentage above 100%" errors on DMG images.
2017-07-24 16:54:02 -03:00
Andrew Scheller
fa8f8151f6 docs(PUBLISHING): fix Etcher forum link (#1626) 2017-07-24 19:55:34 +01:00
Andrew Scheller
bebedf1a50 chore: make distclean now deletes build directory too (#1624) 2017-07-24 13:12:46 -03:00
Juan Cruz Viotti
f53a0af150 upgrade: mountutils to v1.2.1 (#1623)
This version contains a fix to a set of very recurrent "Unmount failed"
macOS errors.

See: https://github.com/resin-io-modules/mountutils/pull/44
Change-Type: patch
Changelog-Entry: Fix most "Unmount failed" errors on macOS.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-24 09:36:31 -03:00
Juan Cruz Viotti
09bf430a1e chore: remove the concept of target and host platforms (#1610)
Its very unlikely that we will ever support cross platform builds. For
that reason, let's simplify the whole Makefile by removing the concept
of target and host platforms.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-23 23:33:05 -03:00
Juan Cruz Viotti
b221914a3d fix(GUI): properly pass error object to "Flash error" event (#1619)
Simply running `_.merge` on an Error object results in an empty plain
object `{}` being sent to Mixpanel/Sentry.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-23 23:32:50 -03:00
Juan Cruz Viotti
1d66794450 fix(windows): include local native modules in final asar (#1616)
Etcher has local native code that gets built to `build/`, but that's not
being included inside the final asar.

The fix is to manually add the `*.node` files inside `build/Release` by
adding the appropriate wilcard to the `files` section of
`electron-builder.yml`.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-21 09:10:46 -03:00
Juan Cruz Viotti
1563a2392d v1.1.0
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-20 14:48:30 -03:00
Juan Cruz Viotti
a19b0e028f upgrade: drivelist to v5.0.27 (#1607)
This new version contains the following PRs that we're interested about:

- https://github.com/resin-io-modules/drivelist/pull/196

To reduce the amount of debug logging we produce (see
https://github.com/resin-io/etcher/pull/1600).

- https://github.com/resin-io-modules/drivelist/pull/195

To properly handle spawning EAGAIN errors.

Fixes: https://github.com/resin-io/etcher/issues/1578
Change-Type: patch
Changelog-Entry: Retry various times on EAGAIN when spawning drive scanning scripts.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-19 15:23:32 -03:00
Andrew Scheller
fa60a746a2 chore: fix typos in target-convert.sh (#1608) 2017-07-19 10:04:15 -03:00
Benedict Aas
227533a7f9 upgrade(package): update resin-corvus to 1.0.0-beta.28 (#1604)
Closes: https://github.com/resin-io/etcher/issues/1465
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-18 14:54:03 -03:00
Juan Cruz Viotti
4122e0bf1d refactor: move most models to lib/shared/ (#1596)
Now that the Redux store is no longer front-end dependent, we can move
most of the models to lib/shared. Currently, lib/shared is a mess, and
contains all sorts of functionality, however moving things out of the
GUI is the first step. Once we have everything decoupled, we can
organise all the code we have there.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-18 12:34:10 -03:00
Juan Cruz Viotti
3a42331875 fix(GUI): incorrect function call in FlashController (#1606)
This commit fixes a subtle issue where we are calling a non-existing
function of an error object, instead of using the exception reporter
module.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-18 11:47:26 -03:00
Juan Cruz Viotti
37b7ea3b0a refactor(image-stream): extract part of utils.js into mime.js (#1594)
This is a small refactoring commit that extracts the MIME related
function from utils.js into a new file called mime.js, and stores the
default image MIME type there as a constant, to avoid duplicating it in
multiple parts of the code.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-14 19:59:33 -04:00
Juan Cruz Viotti
a772877ae1 test(image-stream): move extraction timeout to a shared constant (#1599)
The image stream tests that extract images all have a 20s timeout, which
is manually set in all the suites related to extraction.

This commit extracts that number as a constant called DEFAULT_TIMEOUT.

See: https://github.com/resin-io/etcher/pull/1595
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-14 19:59:25 -04:00
Juan Cruz Viotti
76b6bdfd06 chore: cache ~/.pkg-cache in Travis CI and Appveyor CI (#1598)
Looks like pkg downloads node binaries from GitHub Releases, and GitHub
may impose a rate limiting if we download too many things from them in a
short period of time (likely to happen when there are many concurrent
PRs).

In order to mitigate this issue, this commit adds `$HOME/.pkg-cache`,
the directory where pkg stores node binaries, to the CI services cache.

See: https://github.com/resin-io/etcher/pull/1594
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-14 11:48:45 -04:00
Juan Cruz Viotti
2a8e91190c test(image-stream): increase DMG tests timeouts (#1595)
I caught an sporadic issue a couple of times, where the DMG tests would
exceed the default 2000ms mocha timeout. All the other image
decompression tests have a much higher timeout already, so this commit
adds the same timeout to the DMG tests file.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-13 17:41:44 -04:00
Juan Cruz Viotti
be8a638fce chore: pass --quiet to pip install (#1592)
This helps reduce a bit of output in the CI servers.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-13 16:15:03 -04:00
Juan Cruz Viotti
3e2da6a386 chore: cache electron-builder temporary files in macOS (#1591)
Our current Travis CI configuration caches temporary files created by
electron-builder, but only for GNU/Linux builds. In macOS, electron and
electron-builder store their cache at ~/Library/Caches, so we must cache
that as well.

This commit was motivated by the fact that most macOS builds are failing
for Electron package download timeouts.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-13 11:37:26 -04:00
Juan Cruz Viotti
ff547035be chore: only ignore top level directories in gitignore for some cases (#1588)
We accidentally added build/ to gitignore, causing any new files from
`scripts/build` to be ignored.

See: https://github.com/resin-io/etcher/pull/1547#discussion_r126790010
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-13 10:23:22 -04:00
Juan Cruz Viotti
ca9136d1cb chore: send analytics about package types (#1570)
This commit adds a `packageType` property to package.json, which is set
according to the package type of the Etcher target (e.g: dmg, nsis, deb,
etc).

This information is then sent to Mixpanel as the `packageType` property
of the "Application start" event.

Change-Type: patch
Changelog-Entry: Send anonymous analytics about package types.
Fixes: https://github.com/resin-io/etcher/issues/1328
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-13 10:13:56 -04:00
Juan Cruz Viotti
439be1c222 refactor(image-stream): rename file variable to imagePath (#1589)
This is a small initial step towards decoupling the image stream
handlers from the concept of a "file."

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-13 09:30:28 -04:00
Juan Cruz Viotti
77c60b91c6 upgrade: drivelist to v5.0.25 (#1574)
This version contains various improvements on the drive detection system
mainly on Windows. The improvements can be summarized as follows:

- Drivelist no longer spawns a .bat script to perform its job. This
  means that a lot of spawning related issues are now fixed

- Drivelist doesn't fetch drive sizes from WMI anymore, which was known
  to incorrectly report a very small size for certain drives, causing
  the famous "0.0 GB" Windows issues (see
  https://github.com/resin-io-modules/drivelist/issues/142)

- Cleanup temporary scripts after execution

This PR also sets the DRIVELIST_DEBUG environment variable to enable
debug information from Windows' drivelist implementation.

Change-Type: patch
Changelog-Entry: Implement Windows drive detection using C++
Changelog-Entry: Fix various Windows `.bat` spawning issues
Changelog-Entry: Fix 0.0 GB Windows drive detection issues
Changelog-Entry: Cleanup drive detection temporary scripts created for other operating systems
Fixes: https://github.com/resin-io/etcher/issues/1108
Fixes: https://github.com/resin-io/etcher/issues/1054
Fixes: https://github.com/resin-io/etcher/issues/995
Fixes: https://github.com/resin-io/etcher/issues/1483
Fixes: https://github.com/resin-io/etcher/issues/1142
Fixes: https://github.com/resin-io/etcher/issues/1571
See: https://github.com/resin-io-modules/drivelist/blob/master/CHANGELOG.md
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-12 15:18:05 -04:00
Juan Cruz Viotti
a5b1a92920 chore: add eslint-jsdoc-plugin to eslint (#1585)
This plugin helps us detect some things the built-in jsdoc rules can't,
like whether there is an example or not.

As expected, the addition of this plugin helped detect some minor JSDoc
issues.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-12 10:19:08 -04:00
Jonas Hermsmeier
58fa59e06d upgrade(package): Update udif 0.9.0 -> 0.10.0 (#1586)
This updates `udif` from 0.9.0 to 0.10.0, fixing two bugs;

* [57ddf788] fix(readstream): Avoid read-before-open situations
* [6333a183] fix(image): try/catch parsing the resource fork plist

[57ddf788]: 57ddf788b7
[6333a183]: 6333a183f6

Change-Type: patch
2017-07-12 10:21:38 +02:00
Benedict Aas
fc6c5bf585 refactor(GUI): deangular os-dialog and error module (#1546)
We remove the Angular dependency from `lib/gui/os/dialog` and
`lib/gui/modules/error` which is also now renamed to
`lib/gui/modules/exception`.

Changelog-Entry: Deangular the os-dialog and error modules
2017-07-11 17:21:48 -04:00
Juan Cruz Viotti
e52ef501bb chore: avoid brew taking a long time on macOS Travis builds (#1583)
- Homebrew now auto-updates before performing any installation, which
  can take quite some time. We can disable this by enabling
  HOMEBREW_NO_AUTO_UPDATE

- We can pass the --force-bottle option to `brew install` to force it to
  download pre-compiled binaries, and don't attempt any compilations

See: https://github.com/resin-io/etcher/pull/1582
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-11 17:12:44 -04:00
Juan Cruz Viotti
6ffba92dc8 chore: make use of pkg to package the Etcher CLI (#1547)
This commit replaces our home-grown CLI packaging mechanism based on
browserify + node-static-entry-point with pkg, an open source tool to
package Node.js applications for distribution.

Some highlights:

- Removing browserify got rid of a lot of dependencies from
  npm-shrinkwrap.json

- pkg currently has an issue where macOS binaries can't be code-signed
  (https://github.com/zeit/pkg/issues/128), therefore this commit
  comments-out the binary signing section for that operating system

- pkg currently has an issue where Windows binaries can't be branded
  (https://github.com/zeit/pkg/issues/149), therefore this commit
  comments-out the branding section for that operating system

See: https://github.com/zeit/pkg
Fixes: https://github.com/resin-io/etcher/issues/1531
Fixes: https://github.com/resin-io/etcher/issues/1450
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-11 14:37:14 -04:00
Juan Cruz Viotti
3ade1ea59b chore: don't install NSIS in Appveyor CI (#1584)
This dependency comes bundled with electron-builder, so there is no
reason to install it separately.

See: https://github.com/resin-io/etcher/pull/1582
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-11 14:14:15 -04:00
Juan Cruz Viotti
427a791de5 refactor(GUI): remove flash of white electron webContents workaround (#1575)
The lib/gui/etcher.js file contained a workaround to an Electron issue
that have since then been solved. In summary:

- Replace the `did-finish-load` event of `webContents` with
  `ready-to-show`, which is only emitted when the whole webview has
  finished loading

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-11 11:56:05 -04:00
Juan Cruz Viotti
dbe6ea68d5 chore: cache as most as possible from electron-builder (#1582)
These directories contain files downloaded by electron-builder (like
electron itself), that we can cache in Travis CI and Appveyor CI to
speed up builds.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-11 11:46:57 -04:00
Juan Cruz Viotti
b6c6eb4dfa chore(appveyor): make node_modules cache depend on npm-shrinkwrap.json (#1580)
We've been hitting some weird npm-shrinkwrap.json issues in our
shrinkwrap staged sanity checks, where Appveyor would complain that the
shrinkwrap is not up to date, while that wasn't the case either locally
or in Travis CI.

The issue is related to caching. If a commit changes a `from` entry of a
npm-shrinkwrap.json dependency, but the CI servers kept the cached
node_modules, then there will be a discrepancy between the `_from` field
from the `package.json` of a dependency in `node_modules` and what the
npm-shrinkwrap.json says. npm will obey `node_modules` over
`npm-shrinkwrap`, causing the invalid diff.

The fix is to make the Appveyor node_modules cached directory dependent
on any change to the npm-shrinkwrap.json file.

Change-Type: patch
See: https://github.com/resin-io/etcher/pull/1547
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-10 15:07:09 -04:00
Juan Cruz Viotti
fdceaadec5 refactor(GUI): move redux store to lib/shared (#1576)
After https://github.com/resin-io/etcher/pull/1569, the redux store can
run outside of a browser context. This commit moves it to `lib/shared`,
where we will likely move all the other models as well. As an extra, I
renamed `Store` to `store`, since there was no reason for that variable
to be capitalized.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-07 18:47:39 -04:00
Juan Cruz Viotti
4dc56f4678 refactor(GUI): decouple localStorage from the redux store (#1569)
We're currently persisting the user settings in localSettings by using a
redux plugin called redux-localstorage. As a way to decouple the redux
store from a technology that is browser specific, this commit makes the
following changes:

- Create local-settings.js, which is concerned with managing settings in
  a persisting location

- Decouple the redux store from the persisting storage method

- Extend the settings model to persist settings, cache reads, etc

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-06 17:49:13 -04:00
Jonas Hermsmeier
1b79d50288 fix(gui): Fix image checks in image selections (#1573)
I must have screwed something up during a rebase,
this mends the partition table an windows image checks.

Change-Type: patch
2017-07-06 16:00:07 -04:00
Juan Cruz Viotti
1b695a49e9 upgrade: electron-builder to v19.9.1 (#1548)
- Exclude *.dll/*.exe files from the asar in non-Windows operating
  systems (from 19.8.0)

- Correctly parse boolean flags in `--extraMetadata` (in v19.9.0)

See: https://github.com/electron-userland/electron-builder/releases/tag/v19.9.1
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-06 13:51:55 -04:00
Juan Cruz Viotti
fd109b5770 fix(elevator): make use of wide characters everywhere (#1559)
Switching the Windows language to a language encoded using UTF-16 (like
Japanese) revealed that our native elevator module garbles language
specific strings, making the child writer process unable to find an
image inside a language specific directory, and thus resulting in a
"File is not accessible" error.

As a solution, we make use of `std::wstring` and wide character Windows
API functions in the elevator module.

Change-Type: patch
Changelog-Entry: Fix "file is not accessible" error when flashing an image that lives inside a directory whose name is UTF-16 encoded on Windows.
Fixes: https://github.com/resin-io/etcher/issues/1459
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-05 14:13:36 -04:00
Jonas Hermsmeier
80b588683e feat(image-stream): Read MBR & GPT in .getImageMetadata() (#1248)
* feat(image-stream): Read MBR & GPT in .getImageMetadata()
* feat(gui): Display warning when image has no MBR
* test(image-stream): Update .isSupportedImage() tests
* feat(image-stream): Normalize MBR & GPT partitions
* test(image-stream): Add partition info
* feat(image-selection): Send missing part table event
* test(image-stream): Add GPT test image

Change-Type: minor
2017-07-05 16:18:02 +02:00
Benedict Aas
b18fa1f13f feat(GUI): add webview api version parameter (#1558)
We add the API version sent to the banner via a GET search parameter,
allowing for more intricate control over what data needs or can be sent.
2017-07-04 13:11:44 -04:00
Jonas Hermsmeier
f1ddf07a45 test(image-stream): Test more compression methods (#1565)
* test(image-stream): Add more zip compression methods
* test(image-stream): Add more dmg compression methods
* test(image-stream): Add bz2 level 9 test

Change-Type: patch
2017-07-03 23:35:06 +02:00
Jonas Hermsmeier
5f5a4b61b0 chore(scripts): Silence stdout for npm install (#1567)
Change-Type: patch
2017-07-03 17:08:53 -04:00
Andrew Scheller
20ca03496f chore: fix typo in Makefile (#1562)
This is a change that should have been made in #1543
2017-07-03 16:26:10 -04:00
Juan Cruz Viotti
7af66c4911 chore:(windows): make use of NSIS one-click installers (#1560)
One-click installers are a "modern" version of usual wizard installers,
and somewhat resemble the Squirrel.Windows installers you can see in
apps like Atom.

As the name implies, the user needs to agree the license, and that's
all, the remaining installer is non-interactive, leading to a very
smooth user experience.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-03 16:25:48 -04:00
Juan Cruz Viotti
2e3a2f045e chore: pipe stdout from npm ls to /dev/null (#1566)
As part of our CI sanity checks, we run `npm ls`, to ensure we don't
have any extraneous dependencies (the command fails if so), however by
its own definition, `npm ls` prints the whole dependency tree, which
spams the builds.

This commit redirects stdout to /dev/null, which contains the dependency
tree, but still prints and extraneous dependency warning, which is
printed to stderr instead.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-03 13:14:22 -04:00
Juan Cruz Viotti
c2563c2f87 chore(npm): move retry options to INSTALL_OPTS (#1564)
See: https://github.com/resin-io/etcher/pull/1550/files#r125015773
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-03 11:48:07 -04:00
Juan Cruz Viotti
53d8118b8f chore: don't remove optional dependencies in clean-shrinkwrap.js (#1551)
If we include a platform specific optional dependency in the shrinkwrap
file, then npm will insist in installing it even if the platform doesn't
match. As a solution, we figured out we can avoid putting this platform
specific optional dependencies in the npm-shrinkwrap.json file.

In order to do this, we currently have a script called
`clean-shrinkwrap.js` that runs *before* any `npm shrinkwrap` file (its
a `preshrinkwrap` npm script) that deletes all the platform specific
modules we know about using `npm rm`.

The problem with this approach is that `npm rm` will remove the module's
code from `node_modules`, which means that if we run `npm shrinkwrap`,
we will lose certain optional dependencies, that may be needed at a
later stage.

The solution is to modify the `clean-shrinkwrap.js` script to parse
`npm-shrinkwrap.json`, and manually delete the entries that we want to
omit. Also, the script needs to be run *after* `npm shrinkwrap`, so we
change the npm script name to `postshrinkwrap`.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-07-03 10:30:04 -04:00
Jonas Hermsmeier
9bd987f7f3 chore(package): Disable node_modules caching on Travis CI (#1561)
This disabled caching of the `node_modules` directory again,
as this is causing failures on Travis CI while building the installers.

Change-Type: patch
2017-06-30 09:54:25 -04:00
Jonas Hermsmeier
a370e9d4cb feat(gui): Show friendlier error dialog when opening images (#1557)
* feat(gui): Friendly error dialog when opening image fails

This displays a friendlier error dialog if opening an image fails
due any reason (like i.e. an unsupported compression method)

Change-Type: patch

* test(image-stream): Add test for unsupported compression method
* test(image-stream): Only check `error.description` when given
* test(image-stream): Add zip-deflate64.zip
2017-06-28 16:44:21 +02:00
Jonas Hermsmeier
65210e4cbc chore(ci): Enable node_modules & ccache caching (#1553)
This enables caching of `node_modules`, and `ccache` directories,
as well as installation of ccache on Mac OS.

Change-Type: patch
2017-06-27 23:27:43 +02:00
Jonas Hermsmeier
2008c50ebf chore(scripts): Make npm output less verbose (#1554)
This adds the `--silent` flag to several npm commands,
ideally making the output less verbose, for better overview in CI logs.

Change-Type: patch
2017-06-27 22:27:34 +02:00
Juan Cruz Viotti
3ab989cf3c chore: increase npm retries and max timeout (#1550)
CI servers fail with timeouts, or network issues quite frequently,
requiring maintainers to manually restart failed builds.

Hopefully these npm settings will help mitigating these issues.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-27 13:11:54 -04:00
Juan Cruz Viotti
d8e9cb93b7 chore: move all electron-builder configuration to electron-builder.yml (#1544)
The electron-builder configuration we're putting in package.json is
growing. To make it easier to read and edit, we'll move the whole
`build` property into a configuration file called
`electron-builder.yml`.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-27 10:15:38 -04:00
Juan Cruz Viotti
cd4cff7e43 chore: remove npm ranges from package.json (#1549)
We don't make use of npm ranges at all (every dependency and its
subdependencies are shrinkwrapped). Removing npm ranges allows us to
simplify our clean-shrinkwrap.js script to get rid of platform specific
optional dependencies, and their subdependencies.

See: https://github.com/resin-io/etcher/pull/1514
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-26 18:49:51 -04:00
Juan Cruz Viotti
9b735778c2 chore: use various electron-builder defaults (#1543)
Now that all GUI builds are done through electron-builder, we'll
simplify our Makefile by adopting certain electron-builder defaults:

- Output final packages in `dist/`
- Adopt electron-builder code-signing environment variables

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-24 15:54:55 -04:00
Juan Cruz Viotti
a7ac28b717 chore: make use of electron-builder to build GNU/Linux packages (#1520)
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-23 20:10:51 -04:00
Juan Cruz Viotti
4f87079f12 chore: make use of electron-builder for the package-electron target (#1540)
This target builds a package for the current operating system, but
doesn't create an installer out of it, which is useful for debugging
purposes.

Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-23 18:59:15 -04:00
Juan Cruz Viotti
840388e8c5 chore: don't extract native dependencies out of the asar (#1542)
Turns out add-ons are loaded just fine from the asar now.

See: https://github.com/electron-userland/electron-builder/issues/1723
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-23 18:57:57 -04:00
Benedict Aas
5297ddf68c feat(GUI): swap progress bar speed and time (#1537)
We swap the placement of the progress speed and time residing below the
progress bar.

Changelog-Entry: Swap speed and time below the flashing progress bar.
Closes: https://github.com/resin-io/etcher/issues/1312
2017-06-22 17:35:51 -04:00
Jonas Hermsmeier
4f4c606949 test(image-stream): Fix test image data (#1535)
This updates the base test image to be a complete, but small
disk image, as thre previous image was quite large for running tests (32MB),
and was chopped off at an arbitrary position, causing other tools to fail
on it as an input.

Change-Type: patch
2017-06-21 16:31:21 +02:00
Juan Cruz Viotti
dbc8aa159d chore(travis): remove unused afsctool macOS dependency (#1521)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-16 17:36:00 -04:00
Juan Cruz Viotti
103a048e4d refactor(GUI): replace SET_SETTING with an atomic SET_SETTINGS action (#1515)
This commit is the first on a series of commit to incrementally
implement support for configuration files (so we avoid a huge PR like we
have at the moment).

Once of the first things we can do is replace the `SET_SETTING` redux
action with an atomic `SET_SETTINGS` action that sets all the settings
for the application at once.

The purpose of this change is that later the `SET_SETTINGS` action can
be modified to stringify all the settings and store them in a
configuration file, without having to deal with merges, conflicts, etc
(since the client application if forced to resolve those problems before
calling the `SET_SETTINGS` action.)

The behaviour of the code remains almost the same, with the exception
that the user can now set settings that we don't know about, so the user
can switch between Etcher versions without getting weird errors if one
of the configuration keys he has doesn't exist in the other version.

See: https://github.com/resin-io/etcher/pull/1382
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-15 12:57:15 -04:00
Juan Cruz Viotti
a8f6275763 chore: generate single-binary portable installers on Windows (#1518)
We currently support portable builds that are basically ZIPs containing
the main Etcher executable and all its related libraries.

Turns out `electron-builder` supports NSIS-based portable builds that
can create a single executable that has everything it needs to run,
including any external assets.

This commit makes use of this new portable Windows installer
functionality, replacing the old ZIP approach.

Change-Type: patch
Changelog-Entry: Generate single-binary portable installers on Windows.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-15 12:10:22 -04:00
Benedict Aas
0f600c3cc2 refactor(GUI): remove angular dependency from drive scanner (#1512)
Remove the Angular dependency from DriveScanner and with it the service,
exposing it through the module directly.
2017-06-15 11:26:03 -04:00
Juan Cruz Viotti
9c1f9a54b1 chore: fix version/platform order inconsistencies in package names (#1517)
See: https://github.com/resin-io/etcher/pull/1132#discussion_r121654527
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-15 10:12:00 -04:00
Juan Cruz Viotti
2f605497be chore: use electron-builder to generate macOS builds (#1511)
This commit makes use of electron-builder to replace what our scripts
were already doing.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-15 10:11:49 -04:00
Juan Cruz Viotti
07adafe6f3 chore: use the new electron-builder version to create NSIS installer (#1510)
We've been using `electron-builder` v2 all this time to create the NSIS
installer. This commit upgrade `electron-builder` to v18.6.2, and keeps
using it just to create the NSIS installer (for now).

The final package behaves exactly like the one we have before, just that
we needed various tweaks to upgrade to the latest `electron-builder`
version.

In more detail:

- Inject data to package.json using the new `--extraMetadata` option
- Remove old `.builder` package.json property
- Change the author of the project to Resin Inc. (the company name used
  in our code-signing certificate)

As an extra, the new NSIS installer allows the user to install the
application to any location, and fixes the fact that the previous
installer copied the application to C:\Program Files (x86) even on x64
systems.

Change-Type: patch
Fixes: https://github.com/resin-io/etcher/issues/1030
Fixes: https://github.com/resin-io/etcher/issues/877
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-13 11:19:29 -04:00
Juan Cruz Viotti
15b178a158 refactor(GUI): move ETCHER_DISABLE_UPDATES into package.json (#1501)
Etcher supports disabling the update notification dialog by setting the
`ETCHER_DISABLE_UPDATES` environment variable.

In order to simplify disabling updates for when these are managed by a
package manager (e.g. in a debian package), this removes support for the
`ETCHER_DISABLE_UPDATES` environment variable, and instead requires
packagers to tweak the `updates.enabled` property of the package.json
file, which is set to `true` by default.

We don't want to encourage end users to disable the update mechanism, so
the documention was removed from `USER-DOCUMENTATION.md`. This option
will remain as something only packagers should tweak.

Change-Type: minor
Changelog-Entry: Remove support for the `ETCHER_DISABLE_UPDATES` environment variable.
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-13 09:07:47 -04:00
Andrew Scheller
22be831535 chore: move mkdir call from node-package-cli.sh to Makefile (#1516)
This makes it more consistent with the other Makefile rules
2017-06-13 14:00:43 +01:00
Juan Cruz Viotti
71ebe047c6 chore: don't use ./ when generating sass files (#1513)
The `./` prefix is unnecessary.

See: https://github.com/resin-io/etcher/pull/1505#pullrequestreview-43444274
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-12 15:17:43 -04:00
Dhruv Paranjape
f350d28dbd chore: Add support for rpm packages (#1425)
* add support for rpm packages.

* remove bintray file not my place neither do i have the keys.

* Remove last visage of publishing rpm's to bintray.

* address review comments.

* remove electron installer redhat from optional dependancies and add it to dockerfiles. also remove variable ELECTRON-INSTALLER-REDHAT inline with electron installer debian script.

* Add dependancy on libXScrnSaver and remove unsupported fields from config.json.
add rpm package to dockerfiles.
add dependancy check on rpmbuild to installer script.

* change dependancy from lsb-core-noarch to just lsb.

* address review comments.

* Add bintray target for rpm packages.

* Fix missing dependancy removed during conflict resolution.
2017-06-12 18:54:31 +01:00
Benedict Aas
a7d713c323 feat(GUI): rewrite svg-icon directive in react (#1464)
We change from using an Angular directive to using React through
react2angular in the SVGIcon module.
2017-06-12 08:42:52 -04:00
Benedict Aas
ef739fb222 refactor(GUI): remove angular dependency from selection-state (#1509)
We remove the dependency on Angular from SelectionStateModel and rename
it to selectionState.
2017-06-12 08:40:52 -04:00
Juan Cruz Viotti
cff445b64b chore: move npm targets to Makefile (#1505)
We currently have various npm script target, and some of them are
getting complex enough that making sense out of them in package.json is
not a trivial task.

This commit moves all npm targets that are not directly recognisable by
npm (like `start`, `test`, `preshrinkwrap`, etc) into the Makefile.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-10 13:50:29 -04:00
Juan Cruz Viotti
b16f9cfdf7 chore: re-organize package.json in a way similar to electron-builder (#1504)
This commit re-organizes various metadata properties in package.json so
that the structure better matches what `electron-builder` expects, to
ease the transition.

- Move `.companyName` to the Makefile (we don't need this in
  package.json)
- Move `.displayName` to `.build.productName`
- Move `.copyright` to `.build.copyright`
- Move category to `.build.mac.category`
- Move bundle id to `.build.appId`

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-10 13:37:44 -04:00
Juan Cruz Viotti
b12c952a6a chore: output build artifacts to dist/ (#1506)
This is the directory where `electron-builder` will output build
artifacts.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-10 13:37:36 -04:00
Juan Cruz Viotti
9bab3054e9 chore: remove ampersand from package description (#1503)
The ampersand confuses nupkg when generating Windows installers from
`electron-builder`.

The referenced issue talks about an issue where the ampersand is present
on the application name, but anything that gets into the `.nuspec` XML
file, including the description, triggers the issue.

See: https://github.com/electron-userland/electron-builder/issues/517
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-09 15:46:08 -04:00
Juan Cruz Viotti
927a0aba06 chore: remove unused electron-packager dependency (#1502)
We're not using this development dependency anymore. Furthermore, we're
also not using the `packageignore.js` script, which was meant to be used
with `electron-packager`.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-08 15:08:37 -04:00
Juan Cruz Viotti
8811bbed09 upgrade: drivelist to v5.0.22 (#1500)
- https://github.com/resin-io-modules/drivelist/pull/168

Change-Type: patch
Changelog-Entry: Fix occasional increased CPU usage because of perl regular expression in macOS.
Fixes: https://github.com/resin-io/etcher/issues/1288
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
2017-06-08 13:36:57 -04:00
Benedict Aas
31a2389d04 fix(GUI): reset webview after navigating away (#1422)
We reload and reset the webview to its original URL when the user
navigates away from the success screen.

Changelog-Entry: Reset webview after navigating away from the success screen.
2017-06-08 11:42:55 -04:00
Romain Bazile
a3c13e75cf feat: support .sdcard images (#1493)
Change-Type: minor
Changelog-Entry: Add support for `.sdcard` images.
Link: https://github.com/resin-io/etcher/issues/1360
Fixes: https://github.com/resin-io/etcher/issues/1348
Fixes: https://github.com/resin-io/etcher/issues/1361
2017-06-06 12:57:55 -04:00
Jonas Hermsmeier
6037eeba00 doc(README): Update & normalize badges (#1491)
This updates & normalizes the badges in the README to all have
a consistent style and adds a release-badge pointing to the website.

Change-Type: patch
2017-06-05 18:54:48 -04:00
Jonas Hermsmeier
ce50364b9f upgrade(package): Update node-sass to 4.5.3 (#1489)
This updates node-sass from v3.x to v4.x in anticipation
of addition of Electron ABI versions in an upcoming version.

Change-Type: patch
2017-06-05 18:38:19 +02:00
Benedict Aas
14b04413b5 refactor(GUI): remove angular from DrivesModel (#1265)
We remove usage of Angular from DrivesModel.

Depends: https://github.com/resin-io/etcher/pull/1261
Depends: https://github.com/resin-io/etcher/pull/1264

* remove angular injection from tests

* move file

* add empty array test
2017-06-05 10:30:58 -04:00
Juan Cruz Viotti
dc2212a57f fix(GUI): ignore UNABLE_TO_VERIFY_LEAF_SIGNATURE HTTP issues (#1473)
This error may get thrown when fetching the list of S3 packages when the
user is behind a proxy tht causes the SSL certificate to incorrectly not
be trusted.

See: https://github.com/atom/apm/issues/103
See: https://github.com/resin-io/etcher/issues/1465
Change-Type: patch
Changelog-Entry: Fix `UNABLE_TO_VERIFY_LEAF_SIGNATURE` error at startup.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-06-05 10:22:15 -04:00
Jonas Hermsmeier
fe40e7bdf1 chore(package): Update mountutils to 1.2.0 (#1488)
This updates `mountutils` from 1.0.6 to 1.2.0, which includes
various fixes and adds AsyncWorkers:

- fix(windows): Replace use of `wsprintf()`
- fix(darwin): Add local context to avoid global state
- feat(src): Use Nan::AsyncWorker

Change-Type: upgrade
2017-06-04 15:17:07 +02:00
Benedict Aas
ee3c146785 fix(GUI): correct relative notification icon path (#1470)
We update the relative icon path to the correct relative path containing
the Etcher icon.

See: https://github.com/resin-io/etcher/issues/1443
2017-06-01 17:07:12 -04:00
Juan Cruz Viotti
296a554637 Revert "chore: make use of resin.io's Docker base images"
This reverts commit d39b4ba7d7.
2017-05-31 10:51:27 -04:00
Benedict Aas
b56a39e576 style(GUI): normal weight message on success page (#1469)
We make the fonts a regular weight instead of bold on the success page's
fallback banner.

Changelog-Entry: Minor style improvements to the fallback success page banner.
2017-05-30 09:36:33 -04:00
Benedict Aas
7898358617 fix(GUI): stop settings overflow into footer (#1468)
By removing the 'advanced' sub-header we stop the settings from
overflowing into the footer.

Fixes: https://github.com/resin-io/etcher/issues/1383
Changelog-Entry: Remove "Advanced" settings subtitle.
2017-05-30 09:34:45 -04:00
Juan Cruz Viotti
9a3900debb chore: make use of resin.io's Docker base images (#1481)
Resin.io already publishes multi-arch Docker base images running Jessie,
which is Debian version we wanted before falling back to Ubuntu 12.04.

The main reason behind this change is to be able to use other resin.io
base images (like ARM ones) without requiring a lot of per-base-image
changes.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-29 20:45:24 -04:00
Benedict Aas
dcb152aa00 fix(GUI): don't break up size number in drive selector (#1467)
We make the size number in the drive selector stay whole through
the `word-break: keep-all` CSS property, ensuring that it doesn't
partially overflow to the next line.

See: https://github.com/resin-io/etcher/issues/1437
Changelog-Entry: Don't break up size numbers in the drive selector.
2017-05-26 07:36:32 -04:00
Andrew Scheller
2e50ad802f chore(docker): Change APT mirror used by the Ubuntu12.04 32bit docker image (#1471)
Previously it was using http://ubuntu.stu.edu.tw but this host is no longer
active, which was causing all the 32bit Linux TravisCI builds to fail.
2017-05-25 19:06:18 +02:00
Juan Cruz Viotti
1e169315fd refactor(GUI): turn the update notifier modal into a native dialog (#1359)
Electron v1.6.1 introduced checkbox support to the native message
dialog, giving us everything that was needed to implement the update
notifier modal using a native dialog.

This change allows us to get rid of a lot code.

See: https://github.com/electron/electron/pull/8590
Change-Type: patch
Changelog-Entry: Turn the update notifier modal into a native dialog.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-23 19:06:35 -04:00
Benedict Aas
3df6cd07d0 feat(GUI): add metadata and icon to notifications (#1455)
We add the image filename, its destination drive, and application icon
to the notifications.

See: https://github.com/resin-io/etcher/issues/1443
Changelog-Entry: Add image name, drive name, and icon to notifications.
2017-05-22 15:06:32 -04:00
Juan Cruz Viotti
8e681b5534 fix(CLI): get rid of Browserify absolute path workaround (#1449)
We encountered a Browserify bug when releasing the CLI, where absolute
paths would be hard-coded in the final bundle. Since we were in the
middle of a release process, we added a quick and dirty
search-and-replace workaround on `concatenate-javascript.sh`.

After the release, we submitted a PR to Browserify which fixes the
issue. This commit makes use of my personal fork to be able to use such
fix while it gets merged to the main project.

See: https://github.com/substack/node-browserify/pull/1725
See: https://github.com/resin-io/etcher/pull/1409
Fixes: https://github.com/resin-io/etcher/issues/1429
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-22 11:33:09 -04:00
Juan Cruz Viotti
a12abc2a6c chore: unify CI scripts (#1434)
Currently we have almost equal CI scripts implemented in bash (for
Travis), and batch (for Appveyor). This commit takes advantage of MinGW
bash to unify all the scripts as bash scripts.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-22 09:20:28 -04:00
Juan Cruz Viotti
705e273400 fix(GUI): catch EACCES when querying S3 packages (#1463)
When the user is behind a firewall, then the HTTP request to query the
latest available version from S3 may throw an EACCES error, eventually
causing a confusin "You don't have access to this resource" error
window.

Change-Type: patch
Changelog-Entry: Fix "You don't have access to this resource" error at startup when behind a firewall.
Fixes: https://github.com/resin-io/etcher/issues/1458
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-20 14:47:50 -04:00
Juan Cruz Viotti
78f36dfd16 chore: track python dependencies with pip (#1447)
We're currently hardcoding various pip dependencies in
`appveyor-install.bat` and `travis-install.sh`.

This commit moves all the dependencies to a `requirements.txt` file in
the root of the project, and makes every install script run `pip install
-r requirements.txt`.

See: https://github.com/resin-io/etcher/pull/1401#discussion_r116547053
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-18 16:35:06 -04:00
Juan Cruz Viotti
30ed217c79 chore: create installers (but don't publish) on every pull request (#1365)
This allows us to catch changes that break our installer builds before
merging the problematic changes.

As a way to simplify the CI configuration files, this commit introduces
an `installers-all` Makefile target that builds all installers.

This commit also replaces all the `cp -rf` calls with `cp -RLf` in
Makefile to avoid some weird hard link Appveyor issues.

See: https://github.com/resin-io/etcher/pull/1078
See: https://github.com/resin-io/etcher/pull/1354
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-17 23:00:59 -04:00
Juan Cruz Viotti
a74e6b53cd chore: fix lzma-native not building for the x86 Linux CLI (#1448)
There are various problems that contributed to this issue:

- `node-pre-gyp` doesn't detect the 6.10.3 node version. We reverted to
  6.1.0, which the module recognised, and which shares the same v8 ABI

- Passing `--force` to `npm install` causes npm to swallow any errors
  and silently continue

- The x86 Docker container has problems writing to `$HOME/.node-gyp`.
  The solution is to enable `unsafe-perm` given that the container is
  running as `root`

Fixes: https://github.com/resin-io/etcher/issues/1444
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-17 17:10:00 -04:00
Andrew Scheller
57e29a5725 chore: Check for the commands used by electron-installer-debian (#1446) 2017-05-17 13:59:18 +01:00
Juan Cruz Viotti
369cfa7e88 refactor: address review comments from #1401 (#1433)
See: https://github.com/resin-io/etcher/pull/1401#pullrequestreview-37459059
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-15 13:17:51 -04:00
Juan Cruz Viotti
1048150654 chore: check that there are no unstaged shrinkwrap changes (#1379)
See: https://github.com/resin-io/etcher/pull/1372
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-15 12:58:20 -04:00
Benedict Aas
697c86362c feat(GUI): add success page resin referrer (#1430) 2017-05-15 11:24:48 -04:00
Jonas Hermsmeier
d8b48e6373 doc(CLI-INSTALLATION): Make headings h3 (#1419) 2017-05-12 15:03:54 +02:00
Andrew Scheller
b04d7ad8f2 docs(CLI): move the CLI installation instructions to a separate page (#1418) 2017-05-12 13:30:09 +01:00
Juan Cruz Viotti
05692b9947 docs(CLI): add installation instructions (#1417)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-12 11:20:46 +01:00
Juan Cruz Viotti
3203eb5eda v1.0.0
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-12 01:09:35 -04:00
Benedict Aas
2c26b4c6ac feat(GUI): dynamic finish page (#1368)
* feat(GUI): dynamic finish page

We implement an externally loaded dynamic finish page in React with
`react2angular`. If the Internet connection is unreliable or unavailable, or a
non-200 HTTP response is returned we display a fallback default finish banner.

Change-Type: minor
Changelog-Entry: Implement a dynamic finish page.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-12 01:07:24 -04:00
Juan Cruz Viotti
5c33abca21 fix: add a delay before the final unmount on success (#1416)
If the user has the "Unmount on success" setting enabled, then Etcher
will unmount the drive after ther flashing process completed, right
after closing the drive file descriptor.

Turns out macOS will attempt to re-mount a drive once its file
descriptor gets closed, which means that if we try to unmount too fast,
then the drive will get re-mounted again.

As a naive solution, we add a timeout before finally unmounting the
drive. Keep in the mind this is only a temporary solution until we fix
mountutils to do the right thing.

See: https://github.com/resin-io/etcher/pull/1414
Fixes: https://github.com/resin-io/etcher/issues/1385
Change-Type: patch
Changelog-Entry: Prevent drive from getting re-mounted in macOS even when the unmount on success setting is enabled.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-12 00:40:08 -04:00
Juan Cruz Viotti
b7f871607e fix(GUI): ignore ECONNRESET and ECONNREFUSED when querying S3 (#1415)
Querying S3 to determine the latest available versions might throw
`ECONNRESET` and `ECONNREFUSED`. This commit extends the
`s3Packages.getRemoteVersions()` function to handle these errors and
return no available version if so, like we already do with other similar
HTTP errors.

Change-Type: patch
Changelog-Entry: Fix `ECONNRESET` and `ECONNREFUSED` errors when checking for updates on unstable connections.
Fixes: https://github.com/resin-io/etcher/issues/1396
Fixes: https://github.com/resin-io/etcher/issues/1388
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-11 21:20:03 -04:00
Juan Cruz Viotti
babe12cd7b fix(GUI): handle spaces in installation path when elevating on Windows (#1411)
Etcher will get stuck at "Starting..." when executing the application on
a directory that contains spaces, like "C:\Program Files (x86)".

The problem is that the command is not quoted correctly when passed to
`cmd.exe /c`. This commit addresses the following specific problems:

- Quote the whole argument to `cmd.exe /c`
- Quote each individual argument after `call`

Change-Type: patch
Changelog-Entry: Fix application stuck at "Starting..." on Windows.
See: https://github.com/resin-io/etcher/pull/1376
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-11 18:05:40 -04:00
Jonas Hermsmeier
bb4d352da0 doc(github): Add question about flashed image to issue template (#1413) 2017-05-11 16:10:32 -04:00
Juan Cruz Viotti
9c055fb165 fix(CLI): workaround absolute paths in Browserify bundles (#1409)
For some strange reason, Browserify will hardcode absolute paths from
the machine that generated the bundle to be able to resolve `__dirname`
and `__filename` calls. This makes no sense, given that it means that
the Browserify bundle will not work when we move it to another machine,
which went undetected probably for months.

The Browserify community apparently makes modules to fix this particular
issue (like `bundle-collapser`, and `intreq`), however none of this seem
to solve the problem for the Etcher CLI bundle.

I also gave https://github.com/zeit/pkg a go, however I gave up after
not being able to make use of native modules (nothing seems to work; the
packager result will simply not find the addons).

Finally, I ended up making the following workarounds:

- Edit the Browserify bundle file to use its own `__dirname` to
  dynamically resolve the values of `__dirname` and `__filename` of the
  files it contains

- Patch `lzma-native` to statically require its add-on rather than
  relying on dynamic requires from `node-pre-gyp`, which makes it
  impossible to resolve on the final bundle

See: https://github.com/resin-io/etcher/issues/355
See: http://stackoverflow.com/questions/21993073/browserify-with-paths-to-folders-in-my-system
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-11 15:37:45 -04:00
Juan Cruz Viotti
b02da2d0cd chore(CLI): fix cli-develop Make target headers version (#1407)
The `cli-develop` target was pointing `node-gyp` to the Electron
headers, which caused native add-ons to not work.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-11 06:51:49 -04:00
Benedict Aas
69a982bf8d refactor(GUI): remove analytics angular dependency (#1387)
We rename `AnalyticsService` to `analytics` and remove its dependency on
Angular.
2017-05-10 20:27:54 -04:00
Juan Cruz Viotti
66547c5abd chore: replace wget with curl on node-static-entry-point-download.sh (#1406)
See: https://github.com/resin-io/etcher/pull/1365
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-10 19:28:12 -04:00
Juan Cruz Viotti
159cc24e78 upgrade: resin-cli-visuals to v1.3.1 (#1404)
This version upgrades `drivelist` to v5.0.20, which inlines the scripts
as a JSON file.

See: https://github.com/resin-io-modules/resin-cli-visuals/pull/41
See: https://github.com/resin-io-modules/resin-cli-visuals/blob/master/CHANGELOG.md
See: https://github.com/resin-io/etcher/issues/355
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-10 18:02:15 -04:00
Juan Cruz Viotti
777ad14762 chore: upgrade npm-shrinkwrap.json file (#1405)
Ensure that the `npm-shrinkwrap.json` is up to date.

These changes were backported from
https://github.com/resin-io/etcher/pull/1379, since it will take a while
for that PR to get merged.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-10 17:21:48 -04:00
Juan Cruz Viotti
78705165f0 upgrade: drivelist to v5.0.20 (#1402)
This version includes the following fix:

- https://github.com/resin-io-modules/drivelist/pull/164

The above change is also a huge step forward to finalizing the Etcher
CLI packaging story.

See: https://github.com/resin-io/etcher/issues/355
See: https://github.com/resin-io-modules/drivelist/blob/master/CHANGELOG.md
Fixes: https://github.com/resin-io/etcher/issues/1395
Change-Type: patch
Changelog-Entry: Fix error on startup when Windows username contained an ampersand.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-10 15:19:35 -04:00
Juan Cruz Viotti
d521fbbd2c chore(CLI): minify Etcher CLI code (#1401)
UglifyJS v3 was recently released, which includes support for
compressing ES6 code.

This commit introduces the following changes:

- Add a boolean `-m` option to `concatenate-javascript.sh`, which when
  set, will minify the final concatenated JavaScript file

- Install `uglify-es` in the CI servers

See: https://news.ycombinator.com/item?id=14285179
See: https://github.com/mishoo/UglifyJS2/tree/harmony
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-10 15:15:41 -04:00
Benedict Aas
b6aa5ada30 refactor(GUI): central error/warning messages function (#1193)
* Centralise drive error/warning messages with a function
  `.getDriveImageCompatibilityStatuses` in `lib/shared/drive-constraints.js`
  -- tests included
* Fix an error where several labels show at once
* Clarify the source drive label to 'Drive Contains Image'
* Remove label icons and make text bold to match Zeplin's design

Closes: https://github.com/resin-io/etcher/issues/1143
Closes: https://github.com/resin-io/etcher/issues/1144
2017-05-10 13:52:20 -04:00
Daniel Aleksandersen
d76a6dff89 doc(GUI): suggest BootCamp as an alternative when flashing Windows images (#1393)
* Specify that Rufus is only an option for Windows.
* Suggest Apple Boot Camp Assistant (built-in) as an alternative for macOS users.
2017-05-10 11:50:36 -04:00
Juan Cruz Viotti
ecb8dd29b7 upgrade: etcher-image-write to v9.1.3 (#1400)
This version gets rid of the `diskpart` optional dependency:

- https://github.com/resin-io-modules/etcher-image-write/pull/101

which will simplify the way we manage our `npm-shrinkwrap.json` file.

See: https://github.com/resin-io/etcher/pull/1379
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-10 11:47:44 -04:00
Andrew Scheller
bfd2f2bf57 style(settings): Clarify meaning of the "Report Errors" button (#1392)
To make it clear that this actually controls the reporting of errors back to resin.io, and not the reporting of errors to the user.

See #1383
2017-05-10 16:13:07 +01:00
Juan Cruz Viotti
7ddc5d525c refactor: address code review comments from #1366 (#1390)
See: https://github.com/resin-io/etcher/pull/1366
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-09 19:33:45 -04:00
Benedict Aas
efa7f986a4 fix(GUI): bound flash progress percentage within 0-100 (#1258)
We limit the Store state flashing percentage to be within 0-100,
throwing errors otherwise. Comes with tests.

Changelog-Type: Bound flash progress percentage within 0-100 range.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-09 19:24:44 -04:00
Jonas Hermsmeier
df74a2763c feat(image-stream): Make invalid images user errors (#1369)
This displays a user error if the reading the image causes an error,
instead of letting it fall through and get reported.
This is to avoid reporting errors that are not due to malfunction of the software,
but due to malformatted images.

Change-Type: minor
Changelog-Entry: Display nicer error dialog when reading an invalid image
2017-05-08 18:29:28 +02:00
Juan Cruz Viotti
60754250d9 chore: add ensure-npm-valid-dependencies.sh to sanity-checks make target (#1378)
We forgot to do so on the PR that introduces this script.

This commit also moves all the CI code to separate scripts.

See: https://github.com/resin-io/etcher/pull/1371
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-07 17:35:22 -04:00
Jonas Hermsmeier
9055b4b773 doc(contributing): Add section about binary diffs (#1380)
This adds instructions on how to set up human-readable binary diffs
with git for Etcher, which is useful when altering test images etc.
2017-05-07 14:59:11 -04:00
Juan Cruz Viotti
91784d6380 chore(codespell): add rpi-sdcard to the list of ignored extensions (#1377)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-07 14:58:40 -04:00
Juan Cruz Viotti
63fdb18286 v1.0.0-rc.5 2017-05-02 18:40:32 -04:00
Juan Cruz Viotti
b75dfd3ece feat(GUI): implement Windows elevation using a native module (#1366)
Sentry error reports showcase that elevation errors on Windows are one
of the most frequent Windows errors.

In order to perform Windows elevation, we ship compiled EXEs of a third
party CLI elevation application (http://code.kliu.org/misc/elevate/)
that has several limitations:

- We have the scan the output of the script to determine if a user
  cancelled the elevation request, which causes all sorts of issues on
  computers where English is not the main language

- The application displays a `cmd.exe` window for some milliseconds,
  which is bad UX, that we have to workaround by distributing a patched
  version of the tool

- The CLI application has to be spawned, which seems to be problematic
  if users have anti-virus software, leading to hard to debug issues

- We don't have any control if something goes wrong

For these reasons, we decided to implement our own elevation mechanism
in C++ as a Node.js add-on, based on the `elevate.exe` code we where
previously using.

Misc changes:

- Introduce a `lib/shared/bindings.js` module to easily require local native
  add-ons

- Install `cpplint` and configure it to lint C++ files

Note that for practical reasons, the C++ code lives in this repository
rather than in a separate module. We will release this functionality in
a more accessible way in the future as part of the Etcher SDK project.

Change-Type: patch
Changelog-Entry: Fix uncaught errors when cancelling elevation requests on Windows when the system's language is not English.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-02 18:36:57 -04:00
Juan Cruz Viotti
9881364e1d chore: make isstream a top level production development (#1373)
Our `npm-shrinkwrap.json` file contains two entries for the `isstream`
dependency. One of them is in the top level of the file, and marks
`isstream` as a development dependency.

The `request` module makes use of `isstream`, so there is another
instance of `isstream` nested inside `request` which is marked as a
production dependency.

Most NPM versions will realise that there are two instances of
`isstream`, and since one of them is a production development, it will
include it in the final package.

However, there are some NPM version, like 4.6.1, which will only
consider the top level entry, and completely omit `isstream` on the
final package, causing a "Cannot find module 'isstream'" error.

The solution was to manually update the shrinkwrap file to remove the
nested instance, and make the top level instance a production
development.

I don't think there is a way we can protect ourselves from these edge
cases. NPM should have recognised that the dependencies were compatible,
and not create a nested instance on the first place.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-01 19:39:21 -04:00
Juan Cruz Viotti
4f5179f5c9 chore: ensure there are no extraneous or invalid npm dependencies (#1371)
The `npm ls` command will exit with an error code if there are invalid
or extraneous dependencies.

This commits adds that command to `make sanity-checks`, so we can catch
those cases early one.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-01 19:39:03 -04:00
Juan Cruz Viotti
79d5f0e90c chore: remove etcher-latest-version from package.json (#1372)
This version is no longer used, and was removed from the shrinkwrap
file, but for some reason, we forgot to remove it from package.json.

See: https://github.com/resin-io/etcher/pull/1183
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-05-01 19:38:52 -04:00
Juan Cruz Viotti
09d2a9d897 chore: build on Ubuntu 12.04 Docker base images (#1364)
We recently discovered that users not running latest GNU/Linux
distributions were having problems when Etcher tried to load native
modules. We used to build packages on Ubuntu 16.04, which ships with
GLIBC 2.23.

In order to solve that issue, we moved our build Docker containers to
Debian Jessie, which ships with GLIBC 2.19, however we noticed that
users running even older Linux distributions were still having the same
issue, so this commit switched the Docker containers to Ubuntu 12.04,
which ships with GLIBC 2.15.

See: https://github.com/resin-io/etcher/pull/1319
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-28 12:43:38 -04:00
Jonas Hermsmeier
0c79c492e2 chore(gitattributes): Add "hex" diff tag to binary files (#1367)
This adds a `diff` tag to binary files in `.gitattributes`,
enabling git to use an external tool to generate diffable output for binary files
by adding a handler to the local or global git config, i.e:

```
[diff "hex"]
  textconv = hexdump
  binary = true
```

Change-Type: patch
2017-04-28 11:46:41 -04:00
Jonas Hermsmeier
becca2d05e fix(image-stream): Remove inability to fallback to octet-stream (#1363)
Using `mime-types` in that place made it impossible to use other
other file extensions like `.sdcard` and have them treated as `application/octet-stream`
when drag and dropping images into Etcher.

This moves the fallback logic in `lib/image-stream` to `.getFromFilePath()`,
to still facilitate proper MIME type detection, while allowing it to fall back
to the octet-stream handler, if there's no available handler for a specific type.

Change-Type: patch
Changelog-Entry: Fix not treating unknown images as octet-stream
2017-04-27 18:00:53 +02:00
Juan Cruz Viotti
1cf4cdcee9 refactor(errors): add isUserError utility function (#1320)
This utility function is useful to avoid duplicating the logic of
checking whether an error is a user error across the code base.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-26 23:54:16 -04:00
Juan Cruz Viotti
c9e410fcb1 refactor: address file-extensions review comments (#1347)
See: https://github.com/resin-io/etcher/pull/1343#pullrequestreview-34288142
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-26 23:53:03 -04:00
Juan Cruz Viotti
59edd881e2 refactor: move OSNotificationService out of the angular world (#1352)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-26 23:52:46 -04:00
Juan Cruz Viotti
d3b35742a6 refactor(GUI): integrate etcher-latest-version into the main repo (#1183)
`etcher-latest-version` was kept in a separate repository in order to
re-use it with the Etcher website, however the Etcher website is not
using it at all, and we're moving towards having the website in the main
repository.

Therefore, this commit brings back the logic from
`etcher-latest-version`, but introduces it as
`lib/shared/s3-packages.js`, in order to not tie ourselves to the
AngularJS framework, and as a step towards the Etcher SDK.

As a nice little bonus, this commit adds support for an
`ETCHER_FAKE_S3_LATEST_VERSION` environment variable that can be used to
trick Etcher that there is an available update, and therefore show the
update notifier modal.

Also, this commit adds support for snapshot builds update-checks, by
checking the `resin-nightly-downloads` S3 bucket if the current version
contains a git commit hash build number.

If the version is not a production release, then the update notifier
modal doesn't present the checkbox to disable update notifications for X
days.

We also add a property called `updates.semverRange` to `package.json`,
which can be used to fine control which versions are considered as
candidates for an update notification.

This commit adds a setting called `includeUnstableChannel`, which can be
used to tweak whether unstable (beta) releases are considered or not
when checking for the latest available version.

See: https://github.com/resin-io-modules/etcher-latest-version
Fixes: https://github.com/resin-io/etcher/issues/953
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-26 23:52:04 -04:00
Juan Cruz Viotti
9acebda035 chore: make use of browserify as a development dependency (#1354)
This is causing all the snapshot builds to fail when a PR is merged to
master.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-26 11:06:23 -04:00
Juan Cruz Viotti
23a5e53d50 refactor: address review comments from #1351 (#1355)
See: https://github.com/resin-io/etcher/pull/1351
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-26 11:05:36 -04:00
Andrew Scheller
30c531417a refactor(utils): make PERCENTAGE_ constants public, and re-use them in flash.js (#1353) 2017-04-26 11:05:14 -04:00
Juan Cruz Viotti
bc01e151c4 upgrade: electron to v1.6.6 (#1357)
Some changes that we're particularly interested in:

- https://github.com/electron/electron/pull/8590
- https://github.com/electron/electron/pull/8852
- https://github.com/electron/electron/pull/7631

Note that the `electron-prebuilt` packaged has been renamed to
`electron`.

Change-Type: patch
Changelog-Entry: Upgrade Electron to v1.6.6.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-25 15:52:19 -04:00
Juan Cruz Viotti
62ca0e5b09 refactor: extract elevation routines to lib/shared/permissions.js (#1351)
The elevation mechanism currently embedded in
`lib/child-writer/writer-proxy.js` is extracted as a separate re-usable
function in `lib/shared/permissions.js`.

This change hugely simplifies the writer proxy, while allowing us to
iterate faster on the elevation core functionality.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-25 11:28:50 -04:00
Juan Cruz Viotti
0696833ad6 docs: clarify how to deal with problematic releases (#1297)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-24 09:51:11 -04:00
Juan Cruz Viotti
0668f424e1 v1.0.0-rc.4 2017-04-22 20:42:40 -04:00
Ștefan Daniel Mihăilă
1fe87d8883 feat(GUI): collect archive and image extension in analytics (#1343)
Change-Type: patch
2017-04-22 20:40:42 -04:00
Ștefan Daniel Mihăilă
9e7e5de63a feat(GUI): add uuid to flash events (#1344)
Change-Type: patch
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-22 20:40:05 -04:00
Juan Cruz Viotti
78ab59a55e upgrade: mountutils to v1.0.6 (#1345)
- https://github.com/resin-io-modules/mountutils/pull/26

Change-Type: patch
Changelog-Entry: Fix "Unmount failed" on Windows where the PC is connected to network drives.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-22 12:07:31 -04:00
Jonas Hermsmeier
4023fe5b59 chore(package): Update udif to 0.9.0 (#1346)
This updates `udif` from 0.8.0 -> 0.9.0, fixing a stall when flashing
certain dmg images due to `UDIF.ReadStream()` overrunning block regions.

See https://github.com/jhermsmeier/node-udif/issues/5

Change-Type: patch
Changelog-Entry: Fix stall / freezing when flashing certain dmg images.
Connects To: #1342
2017-04-22 12:07:22 -04:00
Juan Cruz Viotti
dafa1f3ede refactor(child-writer): add robot commands constant (#1332)
See: https://github.com/resin-io/etcher/pull/1295#discussion_r112463686
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-21 17:41:20 -04:00
Juan Cruz Viotti
cf99a5d598 upgrade: etcher-image-write to v9.1.2 (#1339)
- https://github.com/resin-io-modules/etcher-image-write/pull/99
- https://github.com/resin-io-modules/etcher-image-write/pull/98

See: https://github.com/resin-io-modules/etcher-image-write/blob/master/CHANGELOG.md
Change-Type: patch
Changelog-Entry: Show user friendly messages for `EBUSY, read` and `EBUSY, write` errors on macOS.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-21 17:41:13 -04:00
Jonas Hermsmeier
b06d39726f chore(scripts): Remove prune from shrinkwrap cleanup (#1338)
Newer npm versions (4.4+ I believe) even remove dependencies
not shrinkwrapped yet while pruning causing newly installed dependencies
to not always be shrinkwrapped / updated in the shrinkwrap.
Removing the prune allows for this to work properly again and in the future,
with the drawback that care must be taken to not have extraneous dependencies
in the module tree.

Change-Type: patch
2017-04-21 18:33:27 +02:00
Juan Cruz Viotti
0f8ad15e45 chore(CLI): create basic CLI package installers (#1240)
This commit packages the Etcher CLI as a ZIP archive for Windows, and as
a tarball for GNU/Linux and macOS. These basic "installers" are the
foundation to provide Chocolatey/Brew/AUR/etc packages.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-21 12:17:36 -04:00
Juan Cruz Viotti
8057041bc7 chore: lock optional dependencies versions (#1337)
Optional dependencies (and their dependencies) are not tracked by the
shrinkwrap file. In order to prevent incompatibilities, we lock the
versions of all optional dependencies.

See: https://github.com/resin-io/etcher/pull/1304
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-21 12:03:39 -04:00
Andrew Scheller
ebf9439327 chore: add another typo to codespell dictionary (#1335)
From #1193
2017-04-21 08:55:52 -04:00
Juan Cruz Viotti
c0a91c0aba feat(GUI): add a validateWriteOnSuccess property to the flash event (#1333)
This event property will allow us to inspect how many people are running
Etcher without the validation mechanism.

See: https://github.com/resin-io/etcher/issues/1293
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-21 08:54:44 -04:00
Juan Cruz Viotti
0aefa56e1d chore: make asar a development dependency (#1330)
To prevent any potential version incompatibility caused by simply installing
the latest version of the packages in the CI services.

See: https://github.com/resin-io/etcher/pull/1326
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 13:48:31 -04:00
Juan Cruz Viotti
14a28fedcc upgrade: elevator to v2.2.3 (#1331)
This version contains a fix where an elevation error was not yielded
correctly.

See: https://github.com/resin-io-modules/elevator/pull/12
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 13:44:12 -04:00
Juan Cruz Viotti
fe91be11e8 refactor(errors): createError and createUserError accept an object (#1322)
Currently, both of these functions accept two arguments: the error
title, and the error description. This function signature makes is hard
to keep adding options to these error creation functions, like an error
code, so this commit refactors them to take a single argument: an
options object containing `title` and `description` properties.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 12:23:32 -04:00
Juan Cruz Viotti
b93fd86092 chore: perform GNU/Linux builds on Debian Jessie docker containers (#1319)
We recently hit an issue where Etcher builds produced on Ubuntu relied
on a too new glibc version, making them incompatible with GNU/Linux
distributions such as Debian Jessie.

As a solution, we will start producing builds on Debian Jessie, which
ensures that the builds will be compatible with the majority of
GNU/Linux versions out there.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 12:23:13 -04:00
Juan Cruz Viotti
880ca257a6 chore: make electron-installer-debian an optional dependency (#1326)
We currently require this module to be available in the environment in
order to be able to build debian packages.

This commit adds it as an optional dependency, so we can have control
over the version that we use, to prevent any potential incompatibility.

We also update the `udif` package.json version to match what its on the
shrinkwrap file to avoid npm complaining about version mismatches.

See: https://github.com/resin-io/etcher/pull/1290
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 12:06:53 -04:00
Juan Cruz Viotti
96f586900c fix(GUI): catch EIO errors and display a user friendly message (#1318)
If we get EIO at this point, then it means that the writer did
everything it could to recover (like multiple retries), and the error
is truly an input/output error coming from the operating system.

In this commit, we show a nice user friendly message explaining what
happened, and advising users to try again with another drive, reader, or
port instead of showing an uncaught EIO error.

Change-Type: patch
Changelog-Entry: Show a friendly user message on EIO after many retries.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 12:01:43 -04:00
Juan Cruz Viotti
c3a41b172e chore: pass bintray environment variables to Docker containers (#1307)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 11:06:17 -04:00
Juan Cruz Viotti
586a6950b2 fix(GUI): send an "elevation cancelled" analytics event (#1310)
If the user cancels the elevation dialog, then no event is emitted,
making it hard to track down what happened after the flash button was
pressed.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 11:04:45 -04:00
Juan Cruz Viotti
2ec2ceea14 upgrade: drivelist to v5.0.19 (#1327)
- https://github.com/resin-io-modules/drivelist/pull/161
- https://github.com/resin-io-modules/drivelist/pull/156
- https://github.com/resin-io-modules/drivelist/pull/153

Change-Type: patch
Changelog-Entry: Various fixes for when drive descriptions contain special characters.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-20 10:49:40 -04:00
Ștefan Daniel Mihăilă
24fe1a6c89 upgrade: resin-corvus to 1.0.0-beta.26 (#1321)
This version solves the issue regarding some messages
getting console logged (and reaching Sentry) as "[object Object]".

Change-Type: patch
Changelog-Entry: Upgrade `resin-corvus` to 1.0.0-beta.26.
2017-04-19 11:07:50 -04:00
Juan Cruz Viotti
31aa73ce07 v1.0.0-rc.3 2017-04-15 00:18:35 -04:00
Jonas Hermsmeier
6c930e2d8d fix(image-stream): fix Apple disk image detection & reading (#1283)
This fixes two things: The format detection, and a bug in `udif`.

First, by categorizing the `.dmg` extension as compressed image,
`.isSupportedImage()` would attempt to detect the format after stripping
the extension, causing it to be misdetected.

Second, `udif`'s ReadStream didn't add the `dataForkOffset` to its
position when reading blocks, causing the wrong data to be read for some images,
in turn causing zlib to error on invalid headers.

Changes:
- Classify `.dmg` as `type: 'image'`
- Update `udif` to 0.8.0

Change-Type: patch
Changelog-Entry: Fix Apple disk image detection & streaming
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-15 00:17:41 -04:00
Juan Cruz Viotti
847b41f49a upgrade: etcher-image-write to v9.1.1 (#1306)
This version includes a fix to throw an `EUNPLUGGED` error instead of an
`UNKNOWN` one when unplugging an SD Card from an internal reader on
Windows.

Change-Type: patch
Changelog-Entry: Fix "UNKNOWN: unknown error" error when unplugging an SD Card from an internal reader on Windows.
See: https://github.com/resin-io-modules/etcher-image-write/pull/97
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-14 23:45:21 -04:00
Juan Cruz Viotti
e4a47611c0 upgrade: elevator to v2.2.2 (#1304)
This version prints debug messages to `stdout`.

See: https://github.com/resin-io-modules/elevator/pull/11
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-14 22:18:54 -04:00
Juan Cruz Viotti
0b500d2585 fix(GUI): correctly log debugging messages on Windows (#1303)
Windows will not react to dynamically set environment variables (e.g:
`process.env.MOUNTUTILS_DEBUG = '1'`), so in order to workaround this
limitation, we set `MOUNTUTILS_DEBUG` in
`lib/child-writer/writer-proxy.js` when spawning the CLI, and we also
set `DEBUG='*'` in `lib/start.js`, so it gets picked up by the child
writer module, which spawns the writer proxy by inheriting the
environment.
2017-04-14 16:41:00 -04:00
Juan Cruz Viotti
ebd2d85de7 upgrade: mountutils to v1.0.5 (#1302)
This version accepts a `MOUNTUTILS_DEBUG` environment variable to make
the module output extra logging information, which we enable in this
commit as well.

See: https://github.com/resin-io-modules/mountutils/pull/25
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-14 14:59:27 -04:00
Juan Cruz Viotti
c5a9a1fca4 fix(GUI): show a friendly message when the drive is unplugged half-way through (#1301)
This commit shows a user friendly message when Etcher loses access to
the drive while flashing/validating, and prevents the cryptic errors
from getting to Sentry.

See: https://github.com/resin-io-modules/etcher-image-write/pull/96
Change-Type: minor
Changelog-Entry: Show a user friendly message when the drive is unplugged half-way through.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-14 14:24:06 -04:00
Juan Cruz Viotti
e66d805672 feat(child-writer): log non-robot messages for debugging purposes (#1295)
Currently, if the child writer receives a message from the writer
process that is not a valid robot object, then it will throw an error.

Now, we check if the message is a robot message, and if so, we try to
parse it (throwing errors if its indeed a malformed/incomplete robot
message), however we log it if not.

The main motivation behind this feature is that it will allows us to
print debugging information on the mountutils module, and have it
redirected to DevTools.

Change-Type: minor
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-14 14:07:00 -04:00
Juan Cruz Viotti
468312b6cc upgrade: elevator to v2.2.1 (#1300)
This version improves the error message if the elevate.exe utility
failed.

See: https://github.com/resin-io-modules/elevator/pull/10
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-14 13:17:18 -04:00
Ștefan Daniel Mihăilă
8edc41dee0 upgrade: resin-corvus to 1.0.0-beta.25 (#1299)
This version handles better non-error objects sent to Sentry.

Change-Type: patch
Changelog-Entry: Improve error reporting accuracy.
2017-04-14 12:38:20 -04:00
Juan Cruz Viotti
5535111314 upgrade: elevator to v2.2.0 (#1298)
This version contains a patch to output debugging information.

See: https://github.com/resin-io-modules/elevator/pull/9
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-14 12:27:19 -04:00
Juan Cruz Viotti
0890b1e369 refactor(GUI): move SupportedFormatsModel to lib/shared (#1251)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-13 14:38:30 -04:00
Juan Cruz Viotti
64c8eb594b refactor(GUI): make OSWindowProgress a simple CommonJS module (#1253)
There is no need to tie this module to Angular by using an Angular
service.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-13 14:38:22 -04:00
Juan Cruz Viotti
55021376b5 tests(image-stream): ensure imageStream.getFromFilePath() returns a path (#1280)
This would have prevented https://github.com/resin-io/etcher/pull/1278
from happening.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-13 14:38:13 -04:00
Juan Cruz Viotti
3f7ec8a148 tests(image-stream): remove unnecessary big timeout (#1285)
See: https://github.com/resin-io/etcher/pull/1279#discussion_r110880004
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-13 14:38:05 -04:00
Juan Cruz Viotti
5f9b46b98b upgrade: etcher-image-write to v9.0.2 (#1286)
This release fixes an uncaught error when there is a validation error.

See: https://github.com/resin-io-modules/etcher-image-write/pull/94
Change-Type: patch
Changelog-Entry: Fix "function createError(opts) {}" error on validation failure.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-13 14:37:56 -04:00
Juan Cruz Viotti
a1d8f28fc2 upgrade: mountutils to v1.0.4 (#1294)
This version contains a fix for when unmounting a physical drive with no
logical volumes attached.

See: http://github.com/resin-io-modules/mountutils/pull/24
Change-Type: patch
Changelog-Entry: Fix "Unmount failed, invalid drive" error on Windows.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-13 14:37:43 -04:00
Ștefan Daniel Mihăilă
5ace384607 upgrade: resin-corvus to 1.0.0.beta-24 (#1296)
This version fixes the release not being sent to Mixpanel.

Change-Type: patch
2017-04-13 14:30:04 -04:00
David Lechner
588c94a64f chore: fix debian package run script (#1290)
The rc2 debian package is not working because the path where the package files
is installed has changed. The change in paths comes from an upstream change
in the electron-installer-debian node package. So, updating the path here to
match the actuall install location.
2017-04-13 13:38:54 -04:00
Jonas Hermsmeier
7fc10b71e3 chore(package): fix codespell binary file warnings (#1289)
This avoids codespell printing warnings for binary files
which have been added recently (`.iso`, `.dmg`), as well as dotfiles (i.e. `.DS_Store`).

Change-Type: patch
2017-04-13 08:45:02 -04:00
Andrew Scheller
57045ef1f6 chore: small tweak to the jq-insert.sh syntax (#1287) 2017-04-12 18:33:03 -04:00
Juan Cruz Viotti
36822b1f91 v1.0.0-rc.2 2017-04-11 01:00:08 -04:00
Juan Cruz Viotti
68f87435de fix(CLI): throw error if image is inaccessible (#1281)
Consider the following scenario:

- The user selects an image from an external drive
- The user selects a drive
- The user unmounts/ejects the external drive
- The user clicks flash

The application state will contain an image path that is no longer
accessible, causing an ENOENT error when spawning the CLI process.

Change-Type: patch
Changelog-Entry: Display a user error if the image is no longer accessible when the writer starts.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-11 00:59:08 -04:00
Juan Cruz Viotti
6deec4bbb5 Revert "chore(ci): limit git clone depth (#1269)"
This reverts commit 02da446914.
2017-04-11 00:56:52 -04:00
Juan Cruz Viotti
cf271100f5 fix(image-stream): throw user error if image is a directory (#1279)
If the user tries to drag and drop a directory to the application, then
he'll get a scary `EISDIR` error message. This commit catches this
error, and display a nice user friendly message instead.

Change-Type: patch
Changelog-Entry: Prevent uncaught `EISDIR` when dropping a directory to the application.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-11 00:34:21 -04:00
Juan Cruz Viotti
2af129d0b7 chore: add analytics token environment variables to Docker container (#1274)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-10 23:49:53 -04:00
Juan Cruz Viotti
85e1bdb650 chore: fix jq crashing on Windows when using relative paths (#1276)
`jq` crashes when setting a value on a relative file. We workaround the
issue by using `jq` in a pipe instead of passing the file to it as an
argument.

See: https://github.com/stedolan/jq/issues/1155
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-10 23:49:46 -04:00
Juan Cruz Viotti
c418bc6512 chore: remove duplicated curl dependency in Dockerfiles (#1275)
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-10 23:49:37 -04:00
Juan Cruz Viotti
44094680fb fix(image-stream): return a path from the handler (#1278)
The `application/x-apple-diskimage` handler doesn't return a path,
causing an issue when fetching the image metadata, and trying using the
path to determine if its a supported image type.

Change-Type: patch
Changelog-Entry: Fix "Path must be a string. Received undefined" when selecting Apple images.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-10 23:49:22 -04:00
Juan Cruz Viotti
fc46958ac0 fix(image-stream): interpret iso9660 as application/octet-stream (#1277)
This is a regression caused by
https://github.com/resin-io/etcher/pull/1257, which introduced a new way
to detect mime types by using the `mime-types` module.

This module, contrary to `file-type`, will detect certain ISO files as
`application/x-iso9660-image`, which Etcher doesn't know how to handle,
and will therefore should at the user that the format is unsupported.

Change-Type: patch
Changelog-Entry: Don't interpret certain ISO images as unsupported.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2017-04-10 23:49:11 -04:00
394 changed files with 34746 additions and 27818 deletions

View File

@@ -1 +1,2 @@
*
!requirements.txt

View File

@@ -9,5 +9,14 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
[*.ts]
indent_style = tab
[*.tsx]
indent_style = tab

View File

@@ -6,68 +6,33 @@ env:
mocha: true
plugins:
- lodash
extends: 'eslint:recommended'
- jsdoc
- node
- react
extends: 'standard'
parserOptions:
sourceType: 'script'
ecmaFeatures:
jsx: true
settings:
jsdoc:
additionalTagNames:
customTags:
- fulfil
rules:
# Possible Errors
no-cond-assign:
- error
no-console:
- off
no-constant-condition:
- error
no-control-regex:
- error
no-debugger:
- error
no-dupe-args:
- error
no-dupe-keys:
- error
no-duplicate-case:
- error
no-empty:
- error
no-empty-character-class:
- error
no-ex-assign:
- error
no-extra-boolean-cast:
- error
no-extra-parens:
- error
no-extra-semi:
- error
no-func-assign:
- error
no-inner-declarations:
- error
- both
no-invalid-regexp:
- error
no-irregular-whitespace:
- error
no-negated-in-lhs:
- error
no-obj-calls:
- error
no-prototype-builtins:
- error
no-regex-spaces:
- error
no-sparse-arrays:
- error
no-template-curly-in-string:
- error
no-unexpected-multiline:
- error
no-unreachable:
- error
no-unsafe-finally:
- error
use-isnan:
- error
valid-jsdoc:
- error
- requireReturn: false
@@ -83,13 +48,9 @@ rules:
prefer:
arg: "param"
return: "returns"
valid-typeof:
- error
# Best Practices
accessor-pairs:
- error
array-callback-return:
- error
block-scoped-var:
@@ -104,19 +65,12 @@ rules:
- error
default-case:
- error
dot-location:
- error
- property
dot-notation:
- error
eqeqeq:
- error
guard-for-in:
- error
no-alert:
- error
no-caller:
- error
no-case-declarations:
- error
no-div-regex:
@@ -125,106 +79,43 @@ rules:
- error
no-empty-function:
- error
no-empty-pattern:
- error
no-eq-null:
- error
no-eval:
- error
no-extend-native:
- error
no-extra-bind:
- error
no-extra-label:
- error
no-fallthrough:
- error
no-floating-decimal:
- error
no-global-assign:
- error
no-implicit-coercion:
- error
no-implicit-globals:
- error
no-implied-eval:
- error
no-iterator:
- error
no-labels:
- error
no-lone-blocks:
- error
no-loop-func:
- error
no-magic-numbers:
- error
no-multi-spaces:
- error
no-multi-str:
- error
no-native-reassign:
- error
no-new:
- error
no-new-func:
- error
no-new-wrappers:
- error
no-octal:
- error
no-octal-escape:
- error
no-param-reassign:
- error
no-proto:
- error
no-redeclare:
- error
no-restricted-properties:
- error
- property: __proto__
no-return-assign:
- error
no-return-await:
- error
no-script-url:
- error
no-self-assign:
- error
no-self-compare:
- error
no-sequences:
- error
no-throw-literal:
- error
no-unmodified-loop-condition:
- error
no-unused-expressions:
- error
no-unused-labels:
- error
no-useless-call:
- error
no-useless-concat:
- error
no-useless-escape:
- error
no-void:
- error
no-warning-comments:
- off
no-with:
- error
radix:
- error
vars-on-top:
- off
wrap-iife:
- error
- outside
yoda:
- error
# Strict mode
@@ -239,21 +130,11 @@ rules:
- always
no-catch-shadow:
- error
no-delete-var:
- error
no-label-var:
- error
no-restricted-globals:
- error
- event
no-shadow:
- error
no-shadow-restricted-names:
- error
no-undef:
- error
no-undef-init:
- error
no-undefined:
- error
no-unused-vars:
@@ -267,14 +148,8 @@ rules:
- error
global-require:
- off
handle-callback-err:
- error
no-mixed-requires:
- error
no-new-require:
- error
no-path-concat:
- error
no-process-env:
- off
no-process-exit:
@@ -287,38 +162,20 @@ rules:
array-bracket-spacing:
- error
- always
block-spacing:
- error
brace-style:
- error
- 1tbs
camelcase:
- error
capitalized-comments:
- error
- always
- ignoreConsecutiveComments: true
comma-dangle:
- error
- never
comma-spacing:
- error
- before: false
after: true
comma-style:
- error
- last
computed-property-spacing:
- error
- never
consistent-this:
- error
- self
eol-last:
- error
func-call-spacing:
- error
- never
func-name-matching:
- error
- always
@@ -335,19 +192,9 @@ rules:
- min: 2
exceptions:
- "_"
indent:
id-match:
- error
- 2
- SwitchCase: 1
key-spacing:
- error
- beforeColon: false
afterColon: true
mode: strict
keyword-spacing:
- error
- before: true
after: true
- "^[_0-9A-Za-z\\$]+$"
line-comment-position:
- error
- position: above
@@ -382,16 +229,9 @@ rules:
- error
- max: 1
multiline-ternary:
- error
- never
new-cap:
- error
new-parens:
- error
- off
newline-per-chained-call:
- off
no-array-constructor:
- error
no-bitwise:
- error
no-continue:
@@ -402,21 +242,12 @@ rules:
- error
no-mixed-operators:
- error
no-mixed-spaces-and-tabs:
- error
no-multi-assign:
- error
no-multiple-empty-lines:
- error
- max: 1
maxEOF: 1
maxBOF: 0
no-negated-condition:
- error
no-nested-ternary:
- error
no-new-object:
- error
no-plusplus:
- error
no-restricted-syntax:
@@ -425,46 +256,28 @@ rules:
- ForInStatement
no-spaced-func:
- error
no-tabs:
- error
no-trailing-spaces:
- error
no-underscore-dangle:
- error
- allowAfterThis: false
no-unneeded-ternary:
- error
no-whitespace-before-property:
- error
object-curly-newline:
- error
- minProperties: 1
- minProperties: 3
consistent: true
object-curly-spacing:
- error
- always
object-property-newline:
- error
one-var-declaration-per-line:
- error
- always
one-var:
- error
- never
operator-assignment:
- error
- always
operator-linebreak:
- error
- before
padded-blocks:
- error
- classes: always
quote-props:
- error
- as-needed
quotes:
- error
- single
quote-props:
- error
- as-needed
require-jsdoc:
- error
- require:
@@ -472,30 +285,11 @@ rules:
ClassDeclaration: true
MethodDefinition: true
ArrowFunctionExpression: true
semi:
- error
- always
semi-spacing:
- error
- before: false
after: true
space-before-blocks:
- error
space-before-function-paren:
- error
- never
space-in-parens:
- error
- never
space-infix-ops:
- error
space-unary-ops:
- error
- words: true
nonwords: false
spaced-comment:
- error
- always
- anonymous: always
named: always
asyncArrow: always
template-tag-spacing:
- error
- always
@@ -504,9 +298,6 @@ rules:
# ECMAScript 6
arrow-body-style:
- error
- always
arrow-parens:
- error
- always
@@ -514,32 +305,12 @@ rules:
- error
- before: true
after: true
constructor-super:
- error
generator-star-spacing:
- error
- before: true
after: false
no-class-assign:
- error
no-confusing-arrow:
- error
no-const-assign:
- error
no-dupe-class-members:
- error
no-duplicate-imports:
- error
no-new-symbol:
- error
no-this-before-super:
- error
no-useless-computed-key:
- error
no-useless-constructor:
- error
no-useless-rename:
- error
no-var:
- error
object-shorthand:
@@ -547,8 +318,6 @@ rules:
- always
prefer-const:
- error
prefer-reflect:
- error
prefer-spread:
- error
prefer-numeric-literals:
@@ -562,17 +331,8 @@ rules:
- allowNamedFunctions: false
require-yield:
- error
rest-spread-spacing:
- error
template-curly-spacing:
- error
- never
symbol-description:
- error
yield-star-spacing:
- error
- before: true
after: false
# Lodash
@@ -645,3 +405,50 @@ rules:
- error
lodash/prefer-times:
- error
# JSDoc
jsdoc/check-param-names:
- error
jsdoc/check-tag-names:
- error
jsdoc/newline-after-description:
- error
jsdoc/require-example:
- error
jsdoc/require-hyphen-before-param-description:
- error
jsdoc/require-param:
- error
jsdoc/require-param-description:
- error
jsdoc/require-param-type:
- error
jsdoc/require-returns-type:
- error
# Node
node/no-deprecated-api:
- error
node/no-missing-import:
- error
node/no-missing-require:
- error
node/process-exit-as-throw:
- error
node/no-extraneous-require:
- error
node/no-extraneous-import:
- error
# React
react/jsx-uses-vars:
- error
overrides:
files: ['*.jsx']
rules:
require-jsdoc:
- off

49
.gitattributes vendored
View File

@@ -1,18 +1,23 @@
# Javascript files must retain LF line-endings (to keep eslint happy)
*.js text eol=lf
*.jsx text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
# CSS and SCSS files must retain LF line-endings (to keep ensure-staged-sass.sh happy)
*.css text eol=lf
*.scss text eol=lf
# Text files
dictionary text
Dockerfile* text
.dockerignore text
.editorconfig text
etcher text
.git* text
*.html text
*.json text
*.json text eol=lf
*.cpp text
*.h text
*.gyp text
LICENSE text
Makefile text
*.md text
@@ -20,14 +25,36 @@ Makefile text
*.bat text
*.svg text
*.yml text
*.patch text
*.txt text
CODEOWNERS text
*.plist text
# Binary files (no line-ending conversions)
*.bz2 binary
*.gz binary
*.icns binary
*.ico binary
*.img binary
*.png binary
*.xz binary
*.zip binary
*.dmg binary
*.bz2 binary diff=hex
*.gz binary diff=hex
*.icns binary diff=hex
*.ico binary diff=hex
*.tiff binary diff=hex
*.img binary diff=hex
*.iso binary diff=hex
*.png binary diff=hex
*.bin binary diff=hex
*.elf binary diff=hex
*.xz binary diff=hex
*.zip binary diff=hex
*.dtb binary diff=hex
*.dtbo binary diff=hex
*.dat binary diff=hex
*.bin binary diff=hex
*.dmg binary diff=hex
*.rpi-sdcard binary diff=hex
*.wic binary diff=hex
*.foo binary diff=hex
*.eot binary diff=hex
*.otf binary diff=hex
*.woff binary diff=hex
*.woff2 binary diff=hex
*.ttf binary diff=hex
xz-without-extension binary diff=hex
wmic-output.txt binary diff=hex

View File

@@ -1,5 +1,6 @@
- **Etcher version:**
- **Operating system and architecture:**
- **Do you see any meaningful error information on DevTools?**
- **Etcher version:**
- **Operating system and architecture:**
- **Image flashed:**
- **Do you see any meaningful error information in the DevTools?**
<!-- You can open DevTools by pressing `Ctrl+Alt+I`, or `Cmd+Alt+I` if you're running OS X. -->
<!-- You can open DevTools by pressing `Ctrl+Shift+I` (`Ctrl+Alt+I` for Etcher before v1.3.x), or `Cmd+Alt+I` if you're on Mac OS. -->

24
.gitignore vendored
View File

@@ -1,5 +1,5 @@
# Logs
logs
/logs
*.log
npm-debug.log*
@@ -9,10 +9,13 @@ pids
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
/lib-cov
# Image stream output directory
/tests/image-stream/output
# Coverage directory used by tools like istanbul
coverage
/coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
@@ -21,16 +24,17 @@ coverage
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
/build
# Generated files
/generated
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules
bower_components
# Compiled Electron releases
release/
etcher-release/
# Compiled Etcher releases
/dist
# Certificates
*.spc
@@ -39,3 +43,7 @@ etcher-release/
*.cer
*.crt
*.pem
# OSX files
.DS_Store

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "scripts/resin"]
path = scripts/resin
url = https://github.com/balena-io/scripts.git
branch = master

85
.resinci.json Normal file
View File

@@ -0,0 +1,85 @@
{
"electron": {
"npm_version": "6.7.0",
"dependencies": {
"linux": [
"libudev-dev",
"libusb-1.0-0-dev",
"libyaml-dev",
"libgtk-3-0",
"libatk-bridge2.0-0",
"libdbus-1-3",
"libc6"
]
},
"builder": {
"appId": "io.balena.etcher",
"copyright": "Copyright 2016-2019 Balena Ltd",
"productName": "balenaEtcher",
"nodeGypRebuild": true,
"afterPack": "./afterPack.js",
"files": [
"build/Release/elevator.node",
"generated",
"lib/shared/catalina-sudo/sudo-askpass.osascript.js",
"lib/gui/app/index.html",
"lib/gui/css/*.css",
"lib/gui/css/fonts/*.woff2",
"lib/gui/assets/*.svg",
"assets/icon.png",
"!node_modules/**/**",
"node_modules/**/*.js",
"node_modules/**/*.json",
"node_modules/**/*.node",
"node_modules/**/*.dll",
"node_modules/node-raspberrypi-usbboot/blobs/**",
"node_modules/flexboxgrid/dist/flexboxgrid.css",
"node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff",
"node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff",
"node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff",
"node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff",
"node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff",
"node_modules/bootstrap-sass/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2"
],
"afterSign": "./afterSignHook.js",
"mac": {
"asar": false,
"category": "public.app-category.developer-tools",
"hardenedRuntime": true,
"entitlements": "entitlements.mac.plist",
"entitlementsInherit": "entitlements.mac.plist"
},
"dmg": {
"iconSize": 110,
"contents": [
{
"x": 140,
"y": 245
},
{
"x": 415,
"y": 245,
"type": "link",
"path": "/Applications"
}
],
"window": {
"width": 544,
"height": 407
}
},
"linux": {
"category": "Utility",
"packageCategory": "utils",
"synopsis": "balenaEtcher is a powerful OS image flasher built with web technologies to ensure flashing an SDCard or USB drive is a pleasant and safe experience. It protects you from accidentally writing to your hard-drives, ensures every byte of data was written correctly and much more."
},
"deb": {
"compression": "bzip2",
"priority": "optional",
"depends": [
"polkit-1-auth-agent | policykit-1-gnome | polkit-kde-1"
]
}
}
}
}

View File

@@ -1,74 +0,0 @@
language: node_js
sudo: false
node_js:
- "6.1.0"
git:
depth: 3
services:
- docker
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- libstdc++-6-dev
env:
global:
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
- CC="clang"
- CXX="clang++"
matrix:
- TARGET_ARCH=x64
- TARGET_ARCH=x86
matrix:
fast_finish: true
exclude:
- os: osx
env: TARGET_ARCH=x86
os:
- linux
- osx
before_install:
- npm config set spin=false
install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
./scripts/build/docker/run-command.sh -r "${TARGET_ARCH}" -s "${PWD}" -c "make info && make electron-develop";
else
pip install codespell==1.9.2 awscli;
npm install -g asar;
brew install afsctool jq;
make info;
travis_wait make electron-develop;
fi
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
./scripts/build/docker/run-command.sh -r "${TARGET_ARCH}" -s "${PWD}" -c "make sanity-checks && xvfb-run --server-args=$XVFB_ARGS npm test";
else
make sanity-checks && npm test;
fi
deploy:
provider: script
skip_cleanup: true
script: scripts/ci/deploy-travis.sh
on:
branch: master
notifications:
email: false
webhooks:
urls:
- https://webhooks.gitter.im/e/0a019c8b9828eb9f6a72
on_success: change
on_failure: always
on_start: never

View File

@@ -3,10 +3,855 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
# v1.5.79
## (2020-02-20)
* Remove "Download the React DevTools for a better development experience" message [Alexis Svinartchouk]
* Fix error when launching from terminal when installed via apt. [Alois Klink]
# v1.5.78
## (2020-02-19)
* Update drivelist to 8.0.10 to fix parsing lsblk --pairs [Alexis Svinartchouk]
# v1.5.77
## (2020-02-17)
* Fix error message not being shown on write error [Alexis Svinartchouk]
* The RGBLed module has been moved to a separate repository [Alexis Svinartchouk]
# v1.5.76
## (2020-02-05)
* Prefix temp permissions script name [Lorenzo Alberto Maria Ambrosi]
* Fix image drop zone, remove react-dropzone dependency [Alexis Svinartchouk]
* Update etcher-sdk to ^2.0.17 [Alexis Svinartchouk]
# v1.5.75
## (2020-02-05)
* Initialize leds object map [Omar López]
# v1.5.74
## (2020-02-04)
* Etcher pro leds feature [Alexis Svinartchouk]
* Compress deb package with bzip instead of xz [Alexis Svinartchouk]
* Update electron to 7.1.11 [Alexis Svinartchouk]
* Sort devices by device path on Linux [Alexis Svinartchouk]
# v1.5.73
## (2020-01-28)
* Update electron to v7.1.10 [Alexis Svinartchouk]
# v1.5.72
## (2020-01-27)
* Remove no longer used angular svg-icon component [Alexis Svinartchouk]
* Remove no longer used closestUnit angular filter [Alexis Svinartchouk]
# v1.5.71
## (2020-01-14)
* Update resin-corvus to 2.0.5 [Lorenzo Alberto Maria Ambrosi]
# v1.5.70
## (2019-12-13)
* Make header draggable again [Lorenzo Alberto Maria Ambrosi]
* Refactor drive selector and confirm modal to React [Lorenzo Alberto Maria Ambrosi]
* Rework lib/gui/app/styled-components to typescript [Alexis Svinartchouk]
* Convert FlashAnother & FlashResults to typescript [Lorenzo Alberto Maria Ambrosi]
* Use React instead of Angular for image selection [Lucian]
* Convert the drive selection step to React [Thodoris Greasidis]
* chore: move flash step to React [Stevche Radevski]
* Use React instead of Angular for image selection [Lucian]
# v1.5.69
## (2019-12-10)
* Don't add --no-sandbox when ELECTRON_RUN_AS_NODE true [Alexis Svinartchouk]
# v1.5.68
## (2019-12-08)
* Add version in settings modal [Lorenzo Alberto Maria Ambrosi]
# v1.5.67
## (2019-12-06)
* Fix elevation on macos in development [Alexis Svinartchouk]
# v1.5.66
## (2019-12-03)
* Update spectron to ^8 [Alexis Svinartchouk]
* Update dependencies, get node-usb from npm [Alexis Svinartchouk]
* Update nan to ^2.14 [Alexis Svinartchouk]
* Use the same entrypoint for etcher and the child writer [Alexis Svinartchouk]
* Require angular-mocks only when needed [Alexis Svinartchouk]
* Remove no longer needed pkg dev dependency [Alexis Svinartchouk]
* Update mocha, remove nock [Alexis Svinartchouk]
* Remove no longer needed xml2js [Alexis Svinartchouk]
* Remove node-pre-gyp patch that is no longer needed with electron 6 [Alexis Svinartchouk]
* Update electron-mocha to ^8.1.2, remove acorn [Alexis Svinartchouk]
* Update electron to 6.0.10 [Alexis Svinartchouk]
# v1.5.65
## (2019-12-02)
* Convert settings modal to typescript [Lorenzo Alberto Maria Ambrosi]
* Refactor settings page into modal [Lorenzo Alberto Maria Ambrosi]
# v1.5.64
## (2019-11-22)
* Use bash instead of sh for running the elevated process on Linux and Mac [Alexis Svinartchouk]
# v1.5.63
## (2019-11-08)
* Introduce an FAQ file [Dimitrios Lytras]
# v1.5.62
## (2019-11-06)
* Update drivelist to 8.0.9 [Alexis Svinartchouk]
# v1.5.61
## (2019-11-05)
* Notarize app on macOS [Lorenzo Alberto Maria Ambrosi]
# v1.5.60
## (2019-10-18)
* Upgrade ext2fs to 1.0.30 [Matthew McGinn]
# v1.5.59
## (2019-10-14)
* Catch console log messages from SafeWebView [Roman Mazur]
# v1.5.58
## (2019-10-10)
* Remove leftover GH-pages configuration file [Dimitrios Lytras]
# v1.5.57
## (2019-09-16)
* Fix entrypoint when options are passed to electron [Alexis Svinartchouk]
# v1.5.56
## (2019-08-20)
* Fix windows portable download [Lorenzo Alberto Maria Ambrosi]
# v1.5.55
## (2019-08-19)
* Update etcher-sdk to ^2.0.13 [Alexis Svinartchouk]
# v1.5.54
## (2019-08-07)
* Fix auto-updater check for updates [Lorenzo Alberto Maria Ambrosi]
# v1.5.53
## (2019-08-06)
* Allow typescript files [Lorenzo Alberto Maria Ambrosi]
# v1.5.52
## (2019-07-22)
* Don't use wmic's ProviderName if it's empty [Alexis Svinartchouk]
# v1.5.51
## (2019-06-28)
* Update sudo-prompt to ^9.0.0 [Alexis Svinartchouk]
# v1.5.50
## (2019-06-13)
* Option for trimming ext partitions on raw images [Alexis Svinartchouk]
# v1.5.49
## (2019-06-13)
* Make window size configurable [Alexis Svinartchouk]
# v1.5.48
## (2019-06-13)
* Don't use sudo-prompt when already elevated [Alexis Svinartchouk]
# v1.5.47
## (2019-06-10)
* Rework drive-selector with react + rendition [Lorenzo Alberto Maria Ambrosi]
* Use rendition theme property for step buttons [Lorenzo Alberto Maria Ambrosi]
* Upgrade styled-system to v4.1.0 [Lorenzo Alberto Maria Ambrosi]
* Upgrade rendition to v8.7.2 [Lorenzo Alberto Maria Ambrosi]
# v1.5.46
## (2019-06-09)
* Update ext2fs to 1.0.29 [Alexis Svinartchouk]
# v1.5.45
## (2019-06-04)
* Empty commit to trigger build [Alexis Svinartchouk]
# v1.5.44
## (2019-06-03)
* Fix elevation on windows when the path contains "&" or "'" [Alexis Svinartchouk]
# v1.5.43
## (2019-05-28)
* Revert "Include sass in webpack configs" [Lorenzo Alberto Maria Ambrosi]
# v1.5.42
## (2019-05-28)
* Include sass in webpack configs [Lorenzo Alberto Maria Ambrosi]
# v1.5.41
## (2019-05-27)
* waffle.io removal and adding a link to the license [Mateusz Hajder]
# v1.5.40
## (2019-05-24)
* windows installer and portable version support both ia32 and x64 [Alexis Svinartchouk]
# v1.5.39
## (2019-05-14)
* Add clean-shrinkwrap script to postshrinkwrap step [Lorenzo Alberto Maria Ambrosi]
# v1.5.38
## (2019-05-13)
* Add mention to usbboot compatibility [Carlo Maria Curinga]
# v1.5.37
## (2019-05-13)
* Bump react dependency to v16.8.5 [Lorenzo Alberto Maria Ambrosi]
# v1.5.36
## (2019-05-13)
* Update etcher-sdk to ^2.0.9 [Alexis Svinartchouk]
# v1.5.35
## (2019-05-10)
* Downgrade electron 4.1.5 -> 3.1.9 [Alexis Svinartchouk]
# v1.5.34
## (2019-05-09)
* Use https url for fetching config, avoid redirection [Alexis Svinartchouk]
* win32: fix running diskpart when the tmp file path contains spaces [Alexis Svinartchouk]
# v1.5.33
## (2019-04-30)
* Fix gzipped files verification percentage and dmg verification. [Alexis Svinartchouk]
# v1.5.32
## (2019-04-30)
* Export NPM_VERSION variable in Makefile [Lorenzo Alberto Maria Ambrosi]
# v1.5.31
## (2019-04-29)
* Update etcher-sdk to ^2.0.3 [Alexis Svinartchouk]
* Update electron to 4.1.5 [Alexis Svinartchouk]
# v1.5.30
## (2019-04-24)
* Don't show a dialog when the write fails. [Alexis Svinartchouk]
# v1.5.29
## (2019-04-19)
* Add support for auto-updating feature [Giovanni Garufi]
# v1.5.28
## (2019-04-18)
* Update electron-builder to ^20.40.2 [Alexis Svinartchouk]
* Update etcher-sdk to ^2.0.1 [Alexis Svinartchouk]
# v1.5.27
## (2019-04-16)
* (Windows): Fix reading images from network drives when the tmp dir has spaces [Alexis Svinartchouk]
# v1.5.26
## (2019-04-12)
* (Windows): Fix reading images from network drives containing non ascii characters [Alexis Svinartchouk]
# v1.5.25
## (2019-04-09)
* New parameter in webview for opt-out analytics [Lorenzo Alberto Maria Ambrosi]
# v1.5.24
## (2019-04-05)
* Update resin-corvus to ^2.0.3 [Alexis Svinartchouk]
# v1.5.23
## (2019-04-03)
* Configure versionbot to publish repo metadata to github pages [Giovanni Garufi]
# v1.5.22
## (2019-04-02)
* (Windows): Use full path to wmic as some systems don't have it in their PATH [Alexis Svinartchouk]
# v1.5.21
## (2019-04-02)
* Fix error when config.analytics was undefined [Alexis Svinartchouk]
# v1.5.20
## (2019-04-01)
* Don't try to flash when no device is selected [Alexis Svinartchouk]
* Reformat changelog [Giovanni Garufi]
* Avoid "Error: There is already a flash in progress" errors [Alexis Svinartchouk]
# v1.5.19
## (2019-03-28)
* Update resin-corvus to ^2.0.2 [Alexis Svinartchouk]
* Better reporting of unhandled rejections to sentry [Alexis Svinartchouk]
# v1.5.18
## (2019-03-26)
* Update build scripts [Giovanni Garufi]
## v1.5.17 - 2019-03-25
### Misc
- Automatically publish github release from CI
## v1.5.16 - 2019-03-25
### Misc
- Add repo.yml
## v1.5.15 - 2019-03-20
### Misc
- Show the correct logo on usbboot devices on Ubuntu
## v1.5.14 - 2019-03-20
### Misc
- Update etcher-sdk to ^1.3.10
## v1.5.13 - 2019-03-18
### Misc
- Update build scripts
## v1.5.12 - 2019-03-15
### Misc
- Update build scripts
## v1.5.11 - 2019-03-12
### Misc
- Fixed broken Hombrew cask link for etcher
- Remove no longer used travis and appveyor configs
## v1.5.10 - 2019-03-12
### Misc
- Update resin-scripts
## v1.5.9 - 2019-03-05
### Misc
- Update etcher-sdk to 1.3.0
## v1.5.8 - 2019-03-01
### Misc
- Update ext2fs to 1.0.27
## v1.5.7 - 2019-03-01
### Fixes
- Update docs
- Fix disappearing modal window
### Misc
- Fix blurred background image
## v1.5.6 - 2019-02-28
### Misc
- Target electron 3 runtime in babel options
## v1.5.5 - 2019-02-28
### Misc
- Don't pass undefined sockets to ipc.server.emit()
- Fix error when event.dataTransfer.files is empty
- Fix error message not showing when an unsupported image is selected
- Avoid `Invalid percentage` exceptions
- Update etcher-sdk to 1.1.0
## v1.5.4 - 2019-02-27
### Misc
- Add missing step for submodule cloning in README
## v1.5.3 - 2019-02-27
### Misc
- Throw error if no commit is annotated with a changelog entry
## v1.5.2 - 2019-02-26
- Enable versionist editVersion
## v1.5.1 - 2019-02-22
### Misc
- Removed lodash dependency in versionist.conf.js
## v1.5.0 - 2019-02-16
### Misc
- Reworked flashing logic with etcher-sdk
- Add support for flashing Raspberry Pi CM3+
- Upgrade to Electron v3.
- Upgrade to NPM 6.7.0
- Fix incorrect drives list on Linux
- Changed “Drive Contains Image” to “Drive Mountpoint Contains Image”
- Removed etcher-cli
## v1.4.9 - 2018-12-19
### Fixes
- Fix update notifier error popping up on v1.4.1->1.4.8
### Misc
- Added React component for the Flash Results button
- Added React component for the Flash Another button
- Restyle success screen and enlarge UI elements
- Use https for fetching sub modules
- Add `.wic` image extension as supported format
## v1.4.8 - 2018-11-23
### Features
- Added featured-project while flashing
### Fixes
- Moved back the write cancel button
- Reject drives with null size (fixes pretty-bytes error)
## v1.4.7 - 2018-11-12
### Fixes
- Fix typo in contributing guidelines
- Modify versionist.conf.js to match new internal commit guidelines
### Misc
- Rename etcher to balena-etcher
- Convert Select Image button to Rendition
## v1.4.6 - 2018-10-28
### Fixes
- Provide a Buffer to xxhash.Stream
- Fix 64 bit detection on arm
- Fix incorrect file constraint path
- Fix flash cancel button interaction
### Misc
- Add new balena.io logos
- Use Resin CI scripts to build Etcher
- Enable React lint rules
- Convert Progress Button to Rendition
## v1.4.5 - 2018-10-11
### Features
- Center content independent to window resolution.
- Add electron-native file-picker component.
- Hide unsafe mode option toggle with an env var.
- Use new design background color and drive step size ordering.
- Add a convenience Storage class on top of localStorage.
- Introduce env var to toggle autoselection of all drives.
- Add font-awesome.
- Add support for configuration files
- Use GTK-3 darkTheme mode.
- Add environment variable to toggle fullscreen.
- Allow blacklisting of drives through and environment variable ETCHER_BLACKLISTED_DRIVES.
- Show selected drives below drive selection step.
- Add a button to cancel the flash process.
- Download usbboot drivers installer when clicking a driverless usbboot device on Windows.
- Allow disabling links and hiding help link with an env var.
### Fixes
- Add "make webpack" to travis-ci build script
- Makefile: Don't use tilde in rpm versions
- Change Spectron port so not to overlap with other builds
- Fix multi-writes analytics by reusing existing logic in multi-write events.
- Load usbboot adapter on start on GNU/Linux if running as root.
### Misc
- Update drivelist to v6.4.2
- Add instructions for installing and uninstalling on Solus.
## v1.4.4 - 2018-04-24
### Fixes
- Don't display status dots with a quantity of zero on success screen
- Correct wording of flash status to use "successful" instead of "succeeded"
- Keep single drive-image pairs with warnings selected
### Misc
- Improve notification messages
## v1.4.3 - 2018-04-19
### Fixes
- Fix blob handling for usbboot
## v1.4.2 - 2018-04-18
### Features
- Make the progress button blue on verification
- Display succeeded and failed devices on finish screen
### Fixes
- Exclude RAID devices from drive selection list
- Display untitled device when device lacks description
- Prefix multiple devices label with quantity
- Fix handling of errors over IPC
- Fix usbboot blob loading
- Revert using native binding to clean disks on Windows
## v1.4.1 - 2018-04-10
### Fixes
- Exclude package.json from UI bundle
## v1.4.0 - 2018-04-05
### Features
- Move the drive selector warning dialog to the flash step
- Display image size for comparison if drive is too small
- Implement writing to multiple destinations simultaneously
- Add colorised multi-writes progress status dots
- Move CLI write preparation logic into SDK
- Make the drive-selector button orange on warnings
- Warn the user on selection of large drives
- Consolidate low-level components into Etcher SDK
- Use native code to clean drives on Windows
- Increase UV_THREADPOOL_SIZE to allocate 4 threads per CPU
- Add icon next to drive size when compatibility warnings exist
- Display number of active devices while flashing in CLI
- Replace CRC32 checksums with SHA512
- Enable usbboot on Linux if run as root
### Fixes
- Improve spacing to the drive-selector warning/error labels
- Line wrap selector size subtitles wholly
- Hide the size label given multiple devices
- Use correct usbboot blob path in AppImages
- Fix EINVAL error on Linux
- Fix enabling debug output
- Fix DevTools opening in docked mode
- Fix menu's application name
- Fix "Array buffer allocation failed" when flashing some .dmg images
- Log the banner load event to analytics
- Warn on usbboot load error in the console on Linux
- Ensure image/drive size is displayed on new line
- Don't force-inherit process environment on Windows
### Misc
- Replace Helvetica as the main font with Roboto
- Update Electron to v1.7.13
- Add spacing to the drive warning icon
- Use multi-drive methods with drive-list warning button
- Remove unused & deprecated robot protocol
- Update copyright years
- Update instructions in ISSUE_TEMPLATE
- Use Concourse CI for automated release builds
- Only publish production packages to Bintray (remove devel)
- Replace Gitter with Resin.io Forums for support
- Add support for arm64 / armv8 / aarch64 in build scripts
- Add descriptive name to modal popup windows
## v1.3.1 - 2018-01-23
### Fixes
- Fix "stdout maxBuffer" error on Linux
- Fix Etcher not working / crashing on older Windows systems
- Fix not all partitions being unmounted after flashing on Linux
- Fix selection of images in folders with file extension on Mac OS
### Misc
- Update Electron to v1.7.11
## v1.3.0 - 2018-01-04
### Features
- Display connected Compute Modules even if Windows doesn't have the necessary drivers to act on them
- Add read/write retry delays with backoff to ...
- Add native application menu (which fixes OS native window management shortcuts not working)
### Fixes
- Fix "Couldn't scan drives" error
- Ensure the writer process dies when the GUI application is killed
- Run elevated writing process asynchronously on Windows
- Fix trailing space in environment variables during Windows elevation
- Don't send analytics events when attempting to toggle a disabled drive
- Fix handling of transient write errors on Linux (EBUSY)
- Fix runaway perl process in drivelist on Mac OS
### Misc
- Update Electron from v1.7.9 to v1.7.10
- Remove Angular dependency from image-writer
## v1.2.1 - 2017-12-06
### Fixes
- Fix handling of temporary read/write errors
- Don't send initial Mixpanel events before "Anonymous Tracking" settings are loaded
- Fix verification step reading from the cache
## v1.2.0 - 2017-11-22
### Features
- Display actual write speed
- Add the progress and status to the window title.
- Add a sudo-prompt upon launch on Linux-based systems.
- Add optional progress bars to drive-selector drives.
- Increase the flashing speed of usbboot discovered devices.
- Add eye candy to usbboot initialized devices.
- Integrate Raspberry Pi's usbboot technology.
### Fixes
- Fix bzip2 streaming with the new pipelines
- Remove Linux elevation meant for usbboot.
- Fix `LIBUSB_ERROR_NO_DEVICE` error at the end of usbboot.
- Gracefully handle scenarios where a USB drive is disconnected halfway through the usbboot procedure.
- Make sure the progress button is always rounded.
- Fix permission denied issues when XDG_RUNTIME_DIR is mounted with the `noexec` option.
- Fix Etcher being unable to read certain zip files
- Fix "Couldn't scan the drives: An unknown error occurred" error when there is a drive locked with BitLocker.
- Fix "Missing state eta" error when speed is zero
- Fix "Stuck on Starting..." error
- Fix situations where the process would get stuck while flashing
### Misc
- Add the Python version (2.7) to the CONTRIBUTING doc.
- Remove duplicate debug enabling in usbboot module.
- Update Electron to v1.7.9
- Retry ejection various times before giving up on Windows.
- Try to use `$XDG_RUNTIME_DIR` to extract temporary scripts on GNU/Linux.
## v1.1.2 - 2017-08-07
### Features
- Add support for `.rpi-sdcard` images
### Fixes
- Avoid "broken" icon when selecting a zip image archive with invalid SVG
- Fix `UNABLE_TO_GET_ISSUER_CERT_LOCALLY` error at startup when behind certain proxies
- Fix `EHOSTDOWN` error at startup
- Display a user-friendly error message if the user is not in the sudoers file
- Make archive-embedded SVG icons work again
- Fix "imageBasename is not defined" error on the CLI
- Fix various drive scanning Windows errors
### Misc
- Improve Windows drive detection error codes.
## v1.1.1 - 2017-07-25
### Fixes
- Prevent "percentage above 100%" errors on DMG images
- Fix Etcher not starting flashes in AppImages
- Fix most "Unmount failed" errors on macOS
## v1.1.0 - 2017-07-20
### Features
- Add image name, drive name, and icon to OS notifications
- Add support for `.sdcard` images
- Start publishing RPM packages
- Generate single-binary portable installers on Windows
- Show friendlier error dialogs when opening an image results in an error
- Generate one-click Windows NSIS installers
- Show the application version in the WebView banners
- Show a warning message if the selected image has no partition table
- Make use of `pkg` to package the Etcher CLI
- Send anonymous analytics about package types
- Minor style improvements to the fallback success page banner
- Turn the update notifier modal into a native dialog
### Fixes
- Fix "You don't have access to this resource" error at startup when behind a firewall
- Fix `UNABLE_TO_VERIFY_LEAF_SIGNATURE` error at startup when behind a proxy
- Reset webview after navigating away from the success screen
- Fix occasional increased CPU usage because of perl regular expression in macOS
- Don't install to `C:\Program Files (x86)` on 64-bit Windows systems
- Fix "file is not accessible" error when flashing an image that lives inside a directory whose name is UTF-16 encoded on Windows.
- Fix various interrelated Windows `.bat` spawning issues
- Fix 0.0 GB Windows drive detection issues
- Cleanup drive detection temporary scripts in GNU/Linux and macOS
- Ensure no analytics events are sent if error reporting is disabled
- Retry various times on `EAGAIN` when spawning drive scanning scripts
- Don't break up size numbers in the drive selector
### Misc
- Remove "Advanced" settings subtitle
- Remove support for the `ETCHER_DISABLE_UPDATES` environment variable
- Swap speed and time below the flashing progress bar
## v1.0.0 - 2017-05-12
### Features
- Implement a dynamic finish page.
- Display nicer error dialog when reading an invalid image.
### Fixes
- Prevent drive from getting re-mounted in macOS even when the unmount on success setting is enabled.
- Fix `ECONNRESET` and `ECONNREFUSED` errors when checking for updates on unstable connections.
- Fix application stuck at "Starting..." on Windows.
- Fix error on startup when Windows username contained an ampersand.
## v1.0.0-rc.5 - 2017-05-02
### Fixes
- Fix various elevation issues on Windows
- Treat unknown images as octet stream
- Fix uncaught errors when cancelling elevation requests on Windows when the system's language is not English.
## v1.0.0-rc.4 - 2017-04-22
### Fixes
- Fix "Unmount failed" on Windows where the PC is connected to network drives.
- Various fixes for when drive descriptions contain special characters.
### Misc
- Show a friendly user message on EIO after many retries.
- Show user friendly messages for `EBUSY, read` and `EBUSY, write` errors on macOS.
## v1.0.0-rc.3 - 2017-04-14
### Fixes
- Show a user friendly message when the drive is unplugged half-way through.
- Fix "UNKNOWN: unknown error" error when unplugging an SD Card from an internal reader on Windows.
- Fix "function createError(opts) {}" error on validation failure.
- Fix "Unmount failed, invalid drive" error on Windows.
- Fix Apple disk image detection & streaming.
### Misc
- Improve error reporting accuracy.
## v1.0.0-rc.2 - 2017-04-11
### Fixes
- Display a user error if the image is no longer accessible when the writer starts.
- Prevent uncaught `EISDIR` when dropping a directory to the application.
- Fix "Path must be a string. Received undefined" when selecting Apple images.
- Don't interpret certain ISO images as unsupported.
## v1.0.0-rc.1 - 2017-04-10
### Features
- Add support for Apple Disk images.
- Add the un-truncated drive description to the selected drive step tooltip.
- Prevent flashing an image that is larger than the drive with the CLI.
@@ -287,8 +1132,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixes
- Fix broken image drag and drop functionality.
- Prevent global shortcuts from interferring with another applications.
- Prevent re-activating the "Flash" button with the keybaord shortcuts when a flash is already in process.
- Prevent global shortcuts from interfering with another applications.
- Prevent re-activating the "Flash" button with the keyboard shortcuts when a flash is already in process.
- Fix certain non-removable Windows devices not being filtered out.
- Display non-mountable Windows drives in the drive selector.

2
CODEOWNERS Normal file
View File

@@ -0,0 +1,2 @@
* @thundron @zvin @jviotti
/scripts @nazrhom

46
FAQ.md Normal file
View File

@@ -0,0 +1,46 @@
## Why is my drive not bootable?
Etcher copies images to drives byte by byte, without doing any transformation to the final device, which means images that require special treatment to be made bootable, like Windows images, will not work out of the box. In these cases, the general advice is to use software specific to those kind of images, usually available from the image publishers themselves. You can find more information [here](https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md#why-is-my-drive-not-bootable).
## How can I configure persistent storage?
Some programs, usually oriented at making GNU/Linux live USB drives, include an option to set persistent storage. This is currently not supported by Etcher, so if you require this functionality, we advise to fallback to [UNetbootin](https://unetbootin.github.io/).
## How do I flash Ubuntu ISOs
Ubuntu images (and potentially some other related GNU/Linux distributions) have a peculiar format that allows the image to boot without any further modification from both CDs and USB drives.
A consequence of this enhancement is that some programs, like parted get confused about the drive's format and partition table, printing warnings such as:
> /dev/xxx contains GPT signatures, indicating that it has a GPT table. However, it does not have a valid fake msdos partition table, as it should. Perhaps it was corrupted -- possibly by a program that doesn't understand GPT partition tables. Or perhaps you deleted the GPT table, and are now using an msdos partition table. Is this a GPT partition table? Both the primary and backup GPT tables are corrupt. Try making a fresh table, and using Parted's rescue feature to recover partitions.
> Warning: The driver descriptor says the physical block size is 2048 bytes, but Linux says it is 512 bytes.
All these warnings are safe to ignore, and your drive should be able to boot without any problems.
Refer to [the following message from Ubuntu's mailing list](https://lists.ubuntu.com/archives/ubuntu-devel/2011-June/033495.html) if you want to learn more.
## How do I run Etcher on Wayland?
The XWayland Server provides backwards compatibility to run any X client on Wayland, including Etcher.
This usually works out of the box on mainstream GNU/Linux distributions that properly support Wayland. If it doesn't, make sure the xwayland.so module is being loaded by declaring it in your [weston.ini](http://manpages.ubuntu.com/manpages/wily/man5/weston.ini.5.html):
```
[core]
modules=xwayland.so
```
## What are the runtime GNU/LINUX dependencies?
[This entry](https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md#runtime-gnulinux-dependencies) aims to provide an up to date list of runtime dependencies needed to run Etcher on a GNU/Linux system.
## How can I recover the broken drive?
Sometimes, things might go wrong, and you end up with a half-flashed drive that is unusable by your operating systems, and common graphical tools might even refuse to get it back to a normal state.
To solve these kinds of problems, we've collected [a list of fail-proof methods](https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md#recovering-broken-drives) to completely erase your drive in major operating systems.
## I receive ”No polkit authentication agent found” error in GNU/Linux
Etcher requires an available [polkit authentication agent](https://wiki.archlinux.org/index.php/Polkit#Authentication_agents) in your system in order to show a secure password prompt dialog to perform elevation. Make sure you have one installed for the desktop environment of your choice.
## May I run Etcher in older macOS versions?
Etcher GUI is based on the [Electron](http://electron.atom.io/) framework, [which only supports macOS 10.9 and newer versions](https://github.com/electron/electron/blob/master/docs/tutorial/support.md#supported-platforms).

532
Makefile
View File

@@ -2,8 +2,12 @@
# Build configuration
# ---------------------------------------------------------------------
RESIN_SCRIPTS ?= ./scripts/resin
export NPM_VERSION ?= 6.7.0
S3_BUCKET = artifacts.ci.balena-cloud.com
# This directory will be completely deleted by the `clean` rule
BUILD_DIRECTORY ?= release
BUILD_DIRECTORY ?= dist
# See http://stackoverflow.com/a/20763842/1641422
BUILD_DIRECTORY_PARENT = $(dir $(BUILD_DIRECTORY))
@@ -12,37 +16,16 @@ $(error $(BUILD_DIRECTORY_PARENT) does not exist)
endif
BUILD_TEMPORARY_DIRECTORY = $(BUILD_DIRECTORY)/.tmp
BUILD_OUTPUT_DIRECTORY = $(BUILD_DIRECTORY)/out
# ---------------------------------------------------------------------
# Application configuration
# ---------------------------------------------------------------------
$(BUILD_DIRECTORY):
mkdir $@
ELECTRON_VERSION = $(shell jq -r '.devDependencies["electron-prebuilt"]' package.json)
NODE_VERSION = 6.1.0
COMPANY_NAME = $(shell jq -r '.companyName' package.json)
APPLICATION_NAME = $(shell jq -r '.displayName' package.json)
APPLICATION_DESCRIPTION = $(shell jq -r '.description' package.json)
APPLICATION_COPYRIGHT = $(shell jq -r '.copyright' package.json)
APPLICATION_CATEGORY = public.app-category.developer-tools
APPLICATION_BUNDLE_ID = io.resin.etcher
APPLICATION_FILES = lib,assets
$(BUILD_TEMPORARY_DIRECTORY): | $(BUILD_DIRECTORY)
mkdir $@
# Add the current commit to the version if release type is "snapshot"
RELEASE_TYPE ?= snapshot
PACKAGE_JSON_VERSION = $(shell jq -r '.version' package.json)
ifeq ($(RELEASE_TYPE),production)
APPLICATION_VERSION = $(PACKAGE_JSON_VERSION)
S3_BUCKET = resin-production-downloads
endif
ifeq ($(RELEASE_TYPE),snapshot)
CURRENT_COMMIT_HASH = $(shell git log -1 --format="%h")
APPLICATION_VERSION = $(PACKAGE_JSON_VERSION)+$(CURRENT_COMMIT_HASH)
S3_BUCKET = resin-nightly-downloads
endif
ifndef APPLICATION_VERSION
$(error Invalid release type: $(RELEASE_TYPE))
endif
# See https://stackoverflow.com/a/13468229/1641422
SHELL := /bin/bash
PATH := $(shell pwd)/node_modules/.bin:$(PATH)
# ---------------------------------------------------------------------
# Operating system and architecture detection
@@ -50,7 +33,7 @@ endif
# http://stackoverflow.com/a/12099167
ifeq ($(OS),Windows_NT)
HOST_PLATFORM = win32
PLATFORM = win32
ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
HOST_ARCH = x64
@@ -64,7 +47,7 @@ ifeq ($(OS),Windows_NT)
endif
else
ifeq ($(shell uname -s),Linux)
HOST_PLATFORM = linux
PLATFORM = linux
ifeq ($(shell uname -m),x86_64)
HOST_ARCH = x64
@@ -73,11 +56,20 @@ else
HOST_ARCH = x86
endif
ifeq ($(shell uname -m),armv7l)
HOST_ARCH = armv7l
HOST_ARCH = armv7hf
endif
ifeq ($(shell uname -m),aarch64)
HOST_ARCH = aarch64
endif
ifeq ($(shell uname -m),armv8)
HOST_ARCH = aarch64
endif
ifeq ($(shell uname -m),arm64)
HOST_ARCH = aarch64
endif
endif
ifeq ($(shell uname -s),Darwin)
HOST_PLATFORM = darwin
PLATFORM = darwin
ifeq ($(shell uname -m),x86_64)
HOST_ARCH = x64
@@ -85,17 +77,11 @@ else
endif
endif
ifndef HOST_PLATFORM
$(error We couldn't detect your host platform)
ifndef PLATFORM
$(error We could not detect your host platform)
endif
ifndef HOST_ARCH
$(error We couldn't detect your host architecture)
endif
TARGET_PLATFORM = $(HOST_PLATFORM)
ifneq ($(TARGET_PLATFORM),$(HOST_PLATFORM))
$(error We don't support cross-platform builds yet)
$(error We could not detect your host architecture)
endif
# Default to host architecture. You can override by doing:
@@ -104,308 +90,31 @@ endif
#
TARGET_ARCH ?= $(HOST_ARCH)
# Support x86 builds from x64 in GNU/Linux
# See https://github.com/addaleax/lzma-native/issues/27
ifeq ($(TARGET_PLATFORM),linux)
ifneq ($(HOST_ARCH),$(TARGET_ARCH))
ifeq ($(TARGET_ARCH),x86)
export CFLAGS += -m32
else
$(error Can't build $(TARGET_ARCH) binaries on a $(HOST_ARCH) host)
endif
endif
endif
# ---------------------------------------------------------------------
# Code signing
# Electron
# ---------------------------------------------------------------------
ifeq ($(TARGET_PLATFORM),darwin)
ifndef CODE_SIGN_IDENTITY
$(warning No code-sign identity found (CODE_SIGN_IDENTITY is not set))
endif
endif
ifeq ($(TARGET_PLATFORM),win32)
ifndef CODE_SIGN_CERTIFICATE
$(warning No code-sign certificate found (CODE_SIGN_CERTIFICATE is not set))
ifndef CODE_SIGN_CERTIFICATE_PASSWORD
$(warning No code-sign certificate password found (CODE_SIGN_CERTIFICATE_PASSWORD is not set))
endif
endif
endif
# ---------------------------------------------------------------------
# Analytics
# ---------------------------------------------------------------------
ifndef ANALYTICS_SENTRY_TOKEN
$(warning No Sentry token found (ANALYTICS_SENTRY_TOKEN is not set))
endif
ifndef ANALYTICS_MIXPANEL_TOKEN
$(warning No Mixpanel token found (ANALYTICS_MIXPANEL_TOKEN is not set))
endif
# ---------------------------------------------------------------------
# Extra variables
# ---------------------------------------------------------------------
TARGET_ARCH_DEBIAN = $(shell ./scripts/build/architecture-convert.sh -r $(TARGET_ARCH) -t debian)
PRODUCT_NAME = etcher
APPLICATION_NAME_LOWERCASE = $(shell echo $(APPLICATION_NAME) | tr A-Z a-z)
APPLICATION_VERSION_DEBIAN = $(shell echo $(APPLICATION_VERSION) | tr "-" "~")
# ---------------------------------------------------------------------
# Rules
# ---------------------------------------------------------------------
# See http://stackoverflow.com/a/12528721
# Note that the blank line before 'endef' is actually important - don't delete it
define execute-command
$(1)
endef
$(BUILD_DIRECTORY):
mkdir $@
$(BUILD_TEMPORARY_DIRECTORY): | $(BUILD_DIRECTORY)
mkdir $@
$(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies: | $(BUILD_DIRECTORY)
mkdir $@
$(BUILD_DIRECTORY)/node-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies: | $(BUILD_DIRECTORY)
mkdir $@
$(BUILD_OUTPUT_DIRECTORY): | $(BUILD_DIRECTORY)
mkdir $@
$(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies/node_modules: package.json npm-shrinkwrap.json \
| $(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies
./scripts/build/dependencies-npm.sh -p \
-r "$(TARGET_ARCH)" \
-v "$(ELECTRON_VERSION)" \
-x $| \
-t electron \
-s "$(TARGET_PLATFORM)"
$(BUILD_DIRECTORY)/node-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies/node_modules: package.json npm-shrinkwrap.json \
| $(BUILD_DIRECTORY)/node-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies
./scripts/build/dependencies-npm.sh -p -f \
-r "$(TARGET_ARCH)" \
-v "$(NODE_VERSION)" \
-x $| \
-t node \
-s "$(TARGET_PLATFORM)"
$(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH)-app: \
$(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies/node_modules \
| $(BUILD_DIRECTORY) $(BUILD_TEMPORARY_DIRECTORY)
./scripts/build/electron-create-resources-app.sh -s . -o $@ \
-v $(APPLICATION_VERSION) \
-f "$(APPLICATION_FILES)"
cp -RLf $< $@
ifdef ANALYTICS_SENTRY_TOKEN
./scripts/build/jq-insert.sh \
-p ".analytics.sentry.token" \
-v "$(ANALYTICS_SENTRY_TOKEN)" \
-f $@/package.json \
-t $(BUILD_TEMPORARY_DIRECTORY)
endif
ifdef ANALYTICS_MIXPANEL_TOKEN
./scripts/build/jq-insert.sh \
-p ".analytics.mixpanel.token" \
-v "$(ANALYTICS_MIXPANEL_TOKEN)" \
-f $@/package.json \
-t $(BUILD_TEMPORARY_DIRECTORY)
endif
$(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH)-app.asar: \
$(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH)-app \
| $(BUILD_DIRECTORY)
./scripts/build/electron-create-asar.sh -d $< -o $@
$(BUILD_DIRECTORY)/electron-$(ELECTRON_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip: \
| $(BUILD_DIRECTORY)
./scripts/build/electron-download-package.sh \
-r "$(TARGET_ARCH)" \
-v "$(ELECTRON_VERSION)" \
-s "$(TARGET_PLATFORM)" \
-o $@
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-cli-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH)-app: \
package.json lib \
$(BUILD_DIRECTORY)/node-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies/node_modules \
| $(BUILD_DIRECTORY)
mkdir $@
$(foreach prerequisite,$^,$(call execute-command,cp -rf $(prerequisite) $@))
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-cli-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH).js: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-cli-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH)-app \
| $(BUILD_DIRECTORY)
./scripts/build/concatenate-javascript.sh -e $</lib/cli/etcher.js -o $@
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-cli-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH): \
$(BUILD_DIRECTORY)/node-$(TARGET_PLATFORM)-$(TARGET_ARCH)-dependencies/node_modules \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-cli-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH).js \
| $(BUILD_DIRECTORY) $(BUILD_TEMPORARY_DIRECTORY)
./scripts/build/node-package-cli.sh -o $@ -l $< \
-n $(APPLICATION_NAME) \
-e $(word 2,$^) \
electron-develop: | $(BUILD_TEMPORARY_DIRECTORY)
$(RESIN_SCRIPTS)/electron/install.sh \
-b $(shell pwd) \
-r $(TARGET_ARCH) \
-s $(TARGET_PLATFORM)
-s $(PLATFORM) \
-m $(NPM_VERSION)
ifeq ($(TARGET_PLATFORM),win32)
./scripts/build/electron-brand-exe.sh \
-f $@/etcher.exe \
-n $(APPLICATION_NAME) \
-d "$(APPLICATION_DESCRIPTION)" \
-v "$(APPLICATION_VERSION)" \
-c "$(APPLICATION_COPYRIGHT)" \
-m "$(COMPANY_NAME)" \
-i assets/icon.ico \
-w $(BUILD_TEMPORARY_DIRECTORY)
endif
electron-test:
$(RESIN_SCRIPTS)/electron/test.sh \
-b $(shell pwd) \
-s $(PLATFORM)
ifeq ($(TARGET_PLATFORM),darwin)
ifdef CODE_SIGN_IDENTITY
./scripts/build/electron-sign-file-darwin.sh -f $@/etcher -i "$(CODE_SIGN_IDENTITY)"
endif
endif
assets/dmg/background.tiff: assets/dmg/background.png assets/dmg/background@2x.png
tiffutil -cathidpicheck $^ -out $@
ifeq ($(TARGET_PLATFORM),win32)
ifdef CODE_SIGN_CERTIFICATE
ifdef CODE_SIGN_CERTIFICATE_PASSWORD
./scripts/build/electron-sign-exe-win32.sh -f $@/etcher.exe \
-d "$(APPLICATION_NAME) - $(APPLICATION_VERSION)" \
-c $(CODE_SIGN_CERTIFICATE) \
-p $(CODE_SIGN_CERTIFICATE_PASSWORD)
endif
endif
endif
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH): \
$(BUILD_DIRECTORY)/electron-$(TARGET_PLATFORM)-$(APPLICATION_VERSION)-$(TARGET_ARCH)-app.asar \
$(BUILD_DIRECTORY)/electron-$(ELECTRON_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip \
| $(BUILD_DIRECTORY) $(BUILD_TEMPORARY_DIRECTORY)
ifeq ($(TARGET_PLATFORM),darwin)
./scripts/build/electron-configure-package-darwin.sh -p $(word 2,$^) -a $< \
-n "$(APPLICATION_NAME)" \
-v "$(APPLICATION_VERSION)" \
-b "$(APPLICATION_BUNDLE_ID)" \
-c "$(APPLICATION_COPYRIGHT)" \
-t "$(APPLICATION_CATEGORY)" \
-i assets/icon.icns \
-o $@
endif
ifeq ($(TARGET_PLATFORM),linux)
./scripts/build/electron-configure-package-linux.sh -p $(word 2,$^) -a $< \
-n "$(APPLICATION_NAME)" \
-v "$(APPLICATION_VERSION)" \
-l LICENSE \
-o $@
endif
ifeq ($(TARGET_PLATFORM),win32)
./scripts/build/electron-configure-package-win32.sh -p $(word 2,$^) -a $< \
-n "$(APPLICATION_NAME)" \
-d "$(APPLICATION_DESCRIPTION)" \
-v "$(APPLICATION_VERSION)" \
-l LICENSE \
-c "$(APPLICATION_COPYRIGHT)" \
-m "$(COMPANY_NAME)" \
-i assets/icon.ico \
-w $(BUILD_TEMPORARY_DIRECTORY) \
-o $@
ifdef CODE_SIGN_CERTIFICATE
ifdef CODE_SIGN_CERTIFICATE_PASSWORD
./scripts/build/electron-sign-exe-win32.sh -f $@/$(APPLICATION_NAME).exe \
-d "$(APPLICATION_NAME) - $(APPLICATION_VERSION)" \
-c $(CODE_SIGN_CERTIFICATE) \
-p $(CODE_SIGN_CERTIFICATE_PASSWORD)
endif
endif
endif
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH)-rw.dmg: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-darwin-$(TARGET_ARCH) \
| $(BUILD_DIRECTORY)
./scripts/build/electron-create-readwrite-dmg-darwin.sh -p $< -o $@ \
-n "$(APPLICATION_NAME)" \
-i assets/icon.icns \
-b assets/osx/installer.png
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-darwin-$(TARGET_ARCH).zip: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-darwin-$(TARGET_ARCH) \
| $(BUILD_OUTPUT_DIRECTORY)
ifdef CODE_SIGN_IDENTITY
./scripts/build/electron-sign-app-darwin.sh -a $</$(APPLICATION_NAME).app -i "$(CODE_SIGN_IDENTITY)"
endif
./scripts/build/electron-installer-app-zip-darwin.sh -a $</$(APPLICATION_NAME).app -o $@
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-darwin-$(TARGET_ARCH).dmg: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH)-rw.dmg \
| $(BUILD_OUTPUT_DIRECTORY)
ifdef CODE_SIGN_IDENTITY
./scripts/build/electron-sign-dmg-darwin.sh \
-n "$(APPLICATION_NAME)" \
-d $< \
-i "$(CODE_SIGN_IDENTITY)"
endif
./scripts/build/electron-create-readonly-dmg-darwin.sh -d $< -o $@
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-linux-$(TARGET_ARCH).AppDir: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-linux-$(TARGET_ARCH) \
| $(BUILD_DIRECTORY)
./scripts/build/electron-create-appdir.sh -p $< -o $@ \
-n "$(APPLICATION_NAME)" \
-d "$(APPLICATION_DESCRIPTION)" \
-r "$(TARGET_ARCH)" \
-b "$(APPLICATION_NAME_LOWERCASE)" \
-i assets/icon.png
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-linux-$(TARGET_ARCH).AppImage: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-linux-$(TARGET_ARCH).AppDir \
| $(BUILD_DIRECTORY) $(BUILD_TEMPORARY_DIRECTORY)
./scripts/build/electron-create-appimage-linux.sh -d $< -o $@ \
-r "$(TARGET_ARCH)" \
-w "$(BUILD_TEMPORARY_DIRECTORY)"
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-linux-$(TARGET_ARCH).zip: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-linux-$(TARGET_ARCH).AppImage \
| $(BUILD_OUTPUT_DIRECTORY)
./scripts/build/electron-installer-appimage-zip.sh -i $< -o $@
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME_LOWERCASE)-electron_$(APPLICATION_VERSION_DEBIAN)_$(TARGET_ARCH_DEBIAN).deb: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-linux-$(TARGET_ARCH) \
| $(BUILD_OUTPUT_DIRECTORY)
./scripts/build/electron-installer-debian-linux.sh -p $< -r "$(TARGET_ARCH)" -o $| \
-c scripts/build/debian/config.json
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-win32-$(TARGET_ARCH).zip: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-win32-$(TARGET_ARCH) \
| $(BUILD_OUTPUT_DIRECTORY)
./scripts/build/electron-installer-zip-win32.sh -a $< -o $@
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-win32-$(TARGET_ARCH).exe: \
$(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-win32-$(TARGET_ARCH) \
| $(BUILD_OUTPUT_DIRECTORY) $(BUILD_TEMPORARY_DIRECTORY)
./scripts/build/electron-installer-nsis-win32.sh -n $(APPLICATION_NAME) -a $< -t $(BUILD_TEMPORARY_DIRECTORY) -o $@
ifdef CODE_SIGN_CERTIFICATE
ifdef CODE_SIGN_CERTIFICATE_PASSWORD
./scripts/build/electron-sign-exe-win32.sh -f $@ \
-d "$(APPLICATION_NAME) - $(APPLICATION_VERSION)" \
-c $(CODE_SIGN_CERTIFICATE) \
-p $(CODE_SIGN_CERTIFICATE_PASSWORD)
endif
endif
electron-build: assets/dmg/background.tiff | $(BUILD_TEMPORARY_DIRECTORY)
$(RESIN_SCRIPTS)/electron/build.sh \
-b $(shell pwd) \
-r $(TARGET_ARCH) \
-s $(PLATFORM) \
-v production \
-n $(BUILD_TEMPORARY_DIRECTORY)/npm
# ---------------------------------------------------------------------
# Phony targets
@@ -414,123 +123,84 @@ endif
TARGETS = \
help \
info \
lint \
lint-ts \
lint-sass \
lint-cpp \
lint-spell \
test-spectron \
test-gui \
test \
sanity-checks \
clean \
distclean \
package-electron \
package-cli \
cli-develop \
electron-develop
webpack \
electron-develop \
electron-test \
electron-build
package-electron: $(BUILD_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH)
package-cli: $(BUILD_DIRECTORY)/$(APPLICATION_NAME)-cli-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH)
ifeq ($(TARGET_PLATFORM),darwin)
electron-installer-app-zip: $(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip
electron-installer-dmg: $(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).dmg
TARGETS += \
electron-installer-dmg \
electron-installer-app-zip
PUBLISH_AWS_S3 += \
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip \
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).dmg
endif
ifeq ($(TARGET_PLATFORM),linux)
electron-installer-appimage: $(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip
electron-installer-debian: $(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME_LOWERCASE)-electron_$(APPLICATION_VERSION_DEBIAN)_$(TARGET_ARCH_DEBIAN).deb
TARGETS += \
electron-installer-appimage \
electron-installer-debian
PUBLISH_AWS_S3 += \
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip
PUBLISH_BINTRAY_DEBIAN += \
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME_LOWERCASE)-electron_$(APPLICATION_VERSION_DEBIAN)_$(TARGET_ARCH_DEBIAN).deb
endif
ifeq ($(TARGET_PLATFORM),win32)
electron-installer-zip: $(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip
electron-installer-nsis: $(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-win32-$(TARGET_ARCH).exe
TARGETS += \
electron-installer-zip \
electron-installer-nsis
PUBLISH_AWS_S3 += \
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-$(TARGET_PLATFORM)-$(TARGET_ARCH).zip \
$(BUILD_OUTPUT_DIRECTORY)/$(APPLICATION_NAME)-$(APPLICATION_VERSION)-win32-$(TARGET_ARCH).exe
endif
ifdef PUBLISH_AWS_S3
publish-aws-s3: $(PUBLISH_AWS_S3)
ifeq ($(RELEASE_TYPE),production)
$(foreach publishable,$^,$(call execute-command,./scripts/publish/aws-s3.sh \
-f $(publishable) \
-b $(S3_BUCKET) \
-v $(APPLICATION_VERSION) \
-p $(PRODUCT_NAME)))
endif
ifeq ($(RELEASE_TYPE),snapshot)
$(foreach publishable,$^,$(call execute-command,./scripts/publish/aws-s3.sh \
-f $(publishable) \
-b $(S3_BUCKET) \
-v $(APPLICATION_VERSION) \
-p $(PRODUCT_NAME) \
-k $(shell date +"%Y-%m-%d")))
endif
TARGETS += publish-aws-s3
endif
ifdef PUBLISH_BINTRAY_DEBIAN
publish-bintray-debian: $(PUBLISH_BINTRAY_DEBIAN)
$(foreach publishable,$^,$(call execute-command,./scripts/publish/bintray-debian.sh \
-f $(publishable) \
-v $(APPLICATION_VERSION_DEBIAN) \
-r $(TARGET_ARCH) \
-c $(APPLICATION_NAME_LOWERCASE) \
-t $(RELEASE_TYPE)))
TARGETS += publish-bintray-debian
endif
webpack:
./node_modules/.bin/webpack
.PHONY: $(TARGETS)
cli-develop:
./scripts/build/dependencies-npm.sh \
-r "$(TARGET_ARCH)" \
-v "$(ELECTRON_VERSION)" \
-t node \
-s "$(TARGET_PLATFORM)"
sass:
npm rebuild node-sass
node-sass lib/gui/app/scss/main.scss > lib/gui/css/main.css
electron-develop:
./scripts/build/dependencies-npm.sh \
-r "$(TARGET_ARCH)" \
-v "$(ELECTRON_VERSION)" \
-t electron \
-s "$(TARGET_PLATFORM)"
lint-ts:
resin-lint --fix --typescript typings lib tests scripts/clean-shrinkwrap.ts webpack.config.ts
lint-sass:
sass-lint lib/gui/scss
lint-cpp:
cpplint --recursive src
lint-spell:
codespell \
--dictionary - \
--dictionary dictionary.txt \
--skip *.svg *.gz,*.bz2,*.xz,*.zip,*.img,*.dmg,*.iso,*.rpi-sdcard,*.wic,.DS_Store,*.dtb,*.dtbo,*.dat,*.elf,*.bin,*.foo,xz-without-extension \
lib tests docs Makefile *.md LICENSE
lint: lint-ts lint-sass lint-cpp lint-spell
MOCHA_OPTIONS=--recursive --reporter spec --require ts-node/register
# See https://github.com/electron/spectron/issues/127
ETCHER_SPECTRON_ENTRYPOINT ?= $(shell node -e 'console.log(require("electron"))')
test-spectron:
ETCHER_SPECTRON_ENTRYPOINT="$(ETCHER_SPECTRON_ENTRYPOINT)" mocha $(MOCHA_OPTIONS) tests/spectron/runner.spec.ts
test-gui:
electron-mocha $(MOCHA_OPTIONS) --full-trace --no-sandbox --renderer tests/gui/**/*.ts
test-sdk:
electron-mocha $(MOCHA_OPTIONS) --full-trace --no-sandbox tests/shared/**/*.ts
test: test-gui test-sdk test-spectron
help:
@echo "Available targets: $(TARGETS)"
info:
@echo "Application version : $(APPLICATION_VERSION)"
@echo "Release type : $(RELEASE_TYPE)"
@echo "Host platform : $(HOST_PLATFORM)"
@echo "Platform : $(PLATFORM)"
@echo "Host arch : $(HOST_ARCH)"
@echo "Target platform : $(TARGET_PLATFORM)"
@echo "Target arch : $(TARGET_ARCH)"
sanity-checks:
./scripts/ci/ensure-all-node-requirements-available.sh
./scripts/ci/ensure-staged-sass.sh
./scripts/ci/ensure-npm-dependencies-compatibility.sh
./scripts/ci/ensure-npm-shrinkwrap-versions.sh
./scripts/ci/ensure-all-file-extensions-in-gitattributes.sh
./scripts/ci/ensure-all-text-files-only-ascii.sh
clean:
rm -rf $(BUILD_DIRECTORY)
distclean: clean
rm -rf node_modules
rm -rf build
rm -rf dist
rm -rf generated
rm -rf $(BUILD_TEMPORARY_DIRECTORY)
.DEFAULT_GOAL = help

131
README.md
View File

@@ -1,70 +1,109 @@
Etcher
======
# Etcher
> Flash OS images to SD cards & USB drives, safely and easily.
Etcher is a powerful OS image flasher built with web technologies to ensure
flashing an SDCard or USB drive is a pleasant and safe experience. It protects
you from accidentally writing to your hard-drives, ensures every byte of data
was written correctly and much more.
was written correctly and much more. It can also flash directly Raspberry Pi devices that support the usbboot protocol
[![dependencies](https://david-dm.org/resin-io/etcher.svg)](https://david-dm.org/resin-io/etcher.svg)
[![Build Status](https://travis-ci.org/resin-io/etcher.svg?branch=master)](https://travis-ci.org/resin-io/etcher)
[![Build status](https://ci.appveyor.com/api/projects/status/e745k1gt39nik0t7/branch/master?svg=true)](https://ci.appveyor.com/project/resin-io/etcher/branch/master)
[![Gitter](https://badges.gitter.im/resin-io/etcher.svg)](https://gitter.im/resin-io/etcher?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Stories in Ready](https://badge.waffle.io/resin-io/etcher.svg?label=in%20progress&title=In%20Progress)](https://waffle.io/resin-io/etcher)
[![Current Release](https://img.shields.io/github/release/balena-io/etcher.svg?style=flat-square)](https://balena.io/etcher)
[![License](https://img.shields.io/github/license/balena-io/etcher.svg?style=flat-square)](https://github.com/balena-io/etcher/blob/master/LICENSE)
[![Dependency status](https://img.shields.io/david/balena-io/etcher.svg?style=flat-square)](https://david-dm.org/balena-io/etcher)
[![Balena.io Forums](https://img.shields.io/discourse/https/forums.balena.io/topics.svg?style=flat-square&label=balena.io%20forums)](https://forums.balena.io/c/etcher)
***
[**Download**][etcher] | [**Support**][SUPPORT] | [**Documentation**][USER-DOCUMENTATION] | [**Contributing**][CONTRIBUTING] | [**Roadmap**][milestones] | [**CLI**][CLI]
[**Download**][etcher] | [**Support**][SUPPORT] | [**Documentation**][USER-DOCUMENTATION] | [**Contributing**][CONTRIBUTING] | [**Roadmap**][milestones]
![Etcher](https://raw.githubusercontent.com/resin-io/etcher/master/screenshot.png)
Supported Operating Systems
---------------------------
## Supported Operating Systems
- Linux (most distros)
- macOS 10.9 and later
- macOS 10.10 (Yosemite) and later
- Microsoft Windows 7 and later
Note that Etcher will run on any platform officially supported by
[Electron][electron]. Read more in their
[documentation][electron-supported-platforms].
Installers
----------
## Installers
Refer to the [downloads page][etcher] for the latest pre-made
installers for all supported operating systems.
#### Debian and Ubuntu based Package Repository (GNU/Linux x86/x64)
1. Save the following as `/etc/apt/sources.list.d/etcher.list`:
1. Add Etcher debian repository:
```
deb https://dl.bintray.com/resin-io/debian stable etcher
```sh
echo "deb https://deb.etcher.io stable etcher" | sudo tee /etc/apt/sources.list.d/balena-etcher.list
```
2. Trust Bintray.com's GPG key:
```sh
sudo apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 379CE192D401AB61
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 379CE192D401AB61
```
3. Update and install:
```sh
sudo apt-get update
sudo apt-get install etcher-electron
sudo apt-get install balena-etcher-electron
```
##### Uninstall
```sh
sudo apt-get remove etcher-electron
sudo rm /etc/apt/sources.list.d/etcher.list
sudo apt-get remove balena-etcher-electron
sudo rm /etc/apt/sources.list.d/balena-etcher.list
sudo apt-get update
```
#### Redhat (RHEL) and Fedora based Package Repository (GNU/Linux x86/x64)
1. Add Etcher rpm repository:
```sh
sudo wget https://balena.io/etcher/static/etcher-rpm.repo -O /etc/yum.repos.d/etcher-rpm.repo
```
2. Update and install:
```sh
sudo yum install -y balena-etcher-electron
```
or
```sh
sudo dnf install -y balena-etcher-electron
```
##### Uninstall
```sh
sudo yum remove -y balena-etcher-electron
sudo rm /etc/yum.repos.d/etcher-rpm.repo
sudo yum clean all
sudo yum makecache fast
```
or
```sh
sudo dnf remove -y balena-etcher-electron
sudo rm /etc/yum.repos.d/etcher-rpm.repo
sudo dnf clean all
sudo dnf makecache
```
#### Solus (GNU/Linux x64)
```sh
sudo eopkg it etcher
```
##### Uninstall
```sh
sudo eopkg rm etcher
```
#### Brew Cask (macOS)
@@ -73,34 +112,46 @@ so it might not refer to the latest version immediately after an Etcher
release.
```sh
brew cask install etcher
brew cask install balenaetcher
```
##### Uninstall
```sh
brew cask uninstall etcher
brew cask uninstall balenaetcher
```
Support
-------
#### Chocolatey (Windows)
This package is maintained by [@majkinetor](https://github.com/majkinetor), and
is kept up to date automatically.
```sh
choco install etcher
```
##### Uninstall
```sh
choco uninstall etcher
```
## Support
If you're having any problem, please [raise an issue][newissue] on GitHub and
the resin.io team will be happy to help.
the balena.io team will be happy to help.
License
-------
## License
Etcher is free software, and may be redistributed under the terms specified in
the [license].
[etcher]: https://etcher.io
[electron]: http://electron.atom.io
[electron-supported-platforms]: http://electron.atom.io/docs/tutorial/supported-platforms/
[SUPPORT]: https://github.com/resin-io/etcher/blob/master/SUPPORT.md
[CONTRIBUTING]: https://github.com/resin-io/etcher/blob/master/docs/CONTRIBUTING.md
[CLI]: https://github.com/resin-io/etcher/blob/master/docs/CLI.md
[USER-DOCUMENTATION]: https://github.com/resin-io/etcher/blob/master/docs/USER-DOCUMENTATION.md
[milestones]: https://github.com/resin-io/etcher/milestones
[newissue]: https://github.com/resin-io/etcher/issues/new
[license]: https://github.com/resin-io/etcher/blob/master/LICENSE
[etcher]: https://balena.io/etcher
[electron]: https://electronjs.org/
[electron-supported-platforms]: https://electronjs.org/docs/tutorial/support#supported-platforms
[SUPPORT]: https://github.com/balena-io/etcher/blob/master/SUPPORT.md
[CONTRIBUTING]: https://github.com/balena-io/etcher/blob/master/docs/CONTRIBUTING.md
[USER-DOCUMENTATION]: https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md
[milestones]: https://github.com/balena-io/etcher/milestones
[newissue]: https://github.com/balena-io/etcher/issues/new
[license]: https://github.com/balena-io/etcher/blob/master/LICENSE

View File

@@ -4,12 +4,13 @@ Getting help with Etcher
There are various ways to get support for Etcher if you experience an issue or
have an idea you'd like to share with us.
Gitter
Forums
------
We have a [Gitter chat room][gitter] for Etcher which is open to everyone,
please come join us :). Drop us a line there and the resin.io staff and
community users will be happy to assist.
We have a [Discourse forum][discourse] which is open to everyone, so please
come join us :). Drop us a line there and the balena.io staff and community
users will be happy to assist. Your question might already be answered, so take
a look at the existing threads before opening a new one!
Make sure to mention the following information to help us provide better
support:
@@ -19,7 +20,7 @@ support:
- The operating system you're running Etcher in.
- Relevant logging output, if any, from DevTools, which you can open by
pressing `Ctrl+Alt+I` or `Cmd+Alt+I` depending on your platform.
pressing `Ctrl+Shift+I` or `Cmd+Alt+I` depending on your platform.
GitHub
------
@@ -28,6 +29,6 @@ If you encounter an issue or have a suggestion, head on over to Etcher's [issue
tracker][issues] and if there isn't a ticket covering it, [create
one][new-issue].
[gitter]: https://gitter.im/resin-io/etcher
[issues]: https://github.com/resin-io/etcher/issues
[new-issue]: https://github.com/resin-io/etcher/issues/new
[discourse]: https://forums.balena.io/c/etcher
[issues]: https://github.com/balena-io/etcher/issues
[new-issue]: https://github.com/balena-io/etcher/issues/new

31
afterPack.js Normal file
View File

@@ -0,0 +1,31 @@
'use strict'
const cp = require('child_process')
const fs = require('fs')
const outdent = require('outdent')
const path = require('path')
exports.default = function(context) {
if (context.packager.platform.name !== 'linux') {
return
}
const scriptPath = path.join(context.appOutDir, context.packager.executableName)
const binPath = scriptPath + '.bin'
cp.execFileSync('mv', [scriptPath, binPath])
fs.writeFileSync(
scriptPath,
outdent({trimTrailingNewline: false})`
#!/bin/bash
# Resolve symlinks. Warning, readlink -f doesn't work on MacOS/BSD
script_dir="$(dirname "$(readlink -f "\${BASH_SOURCE[0]}")")"
if [[ $EUID -ne 0 ]] || [[ $ELECTRON_RUN_AS_NODE ]]; then
"\${script_dir}"/${context.packager.executableName}.bin "$@"
else
"\${script_dir}"/${context.packager.executableName}.bin "$@" --no-sandbox
fi
`
)
cp.execFileSync('chmod', ['+x', scriptPath])
}

22
afterSignHook.js Normal file
View File

@@ -0,0 +1,22 @@
'use strict'
const { notarize } = require('electron-notarize')
async function main(context) {
const { electronPlatformName, appOutDir } = context
if (electronPlatformName !== 'darwin') {
return
}
const appName = context.packager.appInfo.productFilename
const appleId = 'accounts+apple@balena.io'
await notarize({
appBundleId: 'io.balena.etcher',
appPath: `${appOutDir}/${appName}.app`,
appleId,
appleIdPassword: `@keychain:Application Loader: ${appleId}`
})
}
exports.default = main

View File

@@ -1,59 +0,0 @@
# appveyor file
# http://www.appveyor.com/docs/appveyor-yml
image: Visual Studio 2015
cache:
- C:\Users\appveyor\.node-gyp
- '%AppData%\npm-cache'
- C:\ProgramData\chocolatey\bin -> appveyor.yml
- C:\ProgramData\chocolatey\lib -> appveyor.yml
- C:\Users\appveyor\AppData\Local\Temp\chocolatey -> appveyor.yml
# what combinations to test
environment:
global:
ELECTRON_NO_ATTACH_CONSOLE: true
nodejs_version: 6.1.0
matrix:
- TARGET_ARCH: x64
- TARGET_ARCH: x86
clone_depth: 3
matrix:
fast_finish: true
install:
- ps: Install-Product node $env:nodejs_version x64
- npm install -g npm@4.4.4
- npm install -g rimraf asar
- choco install nsis -version 2.51
- choco install jq
- choco install curl
- set PATH=C:\Program Files (x86)\Windows Kits\8.1\bin\x86;%PATH%
- set PATH=C:\Program Files (x86)\NSIS;%PATH%
- set PATH=C:\MinGW\bin;%PATH%
- set PATH=C:\MinGW\msys\1.0\bin;%PATH%
- pip install codespell==1.9.2 awscli
- make info
- make electron-develop
build: off
test_script:
- node --version
- npm --version
- make sanity-checks
- cmd: npm test
deploy_script:
- cmd: .\scripts\ci\deploy-appveyor.bat
notifications:
- provider: Webhook
url: https://webhooks.gitter.im/e/0becb34b32e20d389bb8
on_build_success: false
on_build_failure: true
on_build_status_changed: true

BIN
assets/dmg/background.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
assets/dmg/background.tiff Executable file

Binary file not shown.

BIN
assets/dmg/background@2x.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
assets/icon.icns Normal file → Executable file

Binary file not shown.

BIN
assets/icon.ico Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 361 KiB

BIN
assets/icon.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
assets/iconset/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
assets/iconset/16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

BIN
assets/iconset/256x256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
assets/iconset/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

BIN
assets/iconset/48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/iconset/512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -1,2 +0,0 @@
#!/usr/bin/env node
require('../lib/cli/etcher');

35
binding.gyp Normal file
View File

@@ -0,0 +1,35 @@
{
"targets": [
{
"target_name": "elevator",
"include_dirs" : [
"src",
"<!(node -e \"require('nan')\")"
],
'conditions': [
[ 'OS=="win"', {
"sources": [
"src/utils/v8utils.cpp",
"src/os/win32/elevate.cpp",
"src/elevator_init.cpp",
],
"libraries": [
"-lShell32.lib",
],
} ],
[ 'OS=="mac"', {
"xcode_settings": {
"OTHER_CPLUSPLUSFLAGS": [
"-stdlib=libc++"
],
"OTHER_LDFLAGS": [
"-stdlib=libc++"
]
}
} ]
],
}
],
}

4
dev-app-update.yml Normal file
View File

@@ -0,0 +1,4 @@
owner: balena-io
repo: etcher
provider: github
updaterCacheDirName: balena-etcher-updater

View File

@@ -1,2 +0,0 @@
boolen->boolean
aknowledge->acknowledge

9
dictionary.txt Normal file
View File

@@ -0,0 +1,9 @@
boolen->boolean
aknowledge->acknowledge
seleted->selected
reming->remind
locl->local
subsribe->subscribe
unsubsribe->unsubscribe
calcluate->calculate
dictionaty->dictionary

View File

@@ -12,7 +12,6 @@ technologies used in Etcher that you should become familiar with:
- [Electron][electron]
- [NodeJS][nodejs]
- [AngularJS][angularjs]
- [Redux][redux]
- [ImmutableJS][immutablejs]
- [Bootstrap][bootstrap]
@@ -40,64 +39,18 @@ to submit their work or bug reports.
These are the main Etcher components, in a nutshell:
- [Etcher Image Write][etcher-image-write]
This is the repository that implements the actual procedures to write an image
to a raw device and the place where image validation resides. Its main purpose
is to abstract the messy details of interacting with raw devices in all major
operating systems.
- [Etcher Image Stream](https://github.com/resin-io-modules/etcher-image-stream)
The goal of this project is to convert any kind of input into a readable stream
representing the image so it can be plugged to [etcher-image-write]. Inputs
that this module might handle could be, for example: a simple image file, a URL
to an image, a compressed image, an image inside a ZIP archive, etc. Together
with [etcher-image-write], these modules are the building blocks needed to take
an image representation to the user's device, the "Etcher's backend".
- [Drivelist](https://github.com/resin-io-modules/drivelist)
- [Drivelist](https://github.com/balena-io-modules/drivelist)
As the name implies, this module's duty is to detect the connected drives
uniformly in all major operating systems, along with valuable metadata, like if
a drive is removable or not, to prevent users from trying to write an image to
a system drive.
- [Etcher](https://github.com/resin-io/etcher)
- [Etcher](https://github.com/balena-io/etcher)
This is the *"main repository"*, from which you're reading this from, which is
basically the front-end and glue for all previously listed projects.
Front-ends
----------
The main repository consists of the implementation of the Etcher CLI and the
Etcher GUI (the desktop application), located at [`lib/cli/`][cli-dir] and
[`lib/gui/`][gui-dir], respectively.
In fact, the only front-end that interacts directly with Etcher's backend is
the CLI. The GUI merely forks the CLI and communicates with its child process
to get state information.
In this sense, you can consider the GUI as being the front-end to the CLI,
which is in turn the front-end to the actual image writing functionality.
As a way to simplify how the GUI forks the CLI in a packaged and distributed
context, both the CLI and GUI share the same application entry point. This
means that the same Etcher binary can behave as CLI or GUI as needed.
## Process communication
As mentioned before, the Etcher GUI forks the CLI and retrieves information
from it to update its state. In order to accomplish this, the Etcher CLI
contains certain features to ease communication:
- [Well-documented exit codes.][exit-codes]
- An environment variable called `ETCHER_CLI_ROBOT` option, which when set
causes the Etcher CLI to output state in a way that can be easily
parsed by a machine.
Summary
-------
@@ -108,13 +61,10 @@ since fresh eyes could help unveil things that we take for granted, but should
be documented instead!
[lego-blocks]: https://github.com/sindresorhus/ama/issues/10#issuecomment-117766328
[etcher-image-write]: https://github.com/resin-io-modules/etcher-image-write
[exit-codes]: https://github.com/resin-io/etcher/blob/master/lib/shared/exit-codes.js
[cli-dir]: https://github.com/resin-io/etcher/tree/master/lib/cli
[gui-dir]: https://github.com/resin-io/etcher/tree/master/lib/gui
[exit-codes]: https://github.com/balena-io/etcher/blob/master/lib/shared/exit-codes.js
[gui-dir]: https://github.com/balena-io/etcher/tree/master/lib/gui
[electron]: http://electron.atom.io
[nodejs]: https://nodejs.org
[angularjs]: https://angularjs.org
[redux]: http://redux.js.org
[immutablejs]: http://facebook.github.io/immutable-js/
[bootstrap]: http://getbootstrap.com

View File

@@ -1,51 +0,0 @@
Etcher CLI
==========
The Etcher CLI is a command-line tool that aims to provide all the benefits of
the Etcher desktop application in a way that can be run from a terminal, or
even used from a script.
In fact, the Etcher desktop application is simply a wrapper around the CLI,
which is the place where the actual writing logic takes place.
Running
-------
We are not oficially releasing the Etcher CLI as a separate package yet, but
you can run it locally with the following steps:
- Clone the Etcher repository.
```
git clone https://github.com/resin-io/etcher
```
- Install the dependencies by running:
```sh
npm install
```
- Run the Etcher CLI from `bin/etcher`.
```
./bin/etcher --help
```
Options
-------
```
--help, -h show help
--version, -v show version number
--drive, -d drive
--check, -c validate write
--yes, -y confirm non-interactively
--unmount, -u unmount on success
```
Debug mode
----------
You can set the `ETCHER_CLI_DEBUG` environment variable to make the Etcher CLI
print error stack traces.

View File

@@ -56,11 +56,6 @@ The scope is required for types that make sense, such as `feat`, `fix`,
`test`, etc. Certain commit types, such as `chore` might not have a clearly
defined scope, in which case its better to omit it.
When it applies, the scope must be either `GUI` or `CLI`.
A commit that takes part in both the GUI and CLI scopes, and makes more logical
sense that way, might entirely omit the scope.
Subject
-------
@@ -122,8 +117,8 @@ A commit can include multiple instances of this tag.
Examples:
```
Closes: https://github.com/resin-io/etcher/issues/XXX
Fixes: https://github.com/resin-io/etcher/issues/XXX
Closes: https://github.com/balena-io/etcher/issues/XXX
Fixes: https://github.com/balena-io/etcher/issues/XXX
```
### `Change-Type: <type>`
@@ -198,7 +193,7 @@ first non compressed extension.
Change-Type: patch
Changelog-Entry: Don't interpret image file name information between dots as image extensions.
Fixes: https://github.com/resin-io/etcher/issues/492
Fixes: https://github.com/balena-io/etcher/issues/492
```
***
@@ -212,8 +207,8 @@ the operating system still thinks the drive has a file system.
Change-Type: patch
Changelog-Entry: Upgrade `etcher-image-write` to v5.0.2.
Link: https://github.com/resin-io-modules/etcher-image-write/blob/master/CHANGELOG.md#502---2016-06-27
Fixes: https://github.com/resin-io/etcher/issues/531
Link: https://github.com/balena-io-modules/etcher-image-write/blob/master/CHANGELOG.md#502---2016-06-27
Fixes: https://github.com/balena-io/etcher/issues/531
```
***
@@ -243,7 +238,7 @@ re-used by other services.
Change-Type: minor
Changelog-Entry: Check for updates and show a modal prompting the user to download the latest version.
Closes: https://github.com/resin-io/etcher/issues/396
Closes: https://github.com/balena-io/etcher/issues/396
```
[angular-commit-guidelines]: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit

View File

@@ -10,18 +10,119 @@ High-level Etcher overview
Make sure you checkout our [ARCHITECTURE.md][ARCHITECTURE] guide, which aims to
explain how all the pieces fit together.
Running locally
---------------
See the [RUNNING-LOCALLY.md][RUNNING-LOCALLY] guide.
Developing
----------
We rely on various `npm` scripts to perform some common tasks:
### Prerequisites
- `npm run lint`: Run the linter.
- `npm run sass`: Compile SCSS files.
#### Common
- [NodeJS](https://nodejs.org) (at least v6.11)
- [Python 2.7](https://www.python.org)
- [jq](https://stedolan.github.io/jq/)
- [curl](https://curl.haxx.se/)
- [npm](https://www.npmjs.com/) (version 6.7)
```sh
pip install -r requirements.txt
```
You might need to run this with `sudo` or administrator permissions.
#### Windows
- [NSIS v2.51](http://nsis.sourceforge.net/Main_Page) (v3.x won't work)
- Either one of the following:
- [Visual C++ 2015 Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) containing standalone compilers, libraries and scripts
- Install the [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) via npm with `npm install --global windows-build-tools`
- [Visual Studio Community 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48146) (free) (other editions, like Professional and Enterprise, should work too)
**NOTE:** Visual Studio 2015 doesn't install C++ by default. You have to rerun the
setup, select "Modify" and then check `Visual C++ -> Common Tools for Visual
C++ 2015` (see http://stackoverflow.com/a/31955339)
- [MinGW](http://www.mingw.org)
You might need to `npm config set msvs_version 2015` for node-gyp to correctly detect
the version of Visual Studio you're using (in this example VS2015).
The following MinGW packages are required:
- `msys-make`
- `msys-unzip`
- `msys-zip`
- `msys-bash`
- `msys-coreutils`
#### macOS
- [Xcode](https://developer.apple.com/xcode/)
It's not enough to have [Xcode Command Line Tools] installed. Xcode must be installed
as well.
#### Linux
- `libudev-dev` for libusb (install with `sudo apt install libudev-dev` for example)
### Cloning the project
```sh
git clone --recursive https://github.com/balena-io/etcher
cd etcher
```
### Installing npm dependencies
**NOTE:** Please make use of the following command to install npm dependencies rather
than simply running `npm install` given that we need to do extra configuration
to make sure native dependencies are correctly compiled for Electron, otherwise
the application might not run successfully.
If you're on Windows, **run the command from the _Developer Command Prompt for
VS2015_**, to ensure all Visual Studio command utilities are available in the
`%PATH%`.
```sh
make electron-develop
```
### Running the application
#### GUI
```sh
# Build the GUI
make webpack
# Start Electron
npm start
```
Testing
-------
To run the test suite, run the following command:
```sh
npm test
```
Given the nature of this application, not everything can be unit tested. For
example:
- The writing operating on real raw devices.
- Platform inconsistencies.
- Style changes.
- Artwork.
We encourage our contributors to test the application on as many operating
systems as they can before sending a pull request.
*The test suite is run automatically by CI servers when you send a pull
request.*
We also rely on various `make` targets to perform some common tasks:
- `make lint`: Run the linter.
- `make sass`: Compile SCSS files.
We make use of [EditorConfig] to communicate indentation, line endings and
other text editing default. We encourage you to install the relevant plugin in
@@ -46,28 +147,33 @@ Use the following steps to ensure everything goes flawlessly:
- Commit *both* `package.json` and `npm-shrinkwrap.json`.
Testing
-------
Diffing Binaries
----------------
To run the test suite, run the following command:
Binary files are tagged as "binary" in the `.gitattributes` file, but also have
a `diff=hex` tag, which allows you to see hexdump-style diffs for binaries,
if you add the following to either your global or repository-local git config:
```sh
npm test
$ git config diff.hex.textconv hexdump
$ git config diff.hex.binary true
```
Given the nature of this application, not everything can be unit tested. For
example:
And global, respectively:
- The writing operating on real raw devices.
- Platform inconsistencies.
- Style changes.
- Artwork.
```sh
$ git config --global diff.hex.textconv hexdump
$ git config --global diff.hex.binary true
```
We encourage our contributors to test the application on as many operating
systems as they can before sending a pull request.
If you don't have `hexdump` available on your platform,
you can try [hxd], which is also a bit faster.
*The test suite is run automatically by CI servers when you send a pull
request.*
Commit Guidelines
-----------------
See [COMMIT-GUIDELINES.md][COMMIT-GUIDELINES] for a thorough guide on how to
write commit messages.
Sending a pull request
----------------------
@@ -95,7 +201,7 @@ Before your pull request can be merged, the following conditions must hold:
- The linter doesn't throw any warning.
- All the tests passes.
- All the tests pass.
- The coding style aligns with the project's convention.
@@ -104,7 +210,9 @@ systems we support.
Don't hesitate to get in touch if you have any questions or need any help!
[ARCHITECTURE]: https://github.com/resin-io/etcher/blob/master/docs/ARCHITECTURE.md
[RUNNING-LOCALLY]: https://github.com/resin-io/etcher/blob/master/docs/RUNNING-LOCALLY.md
[ARCHITECTURE]: https://github.com/balena-io/etcher/blob/master/docs/ARCHITECTURE.md
[COMMIT-GUIDELINES]: https://github.com/balena-io/etcher/blob/master/docs/COMMIT-GUIDELINES.md
[EditorConfig]: http://editorconfig.org
[shrinkwrap]: https://docs.npmjs.com/cli/shrinkwrap
[hxd]: https://github.com/jhermsmeier/hxd
[Xcode Command Line Tools]: https://developer.apple.com/library/content/technotes/tn2339/_index.html

View File

@@ -1,46 +1,174 @@
Maintaining Etcher
==================
This document is meant to serve as a guide for maintainers to perform common
tasks.
This document is meant to serve as a guide for maintainers to perform common tasks.
Preparing a new version
-----------------------
Releasing
---------
- Bump the version number in the `package.json`'s `version` property.
### Release Types
- Bump the version number in the `package.json`'s `builder.win.version`
- **snapshot** (default): A continues snapshot of current master, made by the CI services
- **production**: Full releases
- Bump the version number in the `npm-shrinkwrap.json`'s `version` property.
### Flight Plan
- Add a new entry to `CHANGELOG.md` by running `npm run changelog`.
#### Preparation
- Re-take `screenshot.png` so it displays the latest version in the bottom
right corner.
- [Prepare the new version](#preparing-a-new-version)
- [Generate build artifacts](#generating-binaries) (binaries, archives, etc.)
- [Draft a release on GitHub](https://github.com/balena-io/etcher/releases)
- Upload build artifacts to GitHub release draft
- Commit the changes with the version number as the commit title, including the
`v` prefix, to `master`. For example:
#### Testing
```sh
git commit -m "v1.0.0" # not 1.0.0
- Test the prepared release and build artifacts properly on **all supported operating systems** to prevent regressions that went uncaught by the CI tests (see [MANUAL-TESTING.md](MANUAL-TESTING.md))
- If regressions or other issues arise, create issues on the repository for each one, and decide whether to fix them in this release (meaning repeating the process up until this point), or to follow up with a patch release
#### Publishing
- [Publish release draft on GitHub](https://github.com/balena-io/etcher/releases)
- [Post release note to forums](https://forums.balena.io/c/etcher)
- [Submit Windows binaries to Symantec for whitelisting](#submitting-binaries-to-symantec)
- [Update the website](https://github.com/balena-io/etcher-homepage)
- Wait 2-3 hours for analytics (Sentry, Mixpanel) to trickle in and check for elevated error rates, or regressions
- If regressions arise; pull the release, and release a patched version, else:
- [Upload deb & rpm packages to Bintray](#uploading-packages-to-bintray)
- [Upload build artifacts to Amazon S3](#uploading-binaries-to-amazon-s3)
- Post changelog with `#release-notes` tag on Flowdock
- If this release packs noteworthy major changes:
- Write a blog post about it, and / or
- Write about it to the Etcher mailing list
### Generating binaries
**Environment**
Make sure to set the analytics tokens when generating production release binaries:
```bash
export ANALYTICS_SENTRY_TOKEN="xxxxxx"
export ANALYTICS_MIXPANEL_TOKEN="xxxxxx"
```
- Create an annotated tag for the new version. The commit title should equal
the annotated tag name. For example:
#### Linux
```sh
git tag -a v1.0.0 -m "v1.0.0"
##### Clean dist folder
**NOTE:** Make sure to adjust the path as necessary (here the Etcher repository has been cloned to `/home/$USER/code/etcher`)
```bash
./scripts/build/docker/run-command.sh -r x64 -s . -c "make distclean"
```
- Push the commit and the annotated tag.
##### Generating artifacts
```sh
git push
git push --tags
```bash
# x64
# Build Debian packages
./scripts/build/docker/run-command.sh -r x64 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-debian"
# Build RPM packages
./scripts/build/docker/run-command.sh -r x64 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-redhat"
# Build AppImages
./scripts/build/docker/run-command.sh -r x64 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-appimage"
# x86
# Build Debian packages
./scripts/build/docker/run-command.sh -r x86 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-debian"
# Build RPM packages
./scripts/build/docker/run-command.sh -r x86 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-redhat"
# Build AppImages
./scripts/build/docker/run-command.sh -r x86 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-appimage"
```
Upgrading Electron
------------------
#### Mac OS
- Upgrade the `electron-prebuilt` dependency version in `package.json` to an
*exact version* (no `~`, `^`, etc).
**ATTENTION:** For production releases you'll need the code-signing key,
and set `CSC_NAME` to generate signed binaries on Mac OS.
```bash
make electron-develop
# Build the zip
make RELEASE_TYPE=production electron-installer-app-zip
# Build the dmg
make RELEASE_TYPE=production electron-installer-dmg
```
#### Windows
**ATTENTION:** For production releases you'll need the code-signing key,
and set `CSC_LINK`, and `CSC_KEY_PASSWORD` to generate signed binaries on Windows.
**NOTE:**
- Keep in mind to also generate artifacts for x86, with `TARGET_ARCH=x86`.
```bash
make electron-develop
# Build the Portable version
make RELEASE_TYPE=production electron-installer-portable
# Build the Installer
make RELEASE_TYPE=production electron-installer-nsis
```
### Uploading packages to Bintray
```bash
export BINTRAY_USER="username@account"
export BINTRAY_API_KEY="youruserapikey"
```
```bash
./scripts/publish/bintray.sh -c "etcher" -t "production" -v "1.2.1" -o "etcher" -p "debian" -y "debian" -r "x64" -f "dist/etcher-electron_1.2.1_amd64.deb"
./scripts/publish/bintray.sh -c "etcher" -t "production" -v "1.2.1" -o "etcher" -p "debian" -y "debian" -r "x86" -f "dist/etcher-electron_1.2.1_i386.deb"
./scripts/publish/bintray.sh -c "etcher" -t "production" -v "1.2.1" -o "etcher" -p "redhat" -y "redhat" -r "x64" -f "dist/etcher-electron-1.2.1.x86_64.rpm"
./scripts/publish/bintray.sh -c "etcher" -t "production" -v "1.2.1" -o "etcher" -p "redhat" -y "redhat" -r "x86" -f "dist/etcher-electron-1.2.1.i686.rpm"
```
### Uploading binaries to Amazon S3
```bash
export S3_KEY="..."
```
```bash
./scripts/publish/aws-s3.sh -b "balena-production-downloads" -v "1.2.1" -p "etcher" -f "dist/<filename>"
```
### Dealing with a Problematic Release
There can be times where a release is accidentally plagued with bugs. If you
released a new version and notice the error rates are higher than normal, then
revert the problematic release as soon as possible, until the bugs are fixed.
You can revert a version by deleting its builds from the S3 bucket and Bintray.
Refer to the `Makefile` for the up to date information about the S3 bucket
where we push builds to, and get in touch with the balena.io operations team to
get write access to it.
The Etcher update notifier dialog and the website only show the a certain
version if all the expected files have been uploaded to it, so deleting a
single package or two is enough to bring down the whole version.
Use the following command to delete files from S3:
```bash
aws s3api delete-object --bucket <bucket name> --key <file name>
```
The Bintray dashboard provides an easy way to delete a version's files.
### Submitting binaries to Symantec
- [Report a Suspected Erroneous Detection](https://submit.symantec.com/false_positive/standard/)
- Fill out form:
- **Select Submission Type:** "Provide a direct download URL"
- **Name of the software being detected:** Etcher
- **Name of detection given by Symantec product:** WS.Reputation.1
- **Contact name:** Balena.io Ltd
- **E-mail address:** hello@etcher.io
- **Are you the creator or distributor of the software in question?** Yes

115
docs/MANUAL-TESTING.md Normal file
View File

@@ -0,0 +1,115 @@
Manual Testing
==============
This document describes a high-level script of manual tests to check for. We
should aim to replace items on this list with automated Spectron test cases.
Image Selection
---------------
- [ ] Cancel image selection dialog
- [ ] Select an unbootable image (without a partition table), and expect a
sensible warning
- [ ] Attempt to select a ZIP archive with more than one image
- [ ] Attempt to select a tar archive (with any compression method)
- [ ] Change image selection
- [ ] Select a Windows image, and expect a sensible warning
Drive Selection
---------------
- [ ] Open the drive selection modal
- [ ] Switch drive selection
- [ ] Insert a single drive, and expect auto-selection
- [ ] Insert more than one drive, and don't expect auto-selection
- [ ] Insert a locked SD Card and expect a warning
- [ ] Insert a too small drive and expect a warning
- [ ] Put an image into a drive and attempt to flash the image to the drive
that contains it
- [ ] Attempt to flash a compressed image (for which we can get the
uncompressed size) into a drive that is big enough to hold the compressed
image, but not big enough to hold the uncompressed version
- [ ] Enable "Unsafe Mode" and attempt to select a system drive
- [ ] Enable "Unsafe Mode", and if there is only one system drive (and no
removable ones), don't expect autoselection
Image Support
-------------
Run the following tests with and without validation enabled:
- [ ] Flash an uncompressed image
- [ ] Flash a Bzip2 image
- [ ] Flash a XZ image
- [ ] Flash a ZIP image
- [ ] Flash a GZ image
- [ ] Flash a DMG image
- [ ] Flash an image whose size is not a multiple of 512 bytes
- [ ] Flash a compressed image whose size is not a multiple of 512 bytes
- [ ] Flash an archive whose image size is not a multiple of 512 bytes
- [ ] Flash an archive image containing a logo
- [ ] Flash an archive image containing a blockmap file
- [ ] Flash an archive image containing a manifest metadata file
Flashing Process
----------------
- [ ] Unplug the drive during flash or validation
- [ ] Click "Flash", cancel elevation dialog, and click "Flash" again
- [ ] Start flashing an image, try to close Etcher, cancel the application
close warning dialog, and check that Etcher continues to flash the image
### Child Writer
- [ ] Kill the child writer process (i.e. with `SIGINT` or `SIGKILL`), and
check that the UI reacts appropriately
- [ ] Close the application while flashing using the window manager close icon
- [ ] Close the application while flashing using the OS keyboard shortcut
- [ ] Close the application from the terminal using Ctrl-C while flashing
- [ ] Force kill the application (using a process monitor tool, etc)
In all these cases, the child writer process should not remain alive. Note that
in some systems you need to open your process monitor tool of choice with extra
permissions to see the elevated child writer process.
GUI
----
- [ ] Close application from the terminal using Ctrl-C while the application is
idle
- [ ] Click footer links that take you to an external website
- [ ] Attempt to change image or drive selection while flashing
- [ ] Go to the settings page while flashing and come back
- [ ] Flash consecutive images without closing the application
- [ ] Remove the selected drive right before clicking "Flash"
- [ ] Minimize the application
- [ ] Start the application given no internet connection
Success Banner
--------------
- [ ] Click an external link on the success banner (with and without internet
connection)
Elevation Prompt
----------------
- [ ] Flash an image as `root`/administrator
- [ ] Reject elevation prompt
- [ ] Put incorrect elevation prompt password
- [ ] Unplug the drive during elevation
Unmounting
----------
- [ ] Disable unmounting and flash an image
- [ ] Flash an image with a file system that is readable by the host OS, and
check that is unmounted correctly
Analytics
---------
- [ ] Disable analytics, open DevTools Network pane or a packet sniffer, and
check that no request is sent
- [ ] **Disable analytics, refresh application from DevTools (using Cmd-R or
F5), and check that initial events are not sent to Mixpanel**

View File

@@ -4,13 +4,55 @@ Publishing Etcher
This is a small guide to package and publish Etcher to all supported operating
systems.
Release Types
-------------
Etcher supports **production** and **snapshot** release types. Each is
published to a different S3 bucket, and production release types are code
signed, while snapshot release types aren't and include a short git commit-hash
as a build number. For example, `1.0.0-beta.19` is a production release type,
while `1.0.0-beta.19+531ab82` is a snapshot release type.
In terms of comparison: `1.0.0-beta.19` (production) < `1.0.0-beta.19+531ab82`
(snapshot) < `1.0.0-rc.1` (production) < `1.0.0-rc.1+7fde24a` (snapshot) <
`1.0.0` (production) < `1.0.0+2201e5f` (snapshot). Keep in mind that if you're
running a production release type, you'll only be prompted to update to
production release types, and if you're running a snapshot release type, you'll
only be prompted to update to other snapshot release types.
The build system creates (and publishes) snapshot release types by default, but
you can build a specific release type by setting the `RELEASE_TYPE` make
variable. For example:
```sh
make <target> RELEASE_TYPE=snapshot
make <target> RELEASE_TYPE=production
```
We can control the version range a specific Etcher version will consider when
showing the update notification dialog by tweaking the `updates.semverRange`
property of `package.json`.
Update Channels
---------------
Etcher has a setting to include the unstable update channel. If this option is
set, Etcher will consider both stable and unstable versions when showing the
update notifier dialog. Unstable versions are the ones that contain a `beta`
pre-release tag. For example:
- Production unstable version: `1.4.0-beta.1`
- Snapshot unstable version: `1.4.0-beta.1+7fde24a`
- Production stable version: `1.4.0`
- Snapshot stable version: `1.4.0+7fde24a`
Signing
-------
### OS X
1. Get our Apple Developer ID certificate for signing applications distributed
outside the Mac App Store from the resin.io Apple account.
outside the Mac App Store from the balena.io Apple account.
2. Install the Developer ID certificate to your Mac's Keychain by double
clicking on the certificate file.
@@ -20,7 +62,7 @@ packaging for OS X.
### Windows
1. Get access to our code signing certificate and decryption key as a resin.io
1. Get access to our code signing certificate and decryption key as a balena.io
employee by asking for it from the relevant people.
2. Place the certificate in the root of the Etcher repository naming it
@@ -29,40 +71,31 @@ employee by asking for it from the relevant people.
Packaging
---------
The resulting installers will be saved to `dist/out`.
Run the following commands:
### OS X
Run the following command:
```sh
make electron-installer-dmg
make electron-installer-app-zip
```
The resulting installers will be saved to `release/out`.
### GNU/Linux
Run the following command:
```sh
make electron-installer-appimage
make electron-installer-debian
```
The resulting installers will be saved to `release/out`.
### Windows
Run the following command:
```sh
make electron-installer-zip
make electron-installer-nsis
```
The resulting installers will be saved to `etcher-release/installers`.
Publishing to Bintray
---------------------
@@ -76,7 +109,7 @@ Make sure you set the following environment variables:
Run the following command:
```sh
make publish-bintray-debian RELEASE_TYPE=<production|snapshot>
make publish-bintray-debian
```
Publishing to S3
@@ -85,17 +118,17 @@ Publishing to S3
- [AWS CLI][aws-cli]
Make sure you have the [AWS CLI tool][aws-cli] installed and configured to
access resin.io's production or snapshot S3 bucket.
access balena.io's production or snapshot S3 bucket.
Run the following command to publish all files for the current combination of
_platform_ and _arch_ (building them if necessary):
```sh
make publish-aws-s3 RELEASE_TYPE=<production|snapshot>
make publish-aws-s3
```
Also add links to each AWS S3 file in [GitHub Releases][github-releases]. See
[`v1.0.0-beta.17`](https://github.com/resin-io/etcher/releases/tag/v1.0.0-beta.17)
[`v1.0.0-beta.17`](https://github.com/balena-io/etcher/releases/tag/v1.0.0-beta.17)
as an example.
Publishing to Homebrew Cask
@@ -110,14 +143,12 @@ Publishing to Homebrew Cask
Announcing
----------
Post messages to the [Etcher forum][resin-forum-etcher] and
[Etcher gitter channel][gitter-etcher] announcing the new version
Post messages to the [Etcher forum][balena-forum-etcher] announcing the new version
of Etcher, and including the relevant section of the Changelog.
[aws-cli]: https://aws.amazon.com/cli
[bintray]: https://bintray.com
[etcher-cask-file]: https://github.com/caskroom/homebrew-cask/blob/master/Casks/etcher.rb
[etcher-cask-file]: https://github.com/caskroom/homebrew-cask/blob/master/Casks/balenaetcher.rb
[homebrew-cask]: https://github.com/caskroom/homebrew-cask
[resin-forum-etcher]: https://talk.resin.io/c/etcher/annoucements
[gitter-etcher]: https://gitter.im/resin-io/etcher
[github-releases]: https://github.com/resin-io/etcher/releases
[balena-forum-etcher]: https://forums.balena.io/c/etcher
[github-releases]: https://github.com/balena-io/etcher/releases

View File

@@ -1,85 +0,0 @@
Running locally
===============
This document aims to serve as a guide to get Etcher running locally on your
development machine.
Prerequisites
-------------
### Common
- [NodeJS](https://nodejs.org) (at least v6)
- [Python](https://www.python.org)
- [jq](https://stedolan.github.io/jq/)
- [Asar](https://github.com/electron/asar)
- [Codespell](https://github.com/lucasdemarchi/codespell)
- [curl](https://curl.haxx.se/)
### Windows
- [Rimraf](https://github.com/isaacs/rimraf)
- [NSIS v2.51](http://nsis.sourceforge.net/Main_Page) (v3.x won't work)
- Either one of the following:
- [Visual C++ 2015 Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) containing standalone compilers, libraries and scripts
- Install the [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) via npm with `npm install --global windows-build-tools`
- [Visual Studio Community 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48146) (free) (other editions, like Professional and Enterprise, should work too)
**NOTE:** Visual Studio 2015 doesn't install C++ by default. You have to rerun the
setup, select "Modify" and then check `Visual C++ -> Common Tools for Visual
C++ 2015` (see http://stackoverflow.com/a/31955339)
- [MinGW](http://www.mingw.org)
The following MinGW packages are required:
- `msys-make`
- `msys-unzip`
- `msys-zip`
- `msys-bash`
- `msys-coreutils`
### OS X
- [XCode](https://developer.apple.com/xcode/)
- [afsctool](https://brkirch.wordpress.com/afsctool/)
Cloning the project
-------------------
```sh
git clone https://github.com/resin-io/etcher
cd etcher
```
Installing npm dependencies
---------------------------
**Make sure you have all the pre-requisites listed above installed in your
system before running the `install` script.**
Please make use of the following scripts to install npm dependencies rather
than simply running `npm install` given that we need to do extra configuration
to make sure native dependencies are correctly compiled for Electron, otherwise
the application might not run successfully.
If you're on Windows, **run the command from the _Developer Command Prompt for
VS2015_**, to ensure all Visual Studio command utilities are available in the
`%PATH%`.
```sh
make electron-develop
```
Running the application
-----------------------
### GUI
```sh
npm start
```
### CLI
```sh
node bin/etcher
```

View File

@@ -14,8 +14,8 @@ images, usually available from the image publishers themselves.
Images known to require special treatment:
- Microsoft Windows (use [Windows USB/DVD Download Tool][windows-usb-tool], or
[Rufus][rufus]).
- Microsoft Windows (use [Windows USB/DVD Download Tool][windows-usb-tool],
[Rufus][rufus], or [WoeUSB][woeusb]).
- Windows 10 IoT (use the [Windows 10 IoT Core Dashboard][windows-iot-dashboard])
@@ -30,7 +30,7 @@ if you require this functionality, we advise to fallback to
Deactivate desktop shortcut prompt on GNU/Linux
-----------------------------------------------
This is a feature provided by [AppImages](appimage), where the applications
This is a feature provided by [AppImages][appimage], where the applications
prompts the user to automatically register a desktop shortcut to easily access
the application.
@@ -130,25 +130,6 @@ run Etcher on a GNU/Linux system.
- liblzma (for xz decompression)
Disable update notifications
----------------------------
You can disable update notifications, which can be useful when running Etcher
outside a common desktop environment (like in a [resin.io] application), by
setting the `ETCHER_DISABLE_UPDATES` environment variable.
In GNU/Linux and Mac OS X:
```sh
export ETCHER_DISABLE_UPDATES=1
```
In Windows:
```sh
set ETCHER_DISABLE_UPDATES=1
```
Recovering broken drives
------------------------
@@ -210,20 +191,18 @@ Running in older macOS versions
-------------------------------
Etcher GUI is based on the [Electron][electron] framework, [which only supports
macOS 10.9 and newer versions][electron-supported-platforms].
macOS 10.10 (Yosemite) and newer versions][electron-supported-platforms].
You can however, run the [Etcher CLI][etcher-cli], which should work in older
platforms.
[resin.io]: https://resin.io
[balena.io]: https://balena.io
[appimage]: http://appimage.org
[xwayland]: https://wayland.freedesktop.org/xserver.html
[weston.ini]: http://manpages.ubuntu.com/manpages/wily/man5/weston.ini.5.html
[diskpart]: https://technet.microsoft.com/en-us/library/cc770877(v=ws.11).aspx
[electron]: http://electron.atom.io
[electron-supported-platforms]: https://github.com/electron/electron/blob/master/docs/tutorial/supported-platforms.md
[etcher-cli]: https://github.com/resin-io/etcher/blob/master/docs/CLI.md
[electron]: https://electronjs.org/
[electron-supported-platforms]: https://electronjs.org/docs/tutorial/support#supported-platforms
[publishing]: https://github.com/balena-io/etcher/blob/master/docs/PUBLISHING.md
[windows-usb-tool]: https://www.microsoft.com/en-us/download/windows-usb-dvd-download-tool
[rufus]: https://rufus.akeo.ie
[unetbootin]: https://unetbootin.github.io
[windows-iot-dashboard]: https://developer.microsoft.com/en-us/windows/iot/downloads
[woeusb]: https://github.com/slacka/WoeUSB

View File

@@ -1 +0,0 @@
theme: jekyll-theme-minimal

111
electron-builder.yml Normal file
View File

@@ -0,0 +1,111 @@
appId: io.balena.etcher
copyright: Copyright 2016-2019 Balena Ltd
productName: balenaEtcher
npmRebuild: true
nodeGypRebuild: true
publish: null
afterPack: "./afterPack.js"
files:
- build/Release/elevator.node
- generated
- lib/shared/catalina-sudo/sudo-askpass.osascript.js
- lib/gui/app/index.html
- lib/gui/css/*.css
- lib/gui/css/fonts/*.woff2
- lib/gui/assets/*.svg
- assets/icon.png
- "!node_modules/**/**"
- "node_modules/**/*.js"
- "node_modules/**/*.json"
- "node_modules/**/*.node"
- "node_modules/**/*.dll"
- node_modules/node-raspberrypi-usbboot/blobs/**
- node_modules/flexboxgrid/dist/flexboxgrid.css
- node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff
- node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff
- node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff
- node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff
- node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff
- node_modules/bootstrap-sass/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2
mac:
asar: false
icon: assets/icon.icns
category: public.app-category.developer-tools
hardenedRuntime: true
entitlements: "entitlements.mac.plist"
entitlementsInherit: "entitlements.mac.plist"
dmg:
background: assets/dmg/background.tiff
icon: assets/icon.icns
iconSize: 110
contents:
- x: 140
y: 225
- x: 415
y: 225
type: link
path: /Applications
window:
width: 540
height: 405
win:
icon: assets/icon.ico
nsis:
oneClick: true
runAfterFinish: true
installerIcon: assets/icon.ico
uninstallerIcon: assets/icon.ico
deleteAppDataOnUninstall: true
license: LICENSE
artifactName: "${productName}-Setup-${version}.${ext}"
portable:
artifactName: "${productName}-Portable-${version}.${ext}"
requestExecutionLevel: user
linux:
category: Utility
packageCategory: utils
executableName: balena-etcher-electron
synopsis: balenaEtcher is a powerful OS image flasher built with web technologies to ensure flashing an SDCard or USB drive is a pleasant and safe experience. It protects you from accidentally writing to your hard-drives, ensures every byte of data was written correctly and much more.
icon: assets/iconset
deb:
priority: optional
depends:
- gconf2
- gconf-service
- libappindicator1
- libasound2
- libatk1.0-0
- libc6
- libcairo2
- libcups2
- libdbus-1-3
- libexpat1
- libfontconfig1
- libfreetype6
- libgcc1
- libgconf-2-4
- libgdk-pixbuf2.0-0
- libglib2.0-0
- libgtk-3-0
- liblzma5
- libnotify4
- libnspr4
- libnss3
- libpango1.0-0
- libstdc++6
- libx11-6
- libxcomposite1
- libxcursor1
- libxdamage1
- libxext6
- libxfixes3
- libxi6
- libxrandr2
- libxrender1
- libxss1
- libxtst6
- polkit-1-auth-agent | policykit-1-gnome | polkit-kde-1
rpm:
depends:
- lsb
- libXScrnSaver

18
entitlements.mac.plist Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View File

@@ -1,69 +0,0 @@
Etcher Child Writer
===================
This module is in charge of dealing with the gory details of elevating and
managing the child writer process. As a word of warning, it contains tons of
workarounds and "hacks" to deal with platform differences, packaging, and
inter-process communication. This empowers us to write this small guide to
explain how it works in a more high level manner, hoping to make it easier to
grok for contributors.
The problem
-----------
Elevating a forked process is an easy task. Thanks to the widely available NPM
modules to display nice GUI prompt dialogs, elevation is just a matter of
executing the process with one of those modules instead of with `child_process`
directly.
The main problems we faced are:
- The modules that implement elevation provide "execution" support, but don't
allow us to fork/spawn the process and consume its `stdout` and `stderr` in a
stream fashion. This also means that we can't use the nice `process.send` IPC
communication channel directly that `child_process.fork` gives us to send
messages back to the parent.
- Since we can't assume anything from the environment Etcher is running on, we
must make use of the same application entry point to execute both the GUI and
the CLI code, which starts to get messy once we throw `asar` packaging into
the mix.
- Each elevation mechanism has its quirks, mainly on GNU/Linux. Making sure
that the forked process was elevated correctly and could work without issues
required various workarounds targeting `pkexec` or `kdesudo`.
How it works
------------
The Etcher binary runs in CLI or GUI mode depending on an environment variable
called `ELECTRON_RUN_AS_NODE`. When this variable is set, it instructs Electron
to run as a normal NodeJS process (without Chromium, etc), but still keep any
patches applied by Electron, like `asar` support.
When the Etcher GUI is ran, and the user presses the "Flash!" button, the GUI
creates an IPC server, and forks a process called the "writer proxy", passing
it all the required information to perform the flashing, such as the image
path, the device path, the current settings, etc.
The writer proxy then checks if its currently elevated, and if not, prompts the
user for elevation and re-spawns itself.
Once the writer proxy has enough permissions to directly access devices, it
spawns the Etcher CLI passing the `--robot` option along with all the
information gathered before. The `--robot` option basically tells the Etcher
CLI to output state information in a way that can be very easily parsed by the
parent process.
The output of the Etcher CLI is then sent to the IPC server that was opened by
the GUI, which nicely displays them in the progress bar the user sees.
Summary
-------
There are lots of details we're omitting for the sake of clarity. Feel free to
dive in inside the child writer code, which is heavily commented to explain the
reasons behind each decision or workaround.
Don't hesitate in getting in touch if you have any suggestion, or just want to
know more!

View File

@@ -1,100 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const _ = require('lodash');
/**
* @summary Get the explicit boolean form of an argument
* @function
* @private
*
* @description
* We refer as "explicit boolean form of an argument" to a boolean
* argument in either normal or negated form.
*
* For example: `--check` and `--no-check`;
*
* @param {String} argumentName - argument name
* @param {Boolean} value - argument value
* @returns {String} argument
*
* @example
* console.log(cli.getBooleanArgumentForm('check', true));
* > '--check'
*
* @example
* console.log(cli.getBooleanArgumentForm('check', false));
* > '--no-check'
*/
exports.getBooleanArgumentForm = (argumentName, value) => {
const prefix = _.attempt(() => {
if (!value) {
return '--no-';
}
const SHORT_OPTION_LENGTH = 1;
if (_.size(argumentName) === SHORT_OPTION_LENGTH) {
return '-';
}
return '--';
});
return prefix + argumentName;
};
/**
* @summary Get CLI writer arguments
* @function
* @public
*
* @param {Object} options - options
* @param {String} options.image - image
* @param {String} options.device - device
* @param {String} options.entryPoint - entry point
* @param {Boolean} [options.validateWriteOnSuccess] - validate write on success
* @param {Boolean} [options.unmountOnSuccess] - unmount on success
* @returns {String[]} arguments
*
* @example
* const argv = cli.getArguments({
* image: 'path/to/rpi.img',
* device: '/dev/disk2'
* entryPoint: 'path/to/app.asar',
* validateWriteOnSuccess: true,
* unmountOnSuccess: true
* });
*/
exports.getArguments = (options) => {
const argv = [
options.entryPoint,
options.image,
'--drive',
options.device,
// Explicitly set the boolean flag in positive
// or negative way in order to be on the safe
// side in case the Etcher CLI changes the
// default value of these options.
exports.getBooleanArgumentForm('unmount', options.unmountOnSuccess),
exports.getBooleanArgumentForm('check', options.validateWriteOnSuccess)
];
return argv;
};

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const path = require('path');
/**
* @summary Child writer constants
* @namespace CONSTANTS
* @public
*/
module.exports = {
/**
* @property {String} PROJECT_ROOT
* @memberof CONSTANTS
*/
PROJECT_ROOT: path.join(__dirname, '..', '..'),
/**
* @property {String} WRITER_PROXY_SCRIPT
* @memberof CONSTANTS
*/
WRITER_PROXY_SCRIPT: path.join(__dirname, 'writer-proxy.js')
};

View File

@@ -1,198 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const EventEmitter = require('events').EventEmitter;
const _ = require('lodash');
const childProcess = require('child_process');
const ipc = require('node-ipc');
const rendererUtils = require('./renderer-utils');
const cli = require('./cli');
const CONSTANTS = require('./constants');
const EXIT_CODES = require('../shared/exit-codes');
const robot = require('../shared/robot');
/**
* @summary Perform a write
* @function
* @public
*
* @param {String} image - image
* @param {Object} drive - drive
* @param {Object} options - options
* @returns {EventEmitter} event emitter
*
* @example
* const child = childWriter.write('path/to/rpi.img', {
* device: '/dev/disk2'
* }, {
* validateWriteOnSuccess: true,
* unmountOnSuccess: true
* });
*
* child.on('progress', (state) => {
* console.log(state);
* });
*
* child.on('error', (error) => {
* throw error;
* });
*
* child.on('done', () => {
* console.log('Validation was successful!');
* });
*/
exports.write = (image, drive, options) => {
const emitter = new EventEmitter();
const argv = cli.getArguments({
entryPoint: rendererUtils.getApplicationEntryPoint(),
image,
device: drive.device,
validateWriteOnSuccess: options.validateWriteOnSuccess,
unmountOnSuccess: options.unmountOnSuccess
});
// There might be multiple Etcher instances running at
// the same time, therefore we must ensure each IPC
// server/client has a different name.
process.env.IPC_SERVER_ID = `etcher-server-${process.pid}`;
process.env.IPC_CLIENT_ID = `etcher-client-${process.pid}`;
ipc.config.id = process.env.IPC_SERVER_ID;
ipc.config.silent = true;
ipc.serve();
/**
* @summary Safely terminate the IPC server
* @function
* @private
*
* @example
* terminateServer();
*/
const terminateServer = () => {
// Turns out we need to destroy all sockets for
// the server to actually close. Otherwise, it
// just stops receiving any further connections,
// but remains open if there are active ones.
_.each(ipc.server.sockets, (socket) => {
socket.destroy();
});
ipc.server.stop();
};
/**
* @summary Emit an error to the client
* @function
* @private
*
* @param {Error} error - error
*
* @example
* emitError(new Error('foo bar'));
*/
const emitError = (error) => {
terminateServer();
emitter.emit('error', error);
};
/**
* @summary Bridge robot message to the child writer caller
* @function
* @private
*
* @param {String} message - robot message
*
* @example
* bridgeRobotMessage(robot.buildMessage('foo', {
* bar: 'baz'
* }));
*/
const bridgeRobotMessage = (message) => {
try {
const parsedMessage = robot.parseMessage(message);
// These are lighweight accessor methods for
// the properties of the parsed message
const messageCommand = robot.getCommand(parsedMessage);
const messageData = robot.getData(parsedMessage);
// The error object is decomposed by the CLI for serialisation
// purposes. We compose it back to an `Error` here in order
// to provide better encapsulation.
if (messageCommand === 'error') {
emitError(robot.recomposeErrorMessage(parsedMessage));
} else if (messageCommand === 'log') {
console.log(messageData);
} else {
emitter.emit(messageCommand, messageData);
}
} catch (error) {
emitError(error);
}
};
ipc.server.on('error', emitError);
ipc.server.on('message', bridgeRobotMessage);
ipc.server.on('start', () => {
const child = childProcess.fork(CONSTANTS.WRITER_PROXY_SCRIPT, argv, {
silent: true,
env: process.env
});
child.stdout.on('data', (data) => {
console.info(`WRITER: ${data.toString()}`);
});
child.stderr.on('data', (data) => {
bridgeRobotMessage(data.toString());
// This function causes the `close` event to be emitted
child.kill();
});
child.on('error', emitError);
child.on('close', (code) => {
terminateServer();
if (code === EXIT_CODES.CANCELLED) {
return emitter.emit('done', {
cancelled: true
});
}
// We shouldn't emit the `done` event manually here
// since the writer process will take care of it.
if (code === EXIT_CODES.SUCCESS || code === EXIT_CODES.VALIDATION_ERROR) {
return null;
}
return emitError(new Error(`Child process exited with error code: ${code}`));
});
});
ipc.server.start();
return emitter;
};

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
/**
* This file is only meant to be loaded by the renderer process.
*/
const path = require('path');
const isRunningInAsar = require('electron-is-running-in-asar');
const electron = require('electron');
const CONSTANTS = require('./constants');
/**
* @summary Get application entry point
* @function
* @public
*
* @returns {String} entry point
*
* @example
* const entryPoint = rendererUtils.getApplicationEntryPoint();
*/
exports.getApplicationEntryPoint = () => {
if (isRunningInAsar()) {
return path.join(process.resourcesPath, 'app.asar');
}
const ENTRY_POINT_ARGV_INDEX = 1;
const relativeEntryPoint = electron.remote.process.argv[ENTRY_POINT_ARGV_INDEX];
// On GNU/Linux, `pkexec` resolves relative paths
// from `/root`, therefore we pass an absolute path,
// in order to be on the safe side.
return path.join(CONSTANTS.PROJECT_ROOT, relativeEntryPoint);
};

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const _ = require('lodash');
/**
* @summary Split stringified object lines
* @function
* @public
*
* @description
* This function takes special care to not consider new lines
* inside the object properties.
*
* @param {String} lines - lines
* @returns {String[]} split lines
*
* @example
* const result = utils.splitObjectLines('{"foo":"bar"}\n{"hello":"Hello\nWorld"}');
* console.log(result);
*
* > [ '{"foo":"bar"}', '{"hello":"Hello\nWorld"}' ]
*/
exports.splitObjectLines = (lines) => {
return _.chain(lines)
.split(/((?:[^\n"']|"[^"]*"|'[^']*')+)/)
.map(_.trim)
.reject(_.isEmpty)
.value();
};

View File

@@ -1,245 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Bluebird = require('bluebird');
const childProcess = require('child_process');
const commandJoin = require('command-join');
const ipc = require('node-ipc');
const _ = require('lodash');
const os = require('os');
const path = require('path');
const sudoPrompt = Bluebird.promisifyAll(require('sudo-prompt'));
const utils = require('./utils');
const EXIT_CODES = require('../shared/exit-codes');
const errors = require('../shared/errors');
const robot = require('../shared/robot');
const permissions = require('../shared/permissions');
const packageJSON = require('../../package.json');
// This script is in charge of spawning the writer process and
// ensuring it has the necessary privileges. It might look a bit
// complex at first sight, but this is only because elevation
// modules don't work in a spawn/fork fashion.
//
// This script spawns the writer process and redirects its `stdout`
// and `stderr` to the parent process using IPC communication,
// taking care of the writer elevation as needed.
/**
* @summary The Etcher executable file path
* @constant
* @private
* @type {String}
*/
const executable = _.first(process.argv);
/**
* @summary The first index that represents an actual option argument
* @constant
* @private
* @type {Number}
*
* @description
* The first arguments are usually the program executable itself, etc.
*/
const OPTIONS_INDEX_START = 2;
/**
* @summary The list of Etcher argument options
* @constant
* @private
* @type {String[]}
*/
const etcherArguments = process.argv.slice(OPTIONS_INDEX_START);
return permissions.isElevated().then((elevated) => {
if (!elevated) {
console.log('Attempting to elevate');
if (os.platform() === 'win32') {
const elevator = Bluebird.promisifyAll(require('elevator'));
const commandArguments = [
'set',
'ELECTRON_RUN_AS_NODE=1',
'&&',
'set',
`IPC_SERVER_ID=${process.env.IPC_SERVER_ID}`,
'&&',
'set',
`IPC_CLIENT_ID=${process.env.IPC_CLIENT_ID}`,
'&&',
// This is a trick to make the binary afterwards catch
// the environment variables set just previously.
'call'
].concat(process.argv);
// For debugging purposes
console.log(`Running: ${commandArguments.join(' ')}`);
return elevator.executeAsync(commandArguments, {
hidden: true,
terminating: true,
doNotPushdCurrentDirectory: true,
waitForTermination: true
}).catch({
code: 'ELEVATE_CANCELLED'
}, () => {
process.exit(EXIT_CODES.CANCELLED);
});
}
const commandArguments = _.attempt(() => {
const commandPrefix = [
// Some elevation tools, like `pkexec` or `kdesudo`, don't
// provide a way to preserve the environment, therefore we
// have to make sure the environment variables we're interested
// in are manually inherited.
'env',
'ELECTRON_RUN_AS_NODE=1',
`IPC_SERVER_ID=${process.env.IPC_SERVER_ID}`,
`IPC_CLIENT_ID=${process.env.IPC_CLIENT_ID}`,
// This environment variable prevents the AppImages
// desktop integration script from presenting the
// "installation" dialog.
'SKIP=1'
];
if (process.env.APPIMAGE && process.env.APPDIR) {
// Translate the current arguments to point to the AppImage
// Relative paths are resolved from `/tmp/.mount_XXXXXX/usr`
const translatedArguments = _.chain(process.argv)
.tail()
.invokeMap('replace', path.join(process.env.APPDIR, 'usr/'), '')
.value();
return commandPrefix
.concat([ process.env.APPIMAGE ])
.concat(translatedArguments);
}
return commandPrefix.concat(process.argv);
});
const command = commandJoin(commandArguments);
// For debugging purposes
console.log(`Running: ${command}`);
return sudoPrompt.execAsync(command, {
name: packageJSON.displayName
}).then((stdout, stderr) => {
if (!_.isEmpty(stderr)) {
throw errors.createError(stderr);
}
// We're hardcoding internal error messages declared by `sudo-prompt`.
// There doesn't seem to be a better way to handle these errors, so
// for now, we should make sure we double check if the error messages
// have changed every time we upgrade `sudo-prompt`.
}).catch({
message: 'User did not grant permission.'
}, () => {
process.exit(EXIT_CODES.CANCELLED);
}).catch({
message: 'No polkit authentication agent found.'
}, () => {
throw errors.createUserError(
'No polkit authentication agent found',
'Please install a polkit authentication agent for your desktop environment of choice to continue'
);
});
}
console.log('Re-spawning with elevation');
return new Bluebird((resolve, reject) => {
ipc.config.id = process.env.IPC_CLIENT_ID;
ipc.config.silent = true;
// > If set to 0, the client will NOT try to reconnect.
// See https://github.com/RIAEvangelist/node-ipc/
//
// The purpose behind this change is for this process
// to emit a "disconnect" event as soon as the GUI
// process is closed, so we can kill the CLI as well.
ipc.config.stopRetrying = 0;
ipc.connectTo(process.env.IPC_SERVER_ID, () => {
ipc.of[process.env.IPC_SERVER_ID].on('error', reject);
ipc.of[process.env.IPC_SERVER_ID].on('connect', () => {
const child = childProcess.spawn(executable, etcherArguments, {
env: {
// The CLI might call operating system utilities (like `diskutil`),
// so we must ensure the `PATH` is inherited.
PATH: process.env.PATH,
ELECTRON_RUN_AS_NODE: 1,
ETCHER_CLI_ROBOT: 1
}
});
ipc.of[process.env.IPC_SERVER_ID].on('disconnect', _.bind(child.kill, child));
child.on('error', reject);
child.on('close', resolve);
/**
* @summary Emit an object message to the IPC server
* @function
* @private
*
* @param {Buffer} data - json message data
*
* @example
* emitMessage(Buffer.from(JSON.stringify({
* foo: 'bar'
* })));
*/
const emitMessage = (data) => {
// Output from stdout/stderr coming from the CLI might be buffered,
// causing several progress lines to come up at once as single message.
// Trying to parse multiple JSON objects separated by new lines will
// of course make the parser confused, causing errors later on.
_.each(utils.splitObjectLines(data.toString()), (object) => {
ipc.of[process.env.IPC_SERVER_ID].emit('message', object);
});
};
child.stdout.on('data', emitMessage);
child.stderr.on('data', emitMessage);
});
});
}).then((exitCode) => {
process.exit(exitCode);
});
}).catch((error) => {
robot.printError(error);
process.exit(EXIT_CODES.GENERAL_ERROR);
});

View File

@@ -1,46 +0,0 @@
Etcher CLI
==========
The Etcher CLI is a command line interface to the Etcher writer backend, and
currently the only module in the "Etcher" umbrella that makes use of this
backend directly.
This module also has the task of unmounting the drives before and after
flashing.
Notice the Etcher CLI is not worried about elevation, and assumes it has enough
permissions to continue, throwing an error otherwise. Consult the
[`lib/child-writer`][child-writer] module to understand how elevation works on
Etcher.
The robot option
----------------
Setting the `ETCHER_CLI_ROBOT` environment variable allows other applications
to easily consume the output of the Etcher CLI in real-time. When using the
`ETCHER_CLI_ROBOT` option, the `--yes` option is implicit, therefore you need
to manually specify `--drive`.
When `ETCHER_CLI_ROBOT` is used, the program will output JSON lines containing
the progress state and other useful information. For example:
```
$ sudo ETCHER_CLI_ROBOT=1 etcher image.iso --drive /dev/disk2
{"command":"progress","data":{"type":"write","percentage":1,"eta":130,"speed":1703936}}
...
{"command":"progress","data":{"type":"check","percentage":100,"eta":0,"speed":17180514}}
{"command":"done","data":{"sourceChecksum":"27c39a5d"}}
```
See documentation about the robot mode at [`lib/shared/robot`][robot].
Exit codes
----------
The Etcher CLI uses certain exit codes to signal the result of the operation.
These are documented in [`lib/shared/exit-codes.js`][exit-codes] and are also
printed on the Etcher CLI help page.
[exit-codes]: https://github.com/resin-io/etcher/blob/master/lib/shared/exit-codes.js
[robot]: https://github.com/resin-io/etcher/tree/master/lib/shared/robot
[child-writer]: https://github.com/resin-io/etcher/tree/master/lib/child-writer

View File

@@ -1,144 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const _ = require('lodash');
const Bluebird = require('bluebird');
const visuals = require('resin-cli-visuals');
const form = require('resin-cli-form');
const drivelist = Bluebird.promisifyAll(require('drivelist'));
const writer = require('./writer');
const utils = require('./utils');
const options = require('./options');
const robot = require('../shared/robot');
const messages = require('../shared/messages');
const EXIT_CODES = require('../shared/exit-codes');
const errors = require('../shared/errors');
const permissions = require('../shared/permissions');
const ARGV_IMAGE_PATH_INDEX = 0;
const imagePath = options._[ARGV_IMAGE_PATH_INDEX];
permissions.isElevated().then((elevated) => {
if (!elevated) {
throw errors.createUserError(
messages.error.elevationRequired(),
'This tool requires special permissions to write to external drives'
);
}
return form.run([
{
message: 'Select drive',
type: 'drive',
name: 'drive'
},
{
message: 'This will erase the selected drive. Are you sure?',
type: 'confirm',
name: 'yes',
default: false
}
], {
override: {
drive: options.drive,
// If `options.yes` is `false`, pass `null`,
// otherwise the question will not be asked because
// `false` is a defined value.
yes: robot.isEnabled(process.env) || options.yes || null
}
});
}).then((answers) => {
if (!answers.yes) {
throw errors.createUserError('Aborted', 'We can\'t proceed without confirmation');
}
const progressBars = {
write: new visuals.Progress('Flashing'),
check: new visuals.Progress('Validating')
};
return drivelist.listAsync().then((drives) => {
const selectedDrive = _.find(drives, {
device: answers.drive
});
if (!selectedDrive) {
throw errors.createUserError(
'The selected drive was not found',
`We can't find ${answers.drive} in your system. Did you unplug the drive?`
);
}
return writer.writeImage(imagePath, selectedDrive, {
unmountOnSuccess: options.unmount,
validateWriteOnSuccess: options.check
}, (state) => {
if (robot.isEnabled(process.env)) {
robot.printMessage('progress', {
type: state.type,
percentage: Math.floor(state.percentage),
eta: state.eta,
speed: Math.floor(state.speed)
});
} else {
progressBars[state.type].update(state);
}
});
});
}).then((results) => {
return Bluebird.try(() => {
if (robot.isEnabled(process.env)) {
return robot.printMessage('done', {
sourceChecksum: results.sourceChecksum
});
}
console.log(messages.info.flashComplete());
if (results.sourceChecksum) {
console.log(`Checksum: ${results.sourceChecksum}`);
}
return Bluebird.resolve();
}).then(() => {
process.exit(EXIT_CODES.SUCCESS);
});
}).catch((error) => {
return Bluebird.try(() => {
if (robot.isEnabled(process.env)) {
return robot.printError(error);
}
utils.printError(error);
return Bluebird.resolve();
}).then(() => {
if (error.code === 'EVALIDATION') {
process.exit(EXIT_CODES.VALIDATION_ERROR);
}
process.exit(EXIT_CODES.GENERAL_ERROR);
});
});

View File

@@ -1,159 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const _ = require('lodash');
const fs = require('fs');
const yargs = require('yargs');
const utils = require('./utils');
const robot = require('../shared/robot');
const EXIT_CODES = require('../shared/exit-codes');
const errors = require('../shared/errors');
const packageJSON = require('../../package.json');
/**
* @summary The minimum required number of CLI arguments
* @constant
* @private
* @type {Number}
*/
const MINIMUM_NUMBER_OF_ARGUMENTS = 1;
/**
* @summary The index of the image argument
* @constant
* @private
* @type {Number}
*/
const IMAGE_PATH_ARGV_INDEX = 0;
/**
* @summary The first index that represents an actual option argument
* @constant
* @private
* @type {Number}
*
* @description
* The first arguments are usually the program executable itself, etc.
*/
const OPTIONS_INDEX_START = 2;
/**
* @summary Parsed CLI options and arguments
* @type {Object}
* @public
*/
module.exports = yargs
// Don't wrap at all
.wrap(null)
.demand(MINIMUM_NUMBER_OF_ARGUMENTS, 'Missing image')
// Usage help
.usage('Usage: $0 [options] <image>')
.epilogue([
'Exit codes:',
_.map(EXIT_CODES, (value, key) => {
const reason = _.map(_.split(key, '_'), _.capitalize).join(' ');
return ` ${value} - ${reason}`;
}).join('\n'),
'',
'If you need help, don\'t hesitate in contacting us at:',
'',
' GitHub: https://github.com/resin-io/etcher/issues/new',
' Gitter: https://gitter.im/resin-io/etcher'
].join('\n'))
// Examples
.example('$0 raspberry-pi.img')
.example('$0 --no-check raspberry-pi.img')
.example('$0 -d /dev/disk2 ubuntu.iso')
.example('$0 -d /dev/disk2 -y rpi.img')
// Help option
.help()
// Version option
.version(_.constant(packageJSON.version))
// Error reporting
.fail((message, error) => {
const errorObject = error || errors.createUserError(message);
if (robot.isEnabled(process.env)) {
robot.printError(errorObject);
} else {
yargs.showHelp();
utils.printError(errorObject);
}
process.exit(EXIT_CODES.GENERAL_ERROR);
})
// Assert that image exists
.check((argv) => {
fs.accessSync(argv._[IMAGE_PATH_ARGV_INDEX]);
return true;
})
.check((argv) => {
if (robot.isEnabled(process.env) && !argv.drive) {
throw errors.createUserError(
'Missing drive',
'You need to explicitly pass a drive when enabling robot mode'
);
}
return true;
})
.options({
help: {
describe: 'show help',
boolean: true,
alias: 'h'
},
version: {
describe: 'show version number',
boolean: true,
alias: 'v'
},
drive: {
describe: 'drive',
string: true,
alias: 'd'
},
check: {
describe: 'validate write',
boolean: true,
alias: 'c',
default: true
},
yes: {
describe: 'confirm non-interactively',
boolean: true,
alias: 'y'
},
unmount: {
describe: 'unmount on success',
boolean: true,
alias: 'u',
default: true
}
})
.parse(process.argv.slice(OPTIONS_INDEX_START));

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const chalk = require('chalk');
const errors = require('../shared/errors');
/**
* @summary Print an error to stderr
* @function
* @public
*
* @param {Error} error - error
*
* @example
* utils.printError(new Error('Oops!'));
*/
exports.printError = (error) => {
const title = errors.getTitle(error);
const description = errors.getDescription(error, {
userFriendlyDescriptionsOnly: true
});
console.error(chalk.red(title));
if (description) {
console.error(`\n${chalk.red(description)}`);
}
if (process.env.ETCHER_CLI_DEBUG && error.stack) {
console.error(`\n${chalk.red(error.stack)}`);
}
};

View File

@@ -1,115 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const imageWrite = require('etcher-image-write');
const Bluebird = require('bluebird');
const fs = Bluebird.promisifyAll(require('fs'));
const mountutils = Bluebird.promisifyAll(require('mountutils'));
const os = require('os');
const imageStream = require('../image-stream');
const errors = require('../shared/errors');
const constraints = require('../shared/drive-constraints');
/**
* @summary Write an image to a disk drive
* @function
* @public
*
* @description
* See https://github.com/resin-io-modules/etcher-image-write for information
* about the `state` object passed to `onProgress` callback.
*
* @param {String} imagePath - path to image
* @param {Object} drive - drive
* @param {Object} options - options
* @param {Boolean} [options.unmountOnSuccess=false] - unmount on success
* @param {Boolean} [options.validateWriteOnSuccess=false] - validate write on success
* @param {Function} onProgress - on progress callback (state)
*
* @fulfil {Boolean} - whether the operation was successful
* @returns {Promise}
*
* @example
* writer.writeImage('path/to/image.img', {
* device: '/dev/disk2'
* }, {
* unmountOnSuccess: true,
* validateWriteOnSuccess: true
* }, (state) => {
* console.log(state.percentage);
* }).then(() => {
* console.log('Done!');
* });
*/
exports.writeImage = (imagePath, drive, options, onProgress) => {
return Bluebird.try(() => {
// Unmounting a drive in Windows means we can't write to it anymore
if (os.platform() === 'win32') {
return Bluebird.resolve();
}
return mountutils.unmountDiskAsync(drive.device);
}).then(() => {
return fs.openAsync(drive.raw, 'rs+');
}).then((driveFileDescriptor) => {
return imageStream.getFromFilePath(imagePath).then((image) => {
if (!constraints.isDriveLargeEnough(drive, image)) {
throw errors.createUserError(
'The image you selected is too big for this drive',
'Please connect a bigger drive and try again'
);
}
return imageWrite.write({
fd: driveFileDescriptor,
device: drive.raw,
size: drive.size
}, {
stream: image.stream,
size: image.size.original
}, {
check: options.validateWriteOnSuccess,
transform: image.transform,
bmap: image.bmap,
bytesToZeroOutFromTheBeginning: image.bytesToZeroOutFromTheBeginning
});
}).then((writer) => {
return new Bluebird((resolve, reject) => {
writer.on('progress', onProgress);
writer.on('error', reject);
writer.on('done', resolve);
});
}).tap(() => {
// Make sure the device stream file descriptor is closed
// before returning control the the caller. Not closing
// the file descriptor (and waiting for it) results in
// `EBUSY` errors when attempting to unmount the drive
// right afterwards in some Windows 7 systems.
return fs.closeAsync(driveFileDescriptor).then(() => {
if (!options.unmountOnSuccess) {
return Bluebird.resolve();
}
return mountutils.unmountDiskAsync(drive.device);
});
});
});
};

View File

@@ -1,272 +0,0 @@
/*
* Copyright 2016 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @module Etcher
*/
'use strict';
/* eslint-disable no-var */
var angular = require('angular');
/* eslint-enable no-var */
const electron = require('electron');
const Bluebird = require('bluebird');
const EXIT_CODES = require('../shared/exit-codes');
const messages = require('../shared/messages');
const packageJSON = require('../../package.json');
const flashState = require('./models/flash-state');
const Store = require('./models/store');
const app = angular.module('Etcher', [
require('angular-ui-router'),
require('angular-ui-bootstrap'),
require('angular-if-state'),
// Etcher modules
require('./modules/analytics'),
require('./modules/error'),
require('./modules/drive-scanner'),
// Models
require('./models/selection-state'),
require('./models/drives'),
// Components
require('./components/svg-icon/svg-icon'),
require('./components/update-notifier/update-notifier'),
require('./components/warning-modal/warning-modal'),
// Pages
require('./pages/main/main'),
require('./pages/finish/finish'),
require('./pages/settings/settings'),
// OS
require('./os/window-progress/window-progress'),
require('./os/open-external/open-external'),
require('./os/dropzone/dropzone'),
require('./os/dialog/dialog'),
// Utils
require('./utils/manifest-bind/manifest-bind')
]);
app.run(() => {
console.log([
' _____ _ _',
'| ___| | | |',
'| |__ | |_ ___| |__ ___ _ __',
'| __|| __/ __| \'_ \\ / _ \\ \'__|',
'| |___| || (__| | | | __/ |',
'\\____/ \\__\\___|_| |_|\\___|_|',
'',
'Interested in joining the Etcher team?',
'Drop us a line at join+etcher@resin.io'
].join('\n'));
});
app.run((AnalyticsService, ErrorService, UpdateNotifierService, SelectionStateModel) => {
AnalyticsService.logEvent('Application start');
const shouldCheckForUpdates = UpdateNotifierService.shouldCheckForUpdates();
if (!shouldCheckForUpdates || process.env.ETCHER_DISABLE_UPDATES) {
AnalyticsService.logEvent('Not checking for updates', {
shouldCheckForUpdates,
disableUpdatesEnvironmentVariable: process.env.ETCHER_DISABLE_UPDATES
});
return;
}
AnalyticsService.logEvent('Checking for updates', {
currentVersion: packageJSON.version
});
UpdateNotifierService.isLatestVersion().then((isLatestVersion) => {
if (isLatestVersion) {
AnalyticsService.logEvent('Update notification skipped', {
reason: 'Latest version'
});
return Bluebird.resolve();
}
// In case the internet connection is not good and checking the
// latest published version takes too long, only show notify
// the user about the new version if he didn't start the flash
// process (e.g: selected an image), otherwise such interruption
// might be annoying.
if (SelectionStateModel.hasImage()) {
AnalyticsService.logEvent('Update notification skipped', {
reason: 'Image selected'
});
return Bluebird.resolve();
}
AnalyticsService.logEvent('Notifying update');
return UpdateNotifierService.notify();
}).catch(ErrorService.reportException);
});
app.run((AnalyticsService, OSWindowProgressService) => {
Store.subscribe(() => {
const currentFlashState = flashState.getFlashState();
// There is usually a short time period between the `isFlashing()`
// property being set, and the flashing actually starting, which
// might cause some non-sense flashing state logs including
// `undefined` values.
//
// We use the presence of `.eta` to determine that the actual
// writing started.
if (!flashState.isFlashing() || !currentFlashState.eta) {
return;
}
AnalyticsService.logDebug([
`Progress (${currentFlashState.type}):`,
`${currentFlashState.percentage}% at ${currentFlashState.speed} MB/s`,
`(eta ${currentFlashState.eta}s)`
].join(' '));
OSWindowProgressService.set(currentFlashState.percentage);
});
});
app.run(($timeout, DriveScannerService, DrivesModel, ErrorService) => {
DriveScannerService.on('drives', (drives) => {
// Safely trigger a digest cycle.
// In some cases, AngularJS doesn't acknowledge that the
// available drives list has changed, and incorrectly
// keeps asking the user to "Connect a drive".
$timeout(() => {
DrivesModel.setDrives(drives);
});
});
DriveScannerService.on('error', (error) => {
// Stop the drive scanning loop in case of errors,
// otherwise we risk presenting the same error over
// and over again to the user, while also heavily
// spamming our error reporting service.
DriveScannerService.stop();
return ErrorService.reportException(error);
});
DriveScannerService.start();
});
app.run(($window, AnalyticsService, WarningModalService, ErrorService, OSDialogService) => {
let popupExists = false;
$window.addEventListener('beforeunload', (event) => {
if (!flashState.isFlashing() || popupExists) {
AnalyticsService.logEvent('Close application', {
isFlashing: flashState.isFlashing()
});
return;
}
// Don't close window while flashing
event.returnValue = false;
// Don't open any more popups
popupExists = true;
AnalyticsService.logEvent('Close attempt while flashing');
OSDialogService.showWarning({
confirmationLabel: 'Yes, quit',
rejectionLabel: 'Cancel',
title: 'Are you sure you want to close Etcher?',
description: messages.warning.exitWhileFlashing()
}).then((confirmed) => {
if (confirmed) {
AnalyticsService.logEvent('Close confirmed while flashing');
// This circumvents the 'beforeunload' event unlike
// electron.remote.app.quit() which does not.
electron.remote.process.exit(EXIT_CODES.SUCCESS);
}
AnalyticsService.logEvent('Close rejected while flashing');
popupExists = false;
}).catch(ErrorService.reportException);
});
});
app.run(($rootScope, AnalyticsService) => {
$rootScope.$on('$stateChangeSuccess', (event, toState, toParams, fromState) => {
// Ignore first navigation
if (!fromState.name) {
return;
}
AnalyticsService.logEvent('Navigate', {
to: toState.name,
from: fromState.name
});
});
});
app.config(($urlRouterProvider) => {
$urlRouterProvider.otherwise('/main');
});
app.config(($provide) => {
$provide.decorator('$exceptionHandler', ($delegate, $injector) => {
return (exception, cause) => {
const ErrorService = $injector.get('ErrorService');
ErrorService.reportException(exception);
$delegate(exception, cause);
};
});
});
app.controller('HeaderController', function(SelectionStateModel, OSOpenExternalService) {
/**
* @summary Open help page
* @function
* @public
*
* @description
* This application will open either the image's support url, declared
* in the archive `manifest.json`, or the default Etcher help page.
*
* @example
* HeaderController.openHelpPage();
*/
this.openHelpPage = () => {
const DEFAULT_SUPPORT_URL = 'https://github.com/resin-io/etcher/blob/master/SUPPORT.md';
const supportUrl = SelectionStateModel.getImageSupportUrl() || DEFAULT_SUPPORT_URL;
OSOpenExternalService.open(supportUrl);
};
});

352
lib/gui/app/app.ts Normal file
View File

@@ -0,0 +1,352 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as electron from 'electron';
import * as sdk from 'etcher-sdk';
import * as _ from 'lodash';
import outdent from 'outdent';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as uuidV4 from 'uuid/v4';
import * as packageJSON from '../../../package.json';
import * as EXIT_CODES from '../../shared/exit-codes';
import * as messages from '../../shared/messages';
import * as availableDrives from './models/available-drives';
import * as flashState from './models/flash-state';
import { init as ledsInit } from './models/leds';
import * as settings from './models/settings';
import { Actions, observe, store } from './models/store';
import * as analytics from './modules/analytics';
import { scanner as driveScanner } from './modules/drive-scanner';
import * as exceptionReporter from './modules/exception-reporter';
import { updateLock } from './modules/update-lock';
import * as osDialog from './os/dialog';
import * as windowProgress from './os/window-progress';
import MainPage from './pages/main/MainPage';
window.addEventListener(
'unhandledrejection',
(event: PromiseRejectionEvent | any) => {
// Promise: event.reason
// Bluebird: event.detail.reason
// Anything else: event
const error =
event.reason || (event.detail && event.detail.reason) || event;
analytics.logException(error);
event.preventDefault();
},
);
// Set application session UUID
store.dispatch({
type: Actions.SET_APPLICATION_SESSION_UUID,
data: uuidV4(),
});
// Set first flashing workflow UUID
store.dispatch({
type: Actions.SET_FLASHING_WORKFLOW_UUID,
data: uuidV4(),
});
const applicationSessionUuid = store.getState().toJS().applicationSessionUuid;
const flashingWorkflowUuid = store.getState().toJS().flashingWorkflowUuid;
console.log(outdent`
${outdent}
_____ _ _
| ___| | | |
| |__ | |_ ___| |__ ___ _ __
| __|| __/ __| '_ \\ / _ \\ '__|
| |___| || (__| | | | __/ |
\\____/ \\__\\___|_| |_|\\___|_|
Interested in joining the Etcher team?
Drop us a line at join+etcher@balena.io
Version = ${packageJSON.version}, Type = ${packageJSON.packageType}
`);
const currentVersion = packageJSON.version;
analytics.logEvent('Application start', {
packageType: packageJSON.packageType,
version: currentVersion,
applicationSessionUuid,
});
observe(() => {
if (!flashState.isFlashing()) {
return;
}
const currentFlashState = flashState.getFlashState();
const stateType =
!currentFlashState.flashing && currentFlashState.verifying
? `Verifying ${currentFlashState.verifying}`
: `Flashing ${currentFlashState.flashing}`;
// NOTE: There is usually a short time period between the `isFlashing()`
// property being set, and the flashing actually starting, which
// might cause some non-sense flashing state logs including
// `undefined` values.
analytics.logDebug(
`${stateType} devices, ` +
`${currentFlashState.percentage}% at ${currentFlashState.speed} MB/s ` +
`(total ${currentFlashState.totalSpeed} MB/s) ` +
`eta in ${currentFlashState.eta}s ` +
`with ${currentFlashState.failed} failed devices`,
);
windowProgress.set(currentFlashState);
});
/**
* @summary The radix used by USB ID numbers
*/
const USB_ID_RADIX = 16;
/**
* @summary The expected length of a USB ID number
*/
const USB_ID_LENGTH = 4;
/**
* @summary Convert a USB id (e.g. product/vendor) to a string
*
* @example
* console.log(usbIdToString(2652))
* > '0x0a5c'
*/
function usbIdToString(id: number): string {
return `0x${_.padStart(id.toString(USB_ID_RADIX), USB_ID_LENGTH, '0')}`;
}
/**
* @summary Product ID of BCM2708
*/
const USB_PRODUCT_ID_BCM2708_BOOT = 0x2763;
/**
* @summary Product ID of BCM2710
*/
const USB_PRODUCT_ID_BCM2710_BOOT = 0x2764;
/**
* @summary Compute module descriptions
*/
const COMPUTE_MODULE_DESCRIPTIONS: _.Dictionary<string> = {
[USB_PRODUCT_ID_BCM2708_BOOT]: 'Compute Module 1',
[USB_PRODUCT_ID_BCM2710_BOOT]: 'Compute Module 3',
};
let BLACKLISTED_DRIVES: string[] = [];
function driveIsAllowed(drive: {
devicePath: string;
device: string;
raw: string;
}) {
return !(
BLACKLISTED_DRIVES.includes(drive.devicePath) ||
BLACKLISTED_DRIVES.includes(drive.device) ||
BLACKLISTED_DRIVES.includes(drive.raw)
);
}
type Drive =
| sdk.sourceDestination.BlockDevice
| sdk.sourceDestination.UsbbootDrive
| sdk.sourceDestination.DriverlessDevice;
function prepareDrive(drive: Drive) {
if (drive instanceof sdk.sourceDestination.BlockDevice) {
// @ts-ignore (BlockDevice.drive is private)
return drive.drive;
} else if (drive instanceof sdk.sourceDestination.UsbbootDrive) {
// This is a workaround etcher expecting a device string and a size
// @ts-ignore
drive.device = drive.usbDevice.portId;
drive.size = null;
// @ts-ignore
drive.progress = 0;
drive.disabled = true;
drive.on('progress', progress => {
updateDriveProgress(drive, progress);
});
return drive;
} else if (drive instanceof sdk.sourceDestination.DriverlessDevice) {
const description =
COMPUTE_MODULE_DESCRIPTIONS[
drive.deviceDescriptor.idProduct.toString()
] || 'Compute Module';
return {
device: `${usbIdToString(
drive.deviceDescriptor.idVendor,
)}:${usbIdToString(drive.deviceDescriptor.idProduct)}`,
displayName: 'Missing drivers',
description,
mountpoints: [],
isReadOnly: false,
isSystem: false,
disabled: true,
icon: 'warning',
size: null,
link:
'https://www.raspberrypi.org/documentation/hardware/computemodule/cm-emmc-flashing.md',
linkCTA: 'Install',
linkTitle: 'Install missing drivers',
linkMessage: outdent`
Would you like to download the necessary drivers from the Raspberry Pi Foundation?
This will open your browser.
Once opened, download and run the installer from the "Windows Installer" section to install the drivers
`,
};
}
}
function setDrives(drives: _.Dictionary<any>) {
availableDrives.setDrives(_.values(drives));
}
function getDrives() {
return _.keyBy(availableDrives.getDrives() || [], 'device');
}
function addDrive(drive: Drive) {
const preparedDrive = prepareDrive(drive);
if (!driveIsAllowed(preparedDrive)) {
return;
}
const drives = getDrives();
drives[preparedDrive.device] = preparedDrive;
setDrives(drives);
}
function removeDrive(drive: Drive) {
const preparedDrive = prepareDrive(drive);
const drives = getDrives();
delete drives[preparedDrive.device];
setDrives(drives);
}
function updateDriveProgress(
drive: sdk.sourceDestination.UsbbootDrive,
progress: number,
) {
const drives = getDrives();
// @ts-ignore
const driveInMap = drives[drive.device];
if (driveInMap) {
driveInMap.progress = progress;
setDrives(drives);
}
}
driveScanner.on('attach', addDrive);
driveScanner.on('detach', removeDrive);
driveScanner.on('error', error => {
// Stop the drive scanning loop in case of errors,
// otherwise we risk presenting the same error over
// and over again to the user, while also heavily
// spamming our error reporting service.
driveScanner.stop();
return exceptionReporter.report(error);
});
driveScanner.start();
let popupExists = false;
window.addEventListener('beforeunload', async event => {
if (!flashState.isFlashing() || popupExists) {
analytics.logEvent('Close application', {
isFlashing: flashState.isFlashing(),
applicationSessionUuid,
});
return;
}
// Don't close window while flashing
event.returnValue = false;
// Don't open any more popups
popupExists = true;
analytics.logEvent('Close attempt while flashing', {
applicationSessionUuid,
flashingWorkflowUuid,
});
try {
const confirmed = await osDialog.showWarning({
confirmationLabel: 'Yes, quit',
rejectionLabel: 'Cancel',
title: 'Are you sure you want to close Etcher?',
description: messages.warning.exitWhileFlashing(),
});
if (confirmed) {
analytics.logEvent('Close confirmed while flashing', {
flashInstanceUuid: flashState.getFlashUuid(),
applicationSessionUuid,
flashingWorkflowUuid,
});
// This circumvents the 'beforeunload' event unlike
// electron.remote.app.quit() which does not.
electron.remote.process.exit(EXIT_CODES.SUCCESS);
}
analytics.logEvent('Close rejected while flashing', {
applicationSessionUuid,
flashingWorkflowUuid,
});
popupExists = false;
} catch (error) {
exceptionReporter.report(error);
}
});
function extendLock() {
updateLock.extend();
}
window.addEventListener('click', extendLock);
window.addEventListener('touchstart', extendLock);
// Initial update lock acquisition
extendLock();
async function main(): Promise<void> {
try {
await settings.load();
} catch (error) {
exceptionReporter.report(error);
}
BLACKLISTED_DRIVES = settings.get('driveBlacklist') || [];
ledsInit();
ReactDOM.render(
React.createElement(MainPage),
document.getElementById('main'),
);
}
main();

View File

@@ -0,0 +1,292 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Drive as DrivelistDrive } from 'drivelist';
import * as _ from 'lodash';
import * as React from 'react';
import { Modal } from 'rendition';
import {
COMPATIBILITY_STATUS_TYPES,
getDriveImageCompatibilityStatuses,
hasListDriveImageCompatibilityStatus,
isDriveValid,
} from '../../../../shared/drive-constraints';
import { bytesToClosestUnit } from '../../../../shared/units';
import { getDrives, hasAvailableDrives } from '../../models/available-drives';
import * as selectionState from '../../models/selection-state';
import { store } from '../../models/store';
import * as analytics from '../../modules/analytics';
import { open as openExternal } from '../../os/open-external/services/open-external';
/**
* @summary Determine if we can change a drive's selection state
*/
function shouldChangeDriveSelectionState(drive: DrivelistDrive) {
return isDriveValid(drive, selectionState.getImage());
}
/**
* @summary Toggle a drive selection
*/
function toggleDrive(drive: DrivelistDrive) {
const canChangeDriveSelectionState = shouldChangeDriveSelectionState(drive);
if (canChangeDriveSelectionState) {
analytics.logEvent('Toggle drive', {
drive,
previouslySelected: selectionState.isDriveSelected(drive.device),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
selectionState.toggleDrive(drive.device);
}
}
/**
* @summary Get a drive's compatibility status object(s)
*
* @description
* Given a drive, return its compatibility status with the selected image,
* containing the status type (ERROR, WARNING), and accompanying
* status message.
*/
function getDriveStatuses(
drive: DrivelistDrive,
): Array<{ type: number; message: string }> {
return getDriveImageCompatibilityStatuses(drive, selectionState.getImage());
}
function keyboardToggleDrive(
drive: DrivelistDrive,
event: React.KeyboardEvent<HTMLDivElement>,
) {
const ENTER = 13;
const SPACE = 32;
if (_.includes([ENTER, SPACE], event.keyCode)) {
toggleDrive(drive);
}
}
interface DriverlessDrive {
link: string;
linkTitle: string;
linkMessage: string;
}
export function DriveSelectorModal({ close }: { close: () => void }) {
const defaultMissingDriversModalState: { drive?: DriverlessDrive } = {};
const [missingDriversModal, setMissingDriversModal] = React.useState(
defaultMissingDriversModalState,
);
const [drives, setDrives] = React.useState(getDrives());
React.useEffect(() => {
const unsubscribe = store.subscribe(() => {
setDrives(getDrives());
});
return unsubscribe;
});
/**
* @summary Prompt the user to install missing usbboot drivers
*/
function installMissingDrivers(drive: {
link: string;
linkTitle: string;
linkMessage: string;
}) {
if (drive.link) {
analytics.logEvent('Open driver link modal', {
url: drive.link,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
setMissingDriversModal({ drive });
}
}
/**
* @summary Select a drive and close the modal
*/
async function selectDriveAndClose(drive: DrivelistDrive) {
const canChangeDriveSelectionState = await shouldChangeDriveSelectionState(
drive,
);
if (canChangeDriveSelectionState) {
selectionState.selectDrive(drive.device);
analytics.logEvent('Drive selected (double click)', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
close();
}
}
const hasStatus = hasListDriveImageCompatibilityStatus(
selectionState.getSelectedDrives(),
selectionState.getImage(),
);
return (
<Modal
className="modal-drive-selector-modal"
title="Select a Drive"
done={close}
action="Continue"
style={{
padding: '20px 30px 11px 30px',
}}
primaryButtonProps={{
primary: !hasStatus,
warning: hasStatus,
}}
>
<div>
<ul
style={{
height: '250px',
overflowX: 'hidden',
overflowY: 'auto',
padding: '0',
}}
>
{_.map(drives, (drive, index) => {
return (
<li
key={`item-${drive.displayName}`}
className="list-group-item"
// @ts-ignore (FIXME: not a valid <li> attribute but used by css rule)
disabled={!isDriveValid(drive, selectionState.getImage())}
onDoubleClick={() => selectDriveAndClose(drive)}
onClick={() => toggleDrive(drive)}
>
{drive.icon && (
<img
className="list-group-item-section"
alt="Drive device type logo"
src={`../assets/${drive.icon}.svg`}
width="25"
height="30"
/>
)}
<div
className="list-group-item-section list-group-item-section-expanded"
tabIndex={15 + index}
onKeyPress={evt => keyboardToggleDrive(drive, evt)}
>
<h6 className="list-group-item-heading">
{drive.description}
{drive.size && (
<span className="word-keep">
{' '}
- {bytesToClosestUnit(drive.size)}
</span>
)}
</h6>
{!drive.link && (
<p className="list-group-item-text">{drive.displayName}</p>
)}
{drive.link && (
<p className="list-group-item-text">
{drive.displayName} -{' '}
<b>
<a onClick={() => installMissingDrivers(drive)}>
{drive.linkCTA}
</a>
</b>
</p>
)}
<footer className="list-group-item-footer">
{_.map(getDriveStatuses(drive), (status, idx) => {
const className = {
[COMPATIBILITY_STATUS_TYPES.WARNING]: 'label-warning',
[COMPATIBILITY_STATUS_TYPES.ERROR]: 'label-danger',
};
return (
<span
key={`${drive.displayName}-status-${idx}`}
className={`label ${className[status.type]}`}
>
{status.message}
</span>
);
})}
</footer>
{Boolean(drive.progress) && (
<progress
className="drive-init-progress"
value={drive.progress}
max="100"
></progress>
)}
</div>
{isDriveValid(drive, selectionState.getImage()) && (
<span
className="list-group-item-section tick tick--success"
// @ts-ignore (FIXME: not a valid <span> attribute but used by css rule)
disabled={!selectionState.isDriveSelected(drive.device)}
></span>
)}
</li>
);
})}
{!hasAvailableDrives() && (
<li className="list-group-item">
<div>
<b>Connect a drive!</b>
<div>No removable drive detected.</div>
</div>
</li>
)}
</ul>
</div>
{missingDriversModal.drive !== undefined && (
<Modal
width={400}
title={missingDriversModal.drive.linkTitle}
cancel={() => setMissingDriversModal({})}
done={() => {
try {
if (missingDriversModal.drive !== undefined) {
openExternal(missingDriversModal.drive.link);
}
} catch (error) {
analytics.logException(error);
} finally {
setMissingDriversModal({});
}
}}
action={'Yes, continue'}
cancelButtonProps={{
children: 'Cancel',
}}
children={
missingDriversModal.drive.linkMessage ||
`Etcher will open ${missingDriversModal.drive.link} in your browser`
}
></Modal>
)}
</Modal>
);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 resin.io
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/
.modal-drive-selector-modal .modal-content {
width: 300px;
width: 315px;
height: 320px;
}
@@ -30,7 +30,7 @@
.modal-drive-selector-modal {
.list-group-item-footer {
.list-group-item-footer:has(span) {
margin-top: 8px;
}
@@ -52,12 +52,19 @@
border-color: darken($palette-theme-light-background, 7%);
padding: 12px 0;
> .tick {
font-size: 11px;
.list-group-item-section-expanded {
flex-grow: 1;
margin-left: 15px;
}
:first-child {
flex-grow: 1;
.list-group-item-section + .list-group-item-section {
margin-left: 10px;
display: inline-block;
vertical-align: middle;
}
> .tick {
font-size: 11px;
}
&:first-child {
@@ -67,6 +74,26 @@
&[disabled] .list-group-item-heading {
color: $palette-theme-light-soft-foreground;
}
.drive-init-progress {
appearance: none;
width: 100%;
height: 2.5px;
border: none;
border-radius: 50% 50%;
}
.drive-init-progress::-webkit-progress-bar {
background-color: $palette-theme-default-background;
border: none;
outline: none;
}
.drive-init-progress::-webkit-progress-value {
border-bottom: 1px solid darken($palette-theme-primary-background, 15);
background-color: $palette-theme-primary-background;
}
}
.list-group-item-heading {
@@ -78,5 +105,9 @@
font-size: 11px;
color: $palette-theme-light-soft-foreground;
}
.word-keep {
word-break: keep-all;
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Drive as DrivelistDrive } from 'drivelist';
import * as _ from 'lodash';
import * as React from 'react';
import { Txt } from 'rendition';
import { default as styled } from 'styled-components';
import {
getDriveImageCompatibilityStatuses,
Image,
} from '../../../../shared/drive-constraints';
import { bytesToClosestUnit } from '../../../../shared/units';
import { getSelectedDrives } from '../../models/selection-state';
import {
ChangeButton,
DetailsText,
StepButton,
StepNameButton,
} from '../../styled-components';
import { middleEllipsis } from '../../utils/middle-ellipsis';
const TargetDetail = styled(props => <Txt.span {...props}></Txt.span>)`
float: ${({ float }) => float};
`;
interface TargetSelectorProps {
targets: any[];
disabled: boolean;
openDriveSelector: () => any;
reselectDrive: () => any;
flashing: boolean;
show: boolean;
tooltip: string;
image: Image;
}
function DriveCompatibilityWarning(props: {
drive: DrivelistDrive;
image: Image;
}) {
const compatibilityWarnings = getDriveImageCompatibilityStatuses(
props.drive,
props.image,
);
if (compatibilityWarnings.length === 0) {
return null;
}
const messages = _.map(compatibilityWarnings, 'message');
return (
<Txt.span
className="glyphicon glyphicon-exclamation-sign"
ml={2}
tooltip={messages.join(', ')}
/>
);
}
export function TargetSelector(props: TargetSelectorProps) {
const targets = getSelectedDrives();
if (targets.length === 1) {
const target = targets[0];
return (
<>
<StepNameButton plain tooltip={props.tooltip}>
{middleEllipsis(target.description, 20)}
</StepNameButton>
{!props.flashing && (
<ChangeButton plain mb={14} onClick={props.reselectDrive}>
Change
</ChangeButton>
)}
<DetailsText>
<DriveCompatibilityWarning drive={target} image={props.image} />
{bytesToClosestUnit(target.size)}
</DetailsText>
</>
);
}
if (targets.length > 1) {
const targetsTemplate = [];
for (const target of targets) {
targetsTemplate.push(
<DetailsText
key={target.device}
tooltip={`${target.description} ${
target.displayName
} ${bytesToClosestUnit(target.size)}`}
px={21}
>
<Txt.span>
<DriveCompatibilityWarning drive={target} image={props.image} />
<TargetDetail float="left">
{middleEllipsis(target.description, 14)}
</TargetDetail>
<TargetDetail float="right">
{bytesToClosestUnit(target.size)}
</TargetDetail>
</Txt.span>
</DetailsText>,
);
}
return (
<>
<StepNameButton plain tooltip={props.tooltip}>
{targets.length} Targets
</StepNameButton>
{!props.flashing && (
<ChangeButton plain onClick={props.reselectDrive} mb={14}>
Change
</ChangeButton>
)}
{targetsTemplate}
</>
);
}
return (
<StepButton
tabindex={targets.length > 0 ? -1 : 2}
disabled={props.disabled}
onClick={props.openDriveSelector}
>
Select target
</StepButton>
);
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as React from 'react';
import * as settings from '../../models/settings';
import * as analytics from '../../modules/analytics';
import { SafeWebview } from '../safe-webview/safe-webview';
interface FeaturedProjectProps {
onWebviewShow: (isWebviewShowing: boolean) => void;
}
interface FeaturedProjectState {
endpoint: string | null;
}
export class FeaturedProject extends React.Component<
FeaturedProjectProps,
FeaturedProjectState
> {
constructor(props: FeaturedProjectProps) {
super(props);
this.state = { endpoint: null };
}
public componentDidMount() {
try {
const endpoint =
settings.get('featuredProjectEndpoint') ||
'https://assets.balena.io/etcher-featured/index.html';
this.setState({ endpoint });
} catch (error) {
analytics.logException(error);
}
}
public render() {
return this.state.endpoint ? (
<SafeWebview src={this.state.endpoint} {...this.props}></SafeWebview>
) : null;
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _ from 'lodash';
import * as React from 'react';
import * as uuidV4 from 'uuid/v4';
import * as messages from '../../../../shared/messages';
import * as flashState from '../../models/flash-state';
import * as selectionState from '../../models/selection-state';
import { store } from '../../models/store';
import * as analytics from '../../modules/analytics';
import { updateLock } from '../../modules/update-lock';
import { open as openExternal } from '../../os/open-external/services/open-external';
import { FlashAnother } from '../flash-another/flash-another';
import { FlashResults } from '../flash-results/flash-results';
import { SVGIcon } from '../svg-icon/svg-icon';
const restart = (options: any, goToMain: () => void) => {
const {
applicationSessionUuid,
flashingWorkflowUuid,
} = store.getState().toJS();
if (!options.preserveImage) {
selectionState.deselectImage();
}
selectionState.deselectAllDrives();
analytics.logEvent('Restart', {
...options,
applicationSessionUuid,
flashingWorkflowUuid,
});
// Re-enable lock release on inactivity
updateLock.resume();
// Reset the flashing workflow uuid
store.dispatch({
type: 'SET_FLASHING_WORKFLOW_UUID',
data: uuidV4(),
});
goToMain();
};
const formattedErrors = () => {
const errors = _.map(
_.get(flashState.getFlashResults(), ['results', 'errors']),
error => {
return `${error.device}: ${error.message || error.code}`;
},
);
return errors.join('\n');
};
function FinishPage({ goToMain }: { goToMain: () => void }) {
// @ts-ignore
const results = flashState.getFlashResults().results || {};
const progressMessage = messages.progress;
return (
<div className="page-finish row around-xs">
<div className="col-xs">
<div className="box center">
<FlashResults
results={results}
message={progressMessage}
errors={formattedErrors}
></FlashResults>
<FlashAnother
onClick={(options: any) => restart(options, goToMain)}
></FlashAnother>
</div>
<div className="box center">
<div className="fallback-banner">
<div className="caption caption-big">
Thanks for using
<span
style={{ cursor: 'pointer' }}
onClick={() =>
openExternal(
'https://balena.io/etcher?ref=etcher_offline_banner',
)
}
>
<SVGIcon
paths={['../../assets/etcher.svg']}
width="165px"
height="auto"
></SVGIcon>
</span>
</div>
<div className="caption caption-small fallback-footer">
made with
<SVGIcon
paths={['../../assets/love.svg']}
width="auto"
height="20px"
></SVGIcon>
by
<span
style={{ cursor: 'pointer' }}
onClick={() =>
openExternal('https://balena.io?ref=etcher_success')
}
>
<SVGIcon
paths={['../../assets/balena.svg']}
width="auto"
height="20px"
></SVGIcon>
</span>
</div>
</div>
</div>
</div>
</div>
);
}
export default FinishPage;

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as React from 'react';
import styled from 'styled-components';
import { position, right } from 'styled-system';
import { BaseButton, ThemedProvider } from '../../styled-components';
const Div = styled.div<any>`
${position}
${right}
`;
export interface FlashAnotherProps {
onClick: (options: { preserveImage: boolean }) => void;
}
export const FlashAnother = (props: FlashAnotherProps) => {
return (
<ThemedProvider>
<Div position="absolute" right="152px">
<BaseButton
primary
onClick={props.onClick.bind(null, { preserveImage: true })}
>
Flash Another
</BaseButton>
</Div>
</ThemedProvider>
);
};

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _ from 'lodash';
import * as React from 'react';
import styled from 'styled-components';
import { left, position, space, top } from 'styled-system';
import { Underline } from '../../styled-components';
const Div: any = styled.div<any>`
${position}
${top}
${left}
${space}
`;
export const FlashResults: any = ({
errors,
results,
message,
}: {
errors: () => string;
results: any;
message: any;
}) => {
return (
<Div position="absolute" left="153px" top="66px">
<div className="inline-flex title">
<span className="tick tick--success space-right-medium"></span>
<h3>Flash Complete!</h3>
</div>
<Div className="results" mt="11px" mr="0" mb="0" ml="40px">
<Underline tooltip={errors()}>
{_.map(results.devices, (quantity, type) => {
return quantity ? (
<div
key={type}
className={`target-status-line target-status-${type}`}
>
<span className="target-status-dot"></span>
<span className="target-status-quantity">{quantity}</span>
<span className="target-status-message">
{message[type](quantity)}
</span>
</div>
) : null;
})}
</Underline>
</Div>
</Div>
);
};

View File

@@ -0,0 +1,420 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as sdk from 'etcher-sdk';
import * as _ from 'lodash';
import { GPTPartition, MBRPartition } from 'partitioninfo';
import * as path from 'path';
import * as React from 'react';
import { Modal } from 'rendition';
import { default as styled } from 'styled-components';
import * as errors from '../../../../shared/errors';
import * as messages from '../../../../shared/messages';
import * as supportedFormats from '../../../../shared/supported-formats';
import * as shared from '../../../../shared/units';
import * as selectionState from '../../models/selection-state';
import { observe, store } from '../../models/store';
import * as analytics from '../../modules/analytics';
import * as exceptionReporter from '../../modules/exception-reporter';
import * as osDialog from '../../os/dialog';
import { replaceWindowsNetworkDriveLetter } from '../../os/windows-network-drives';
import {
ChangeButton,
DetailsText,
Footer,
StepButton,
StepNameButton,
StepSelection,
Underline,
} from '../../styled-components';
import { middleEllipsis } from '../../utils/middle-ellipsis';
import { SVGIcon } from '../svg-icon/svg-icon';
// TODO move these styles to rendition
const ModalText = styled.p`
a {
color: rgb(0, 174, 239);
&:hover {
color: rgb(0, 139, 191);
}
}
`;
const mainSupportedExtensions = _.intersection(
['img', 'iso', 'zip'],
supportedFormats.getAllExtensions(),
);
const extraSupportedExtensions = _.difference(
supportedFormats.getAllExtensions(),
mainSupportedExtensions,
).sort();
function getState() {
return {
hasImage: selectionState.hasImage(),
imageName: selectionState.getImageName(),
imageSize: selectionState.getImageSize(),
};
}
interface ImageSelectorProps {
flashing: boolean;
}
interface ImageSelectorState {
hasImage: boolean;
imageName: string;
imageSize: number;
warning: { message: string; title: string | null } | null;
showImageDetails: boolean;
}
export class ImageSelector extends React.Component<
ImageSelectorProps,
ImageSelectorState
> {
private unsubscribe: () => void;
constructor(props: ImageSelectorProps) {
super(props);
this.state = {
...getState(),
warning: null,
showImageDetails: false,
};
this.openImageSelector = this.openImageSelector.bind(this);
this.reselectImage = this.reselectImage.bind(this);
this.onDrop = this.onDrop.bind(this);
this.showSelectedImageDetails = this.showSelectedImageDetails.bind(this);
}
public componentDidMount() {
this.unsubscribe = observe(() => {
this.setState(getState());
});
}
public componentWillUnmount() {
this.unsubscribe();
}
private reselectImage() {
analytics.logEvent('Reselect image', {
previousImage: selectionState.getImage(),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
this.openImageSelector();
}
private selectImage(
image: sdk.sourceDestination.Metadata & {
path: string;
extension: string;
hasMBR: boolean;
},
) {
if (!supportedFormats.isSupportedImage(image.path)) {
const invalidImageError = errors.createUserError({
title: 'Invalid image',
description: messages.error.invalidImage(image.path),
});
osDialog.showError(invalidImageError);
analytics.logEvent(
'Invalid image',
_.merge(
{
applicationSessionUuid: store.getState().toJS()
.applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
},
image,
),
);
return;
}
try {
let message = null;
let title = null;
if (supportedFormats.looksLikeWindowsImage(image.path)) {
analytics.logEvent('Possibly Windows image', {
image,
applicationSessionUuid: store.getState().toJS()
.applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
message = messages.warning.looksLikeWindowsImage();
title = 'Possible Windows image detected';
} else if (!image.hasMBR) {
analytics.logEvent('Missing partition table', {
image,
applicationSessionUuid: store.getState().toJS()
.applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
title = 'Missing partition table';
message = messages.warning.missingPartitionTable();
}
if (message) {
this.setState({
warning: {
message,
title,
},
});
}
selectionState.selectImage(image);
analytics.logEvent('Select image', {
// An easy way so we can quickly identify if we're making use of
// certain features without printing pages of text to DevTools.
image: {
...image,
logo: Boolean(image.logo),
blockMap: Boolean(image.blockMap),
},
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
} catch (error) {
exceptionReporter.report(error);
}
}
private async selectImageByPath(imagePath: string) {
try {
imagePath = await replaceWindowsNetworkDriveLetter(imagePath);
} catch (error) {
analytics.logException(error);
}
if (!supportedFormats.isSupportedImage(imagePath)) {
const invalidImageError = errors.createUserError({
title: 'Invalid image',
description: messages.error.invalidImage(imagePath),
});
osDialog.showError(invalidImageError);
analytics.logEvent('Invalid image', { path: imagePath });
return;
}
const source = new sdk.sourceDestination.File(
imagePath,
sdk.sourceDestination.File.OpenFlags.Read,
);
try {
const innerSource = await source.getInnerSource();
const metadata = (await innerSource.getMetadata()) as sdk.sourceDestination.Metadata & {
hasMBR: boolean;
partitions: MBRPartition[] | GPTPartition[];
path: string;
extension: string;
};
const partitionTable = await innerSource.getPartitionTable();
if (partitionTable) {
metadata.hasMBR = true;
metadata.partitions = partitionTable.partitions;
} else {
metadata.hasMBR = false;
}
metadata.path = imagePath;
metadata.extension = path.extname(imagePath).slice(1);
this.selectImage(metadata);
} catch (error) {
const imageError = errors.createUserError({
title: 'Error opening image',
description: messages.error.openImage(
path.basename(imagePath),
error.message,
),
});
osDialog.showError(imageError);
analytics.logException(error);
} finally {
try {
await source.close();
} catch (error) {
// Noop
}
}
}
private async openImageSelector() {
analytics.logEvent('Open image selector', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
try {
const imagePath = await osDialog.selectImage();
// Avoid analytics and selection state changes
// if no file was resolved from the dialog.
if (!imagePath) {
analytics.logEvent('Image selector closed', {
applicationSessionUuid: store.getState().toJS()
.applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
return;
}
this.selectImageByPath(imagePath);
} catch (error) {
exceptionReporter.report(error);
}
}
private onDrop(event: React.DragEvent<HTMLDivElement>) {
const [file] = event.dataTransfer.files;
if (file) {
this.selectImageByPath(file.path);
}
}
private onDragOver(event: React.DragEvent<HTMLDivElement>) {
// Needed to get onDrop events on div elements
event.preventDefault();
}
private onDragEnter(event: React.DragEvent<HTMLDivElement>) {
// Needed to get onDrop events on div elements
event.preventDefault();
}
private showSelectedImageDetails() {
analytics.logEvent('Show selected image tooltip', {
imagePath: selectionState.getImagePath(),
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
});
this.setState({
showImageDetails: true,
});
}
// TODO add a visual change when dragging a file over the selector
public render() {
const { flashing } = this.props;
const { showImageDetails } = this.state;
const hasImage = selectionState.hasImage();
const imageBasename = hasImage
? path.basename(selectionState.getImagePath())
: '';
const imageName = selectionState.getImageName();
const imageSize = selectionState.getImageSize();
return (
<>
<div
className="box text-center relative"
onDrop={this.onDrop}
onDragEnter={this.onDragEnter}
onDragOver={this.onDragOver}
>
<div className="center-block">
<SVGIcon
contents={[selectionState.getImageLogo()]}
paths={['../../assets/image.svg']}
/>
</div>
<div className="space-vertical-large">
{hasImage ? (
<>
<StepNameButton
plain
onClick={this.showSelectedImageDetails}
tooltip={imageBasename}
>
{middleEllipsis(imageName || imageBasename, 20)}
</StepNameButton>
{!flashing && (
<ChangeButton plain mb={14} onClick={this.reselectImage}>
Change
</ChangeButton>
)}
<DetailsText>
{shared.bytesToClosestUnit(imageSize)}
</DetailsText>
</>
) : (
<StepSelection>
<StepButton onClick={this.openImageSelector}>
Select image
</StepButton>
<Footer>
{mainSupportedExtensions.join(', ')}, and{' '}
<Underline tooltip={extraSupportedExtensions.join(', ')}>
many more
</Underline>
</Footer>
</StepSelection>
)}
</div>
</div>
{this.state.warning != null && (
<Modal
titleElement={
<span>
<span
style={{ color: '#d9534f' }}
className="glyphicon glyphicon-exclamation-sign"
></span>{' '}
<span>{this.state.warning.title}</span>
</span>
}
action="Continue"
cancel={() => {
this.setState({ warning: null });
this.reselectImage();
}}
done={() => {
this.setState({ warning: null });
}}
primaryButtonProps={{ warning: true, primary: false }}
>
<ModalText
dangerouslySetInnerHTML={{ __html: this.state.warning.message }}
/>
</Modal>
)}
{showImageDetails && (
<Modal
title="Image File Name"
done={() => {
this.setState({ showImageDetails: false });
}}
>
{selectionState.getImagePath()}
</Modal>
)}
</>
);
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as Color from 'color';
import * as React from 'react';
import { ProgressBar } from 'rendition';
import { css, default as styled, keyframes } from 'styled-components';
import { StepButton, StepSelection } from '../../styled-components';
import { colors } from '../../theme';
const darkenForegroundStripes = 0.18;
const desaturateForegroundStripes = 0.2;
const progressButtonStripesForegroundColor = Color(colors.primary.background)
.darken(darkenForegroundStripes)
.desaturate(desaturateForegroundStripes)
.string();
const desaturateBackgroundStripes = 0.05;
const progressButtonStripesBackgroundColor = Color(colors.primary.background)
.desaturate(desaturateBackgroundStripes)
.string();
const ProgressButtonStripes = keyframes`
0% {
background-position: 0 0;
}
100% {
background-position: 20px 20px;
}
`;
const ProgressButtonStripesRule = css`
${ProgressButtonStripes} 1s linear infinite;
`;
const FlashProgressBar = styled(ProgressBar)`
> div {
width: 200px;
height: 48px;
color: white !important;
text-shadow: none !important;
}
width: 200px;
height: 48px;
font-size: 16px;
line-height: 48px;
background: ${Color(colors.warning.background)
.darken(darkenForegroundStripes)
.string()};
`;
const FlashProgressBarValidating = styled(FlashProgressBar)`
// Notice that we add 0.01 to certain gradient stop positions.
// That workarounds a Chrome rendering issue where diagonal
// lines look spiky.
// See https://github.com/balena-io/etcher/issues/472
background-image: -webkit-gradient(
linear,
0 0,
100% 100%,
color-stop(0.25, ${progressButtonStripesForegroundColor}),
color-stop(0.26, ${progressButtonStripesBackgroundColor}),
color-stop(0.5, ${progressButtonStripesBackgroundColor}),
color-stop(0.51, ${progressButtonStripesForegroundColor}),
color-stop(0.75, ${progressButtonStripesForegroundColor}),
color-stop(0.76, ${progressButtonStripesBackgroundColor}),
to(${progressButtonStripesBackgroundColor})
);
background-color: white;
animation: ${ProgressButtonStripesRule};
overflow: hidden;
background-size: 20px 20px;
`;
interface ProgressButtonProps {
striped: boolean;
active: boolean;
percentage: number;
label: string;
disabled: boolean;
callback: () => any;
}
/**
* Progress Button component
*/
export class ProgressButton extends React.Component<ProgressButtonProps> {
public render() {
if (this.props.active) {
if (this.props.striped) {
return (
<StepSelection>
<FlashProgressBarValidating
primary
emphasized
value={this.props.percentage}
>
{this.props.label}
</FlashProgressBarValidating>
</StepSelection>
);
}
return (
<StepSelection>
<FlashProgressBar warning emphasized value={this.props.percentage}>
{this.props.label}
</FlashProgressBar>
</StepSelection>
);
}
return (
<StepSelection>
<StepButton
onClick={this.props.callback}
disabled={this.props.disabled}
>
{this.props.label}
</StepButton>
</StepSelection>
);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as React from 'react';
import { default as styled } from 'styled-components';
import { color } from 'styled-system';
import { SVGIcon } from '../svg-icon/svg-icon';
const Div = styled.div`
position: absolute;
top: 45px;
left: 545px;
> span.step-name {
justify-content: flex-start;
> span {
margin-left: 10px;
}
> span:nth-child(2) {
font-weight: 500;
}
> span:nth-child(3) {
font-weight: 400;
font-style: italic;
}
}
.svg-icon[disabled] {
opacity: 0.4;
}
`;
const Span = styled.span`
${color}
`;
interface ReducedFlashingInfosProps {
imageLogo: string;
imageName: string;
imageSize: string;
driveTitle: string;
shouldShow: boolean;
}
export class ReducedFlashingInfos extends React.Component<
ReducedFlashingInfosProps
> {
constructor(props: ReducedFlashingInfosProps) {
super(props);
this.state = {};
}
public render() {
return this.props.shouldShow ? (
<Div>
<Span className="step-name">
<SVGIcon
disabled
contents={[this.props.imageLogo]}
paths={['../../assets/image.svg']}
width="20px"
></SVGIcon>
<Span>{this.props.imageName}</Span>
<Span color="#7e8085">{this.props.imageSize}</Span>
</Span>
<Span className="step-name">
<SVGIcon
disabled
paths={['../../assets/drive.svg']}
width="20px"
></SVGIcon>
<Span>{this.props.driveTitle}</Span>
</Span>
</Div>
) : null;
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright 2017 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as electron from 'electron';
import * as _ from 'lodash';
import * as React from 'react';
import * as packageJSON from '../../../../../package.json';
import * as settings from '../../models/settings';
import { store } from '../../models/store';
import * as analytics from '../../modules/analytics';
/**
* @summary Electron session identifier
*/
const ELECTRON_SESSION = 'persist:success-banner';
/**
* @summary Etcher version search-parameter key
*/
const ETCHER_VERSION_PARAM = 'etcher-version';
/**
* @summary API version search-parameter key
*/
const API_VERSION_PARAM = 'api-version';
/**
* @summary Opt-out analytics search-parameter key
*/
const OPT_OUT_ANALYTICS_PARAM = 'optOutAnalytics';
/**
* @summary Webview API version
*
* @description
* Changing this number represents a departure from an older API and as such
* should only be changed when truly necessary as it introduces breaking changes.
* This version number is exposed to the banner such that it can determine what
* features are safe to utilize.
*
* See `git blame -L n` where n is the line below for the history of version changes.
*/
const API_VERSION = '2';
interface SafeWebviewProps {
// The website source URL
src: string;
// @summary Refresh the webview
refreshNow?: boolean;
// Webview lifecycle event
onWebviewShow?: (isWebviewShowing: boolean) => void;
}
interface SafeWebviewState {
shouldShow: boolean;
}
/**
* @summary Webviews that hide/show depending on the HTTP status returned
*/
export class SafeWebview extends React.PureComponent<
SafeWebviewProps,
SafeWebviewState
> {
private entryHref: string;
private session: electron.Session;
private webviewRef: React.RefObject<electron.WebviewTag>;
constructor(props: SafeWebviewProps) {
super(props);
this.webviewRef = React.createRef();
this.state = {
shouldShow: true,
};
const url = new window.URL(this.props.src);
// We set the version GET parameters here.
url.searchParams.set(ETCHER_VERSION_PARAM, packageJSON.version);
url.searchParams.set(API_VERSION_PARAM, API_VERSION);
url.searchParams.set(
OPT_OUT_ANALYTICS_PARAM,
(!settings.get('errorReporting')).toString(),
);
this.entryHref = url.href;
// Events steal 'this'
this.didFailLoad = _.bind(this.didFailLoad, this);
this.didGetResponseDetails = _.bind(this.didGetResponseDetails, this);
// Make a persistent electron session for the webview
this.session = electron.remote.session.fromPartition(ELECTRON_SESSION, {
// Disable the cache for the session such that new content shows up when refreshing
cache: false,
});
}
private static logWebViewMessage(event: electron.ConsoleMessageEvent) {
console.log('Message from SafeWebview:', event.message);
}
public render() {
return (
<webview
ref={this.webviewRef}
partition={ELECTRON_SESSION}
style={{
flex: this.state.shouldShow ? undefined : '0 1',
width: this.state.shouldShow ? undefined : '0',
height: this.state.shouldShow ? undefined : '0',
}}
/>
);
}
// Add the Webview events
public componentDidMount() {
// Events React is unaware of have to be handled manually
if (this.webviewRef.current !== null) {
this.webviewRef.current.addEventListener(
'did-fail-load',
this.didFailLoad,
);
this.webviewRef.current.addEventListener(
'new-window',
SafeWebview.newWindow,
);
this.webviewRef.current.addEventListener(
'console-message',
SafeWebview.logWebViewMessage,
);
this.session.webRequest.onCompleted(this.didGetResponseDetails);
// It's important that this comes after the partition setting, otherwise it will
// use another session and we can't change it without destroying the element again
this.webviewRef.current.src = this.entryHref;
}
}
// Remove the Webview events
public componentWillUnmount() {
// Events that React is unaware of have to be handled manually
if (this.webviewRef.current !== null) {
this.webviewRef.current.removeEventListener(
'did-fail-load',
this.didFailLoad,
);
this.webviewRef.current.removeEventListener(
'new-window',
SafeWebview.newWindow,
);
this.webviewRef.current.removeEventListener(
'console-message',
SafeWebview.logWebViewMessage,
);
}
this.session.webRequest.onCompleted(null);
}
// Set the element state to hidden
public didFailLoad() {
this.setState({
shouldShow: false,
});
if (this.props.onWebviewShow) {
this.props.onWebviewShow(false);
}
}
// Set the element state depending on the HTTP response code
public didGetResponseDetails(event: electron.OnCompletedListenerDetails) {
// This seems to pick up all requests related to the webview,
// only care about this event if it's a request for the main frame
if (event.resourceType === 'mainFrame') {
const HTTP_OK = 200;
analytics.logEvent('SafeWebview loaded', {
event,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
this.setState({
shouldShow: event.statusCode === HTTP_OK,
});
if (this.props.onWebviewShow) {
this.props.onWebviewShow(event.statusCode === HTTP_OK);
}
}
}
// Open link in browser if it's opened as a 'foreground-tab'
public static newWindow(event: electron.NewWindowEvent) {
const url = new window.URL(event.url);
if (
_.every([
url.protocol === 'http:' || url.protocol === 'https:',
event.disposition === 'foreground-tab',
// Don't open links if they're disabled by the env var
!settings.get('disableExternalLinks'),
])
) {
electron.shell.openExternal(url.href);
}
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { faGithub } from '@fortawesome/free-brands-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import * as _ from 'lodash';
import * as os from 'os';
import * as React from 'react';
import { Badge, Checkbox, Modal } from 'rendition';
import styled from 'styled-components';
import { version } from '../../../../../package.json';
import * as settings from '../../models/settings';
import { store } from '../../models/store';
import * as analytics from '../../modules/analytics';
import { open as openExternal } from '../../os/open-external/services/open-external';
const { useState } = React;
const platform = os.platform();
interface WarningModalProps {
message: string;
confirmLabel: string;
cancel: () => void;
done: () => void;
}
const WarningModal = ({
message,
confirmLabel,
cancel,
done,
}: WarningModalProps) => {
return (
<Modal
title={confirmLabel}
action={confirmLabel}
cancel={cancel}
done={done}
style={{
width: 420,
height: 300,
}}
primaryButtonProps={{ warning: true }}
>
{message}
</Modal>
);
};
interface Setting {
name: string;
label: string | JSX.Element;
options?: any;
hide?: boolean;
}
const settingsList: Setting[] = [
{
name: 'errorReporting',
label: 'Anonymously report errors and usage statistics to balena.io',
},
{
name: 'unmountOnSuccess',
/**
* On Windows, "Unmounting" basically means "ejecting".
* On top of that, Windows users are usually not even
* familiar with the meaning of "unmount", which comes
* from the UNIX world.
*/
label: `${platform === 'win32' ? 'Eject' : 'Auto-unmount'} on success`,
},
{
name: 'validateWriteOnSuccess',
label: 'Validate write on success',
},
{
name: 'trim',
label: 'Trim ext{2,3,4} partitions before writing (raw images only)',
},
{
name: 'updatesEnabled',
label: 'Auto-updates enabled',
},
{
name: 'unsafeMode',
label: (
<span>
Unsafe mode{' '}
<Badge danger fontSize={12}>
Dangerous
</Badge>
</span>
),
options: {
description: `Are you sure you want to turn this on?
You will be able to overwrite your system drives if you're not careful.`,
confirmLabel: 'Enable unsafe mode',
},
hide: settings.get('disableUnsafeMode'),
},
];
interface SettingsModalProps {
toggleModal: (value: boolean) => void;
}
export const SettingsModal: any = styled(
({ toggleModal }: SettingsModalProps) => {
const [currentSettings, setCurrentSettings]: [
_.Dictionary<any>,
React.Dispatch<React.SetStateAction<_.Dictionary<any>>>,
] = useState(settings.getAll());
const [warning, setWarning]: [
any,
React.Dispatch<React.SetStateAction<any>>,
] = useState({});
const toggleSetting = async (setting: string, options?: any) => {
const value = currentSettings[setting];
const dangerous = !_.isUndefined(options);
analytics.logEvent('Toggle setting', {
setting,
value,
dangerous,
// @ts-ignore
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
});
if (value || !dangerous) {
await settings.set(setting, !value);
setCurrentSettings({
...currentSettings,
[setting]: !value,
});
setWarning({});
return;
}
// Show warning since it's a dangerous setting
setWarning({
setting,
settingValue: value,
...options,
});
};
return (
<Modal
id="settings-modal"
title="Settings"
done={() => toggleModal(false)}
style={{
width: 780,
height: 420,
}}
>
<div>
{_.map(settingsList, (setting: Setting, i: number) => {
return setting.hide ? null : (
<div key={setting.name}>
<Checkbox
toggle
tabIndex={6 + i}
label={setting.label}
checked={currentSettings[setting.name]}
onChange={() => toggleSetting(setting.name, setting.options)}
/>
</div>
);
})}
<div>
<span
onClick={() =>
openExternal(
'https://github.com/balena-io/etcher/blob/master/CHANGELOG.md',
)
}
>
<FontAwesomeIcon icon={faGithub} /> {version}
</span>
</div>
</div>
{_.isEmpty(warning) ? null : (
<WarningModal
message={warning.description}
confirmLabel={warning.confirmLabel}
done={() => {
settings.set(warning.setting, !warning.settingValue);
setCurrentSettings({
...currentSettings,
[warning.setting]: true,
});
setWarning({});
}}
cancel={() => {
setWarning({});
}}
/>
)}
</Modal>
);
},
)`
> div:nth-child(3) {
justify-content: center;
}
`;

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2018 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as fs from 'fs';
import * as _ from 'lodash';
import * as path from 'path';
import * as React from 'react';
import * as analytics from '../../modules/analytics';
const domParser = new window.DOMParser();
const DEFAULT_SIZE = '40px';
/**
* @summary Try to parse SVG contents and return it data encoded
*
* @param {String} contents - SVG XML contents
* @returns {String|null}
*
* @example
* const encodedSVG = tryParseSVGContents('<svg><path></path></svg>')
*
* img.src = encodedSVG
*/
function tryParseSVGContents(contents: string) {
const doc = domParser.parseFromString(contents, 'image/svg+xml');
const parserError = doc.querySelector('parsererror');
const svg = doc.querySelector('svg');
if (!parserError && svg) {
return `data:image/svg+xml,${encodeURIComponent(svg.outerHTML)}`;
}
return null;
}
interface SVGIconProps {
// Paths to SVG files to be tried in succession if any fails
paths: string[];
// List of embedded SVG contents to be tried in succession if any fails
contents?: string[];
// SVG image width unit
width?: string;
// SVG image height unit
height?: string;
// Should the element visually appear grayed out and disabled?
disabled?: boolean;
}
/**
* @summary SVG element that takes both filepaths and file contents
*/
export class SVGIcon extends React.Component<SVGIconProps> {
public render() {
// __dirname behaves strangely inside a Webpack bundle,
// so we need to provide different base directories
// depending on whether __dirname is absolute or not,
// which helps detecting a Webpack bundle.
// We use global.__dirname inside a Webpack bundle since
// that's the only way to get the "real" __dirname.
let baseDirectory: string;
if (path.isAbsolute(__dirname)) {
baseDirectory = path.join(__dirname, '..');
} else {
// @ts-ignore
baseDirectory = global.__dirname;
}
let svgData = '';
_.find(this.props.contents, content => {
const attempt = tryParseSVGContents(content);
if (attempt) {
svgData = attempt;
return true;
}
return false;
});
if (!svgData) {
_.find(this.props.paths, relativePath => {
// This means the path to the icon should be
// relative to *this directory*.
// TODO: There might be a way to compute the path
// relatively to the `index.html`.
const imagePath = path.join(baseDirectory, 'assets', relativePath);
const contents = _.attempt(() => {
return fs.readFileSync(imagePath, {
encoding: 'utf8',
});
});
if (_.isError(contents)) {
analytics.logException(contents);
return false;
}
const parsed = tryParseSVGContents(contents);
if (parsed) {
svgData = parsed;
return true;
}
return false;
});
}
const width = this.props.width || DEFAULT_SIZE;
const height = this.props.height || DEFAULT_SIZE;
return (
<img
className="svg-icon"
style={{
width,
height,
}}
src={svgData}
// @ts-ignore
disabled={this.props.disabled}
></img>
);
}
}

14
lib/gui/app/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Etcher</title>
<link rel="stylesheet" type="text/css" href="../../../node_modules/flexboxgrid/dist/flexboxgrid.css">
<link rel="stylesheet" type="text/css" href="../css/main.css">
<link rel="stylesheet" type="text/css" href="../css/desktop.css">
</head>
<body>
<main id="main"></main>
<script src="../../../generated/gui.js"></script>
</body>
</html>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 resin.io
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,10 +14,21 @@
* limitations under the License.
*/
.modal-warning-modal .modal-content {
width: 350px;
import * as _ from 'lodash';
import { Actions, store } from './store';
export function hasAvailableDrives() {
return !_.isEmpty(getDrives());
}
.modal-warning-modal .modal-title .glyphicon {
color: $palette-theme-danger-background;
export function setDrives(drives: any[]) {
store.dispatch({
type: Actions.SET_AVAILABLE_DRIVES,
data: drives,
});
}
export function getDrives(): any[] {
return store.getState().toJS().availableDrives;
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as sdk from 'etcher-sdk';
import * as _ from 'lodash';
import { bytesToMegabytes } from '../../../shared/units';
import { Actions, store } from './store';
/**
* @summary Reset flash state
*/
export function resetState() {
store.dispatch({
type: Actions.RESET_FLASH_STATE,
});
}
/**
* @summary Check if currently flashing
*/
export function isFlashing(): boolean {
return store.getState().toJS().isFlashing;
}
/**
* @summary Set the flashing flag
*
* @description
* The flag is used to signify that we're going to
* start a flash process.
*/
export function setFlashingFlag() {
store.dispatch({
type: Actions.SET_FLASHING_FLAG,
});
}
/**
* @summary Unset the flashing flag
*
* @description
* The flag is used to signify that the write process ended.
*/
export function unsetFlashingFlag(results: {
cancelled?: boolean;
sourceChecksum?: string;
errorCode?: string | number;
}) {
store.dispatch({
type: Actions.UNSET_FLASHING_FLAG,
data: results,
});
}
/**
* @summary Set the flashing state
*/
export function setProgressState(
state: sdk.multiWrite.MultiDestinationProgress,
) {
// Preserve only one decimal place
const PRECISION = 1;
const data = _.assign({}, state, {
percentage:
state.percentage !== undefined && _.isFinite(state.percentage)
? Math.floor(state.percentage)
: undefined,
speed: _.attempt(() => {
if (_.isFinite(state.speed)) {
return _.round(bytesToMegabytes(state.speed), PRECISION);
}
return null;
}),
totalSpeed: _.attempt(() => {
if (_.isFinite(state.totalSpeed)) {
return _.round(bytesToMegabytes(state.totalSpeed), PRECISION);
}
return null;
}),
});
store.dispatch({
type: Actions.SET_FLASH_STATE,
data,
});
}
export function getFlashResults() {
return store.getState().toJS().flashResults;
}
export function getFlashState() {
return store
.getState()
.get('flashState')
.toJS();
}
export function wasLastFlashCancelled() {
return _.get(getFlashResults(), ['cancelled'], false);
}
export function getLastFlashSourceChecksum(): string {
return getFlashResults().sourceChecksum;
}
export function getLastFlashErrorCode() {
return getFlashResults().errorCode;
}
export function getFlashUuid() {
return store.getState().toJS().flashUuid;
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2020 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
AnimationFunction,
blinkWhite,
breatheGreen,
Color,
RGBLed,
} from 'sys-class-rgb-led';
import * as settings from './settings';
import { observe } from './store';
const leds: Map<string, RGBLed> = new Map();
function setLeds(
drivesPaths: Set<string>,
colorOrAnimation: Color | AnimationFunction,
) {
for (const path of drivesPaths) {
const led = leds.get(path);
if (led) {
if (Array.isArray(colorOrAnimation)) {
led.setStaticColor(colorOrAnimation);
} else {
led.setAnimation(colorOrAnimation);
}
}
}
}
export function updateLeds(
availableDrives: string[],
selectedDrives: string[],
) {
const off = new Set(leds.keys());
const available = new Set(availableDrives);
const selected = new Set(selectedDrives);
for (const s of selected) {
available.delete(s);
}
for (const a of available) {
off.delete(a);
}
setLeds(off, [0, 0, 0]);
setLeds(available, breatheGreen);
setLeds(selected, blinkWhite);
}
interface DeviceFromState {
devicePath?: string;
device: string;
}
export function init() {
// ledsMapping is something like:
// {
// 'platform-xhci-hcd.0.auto-usb-0:1.1.1:1.0-scsi-0:0:0:0': [
// 'led1_r',
// 'led1_g',
// 'led1_b',
// ],
// ...
// }
const ledsMapping: _.Dictionary<[string, string, string]> =
settings.get('ledsMapping') || {};
for (const [drivePath, ledsNames] of Object.entries(ledsMapping)) {
leds.set('/dev/disk/by-path/' + drivePath, new RGBLed(ledsNames));
}
observe(state => {
const availableDrives = state
.get('availableDrives')
.toJS()
.filter((d: DeviceFromState) => d.devicePath);
const availableDrivesPaths = availableDrives.map(
(d: DeviceFromState) => d.devicePath,
);
// like /dev/sda
const selectedDrivesDevices = state.getIn(['selection', 'devices']).toJS();
const selectedDrivesPaths = availableDrives
.filter((d: DeviceFromState) => selectedDrivesDevices.includes(d.device))
.map((d: DeviceFromState) => d.devicePath);
updateLeds(availableDrivesPaths, selectedDrivesPaths);
});
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2017 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as electron from 'electron';
import { promises as fs } from 'fs';
import * as path from 'path';
const JSON_INDENT = 2;
/**
* @summary Userdata directory path
* @description
* Defaults to the following:
* - `%APPDATA%/etcher` on Windows
* - `$XDG_CONFIG_HOME/etcher` or `~/.config/etcher` on Linux
* - `~/Library/Application Support/etcher` on macOS
* See https://electronjs.org/docs/api/app#appgetpathname
*
* NOTE: The ternary is due to this module being loaded both,
* Electron's main process and renderer process
*/
const USER_DATA_DIR = electron.app
? electron.app.getPath('userData')
: electron.remote.app.getPath('userData');
const CONFIG_PATH = path.join(USER_DATA_DIR, 'config.json');
async function readConfigFile(filename: string): Promise<any> {
let contents = '{}';
try {
contents = await fs.readFile(filename, { encoding: 'utf8' });
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}
try {
return JSON.parse(contents);
} catch (parseError) {
console.error(parseError);
return {};
}
}
async function writeConfigFile(filename: string, data: any): Promise<any> {
await fs.writeFile(filename, JSON.stringify(data, null, JSON_INDENT));
return data;
}
export async function readAll(): Promise<any> {
return await readConfigFile(CONFIG_PATH);
}
export async function writeAll(settings: any): Promise<any> {
return await writeConfigFile(CONFIG_PATH, settings);
}
export async function clear(): Promise<void> {
await fs.unlink(CONFIG_PATH);
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _ from 'lodash';
import * as availableDrives from './available-drives';
import { Actions, store } from './store';
/**
* @summary Select a drive by its device path
*/
export function selectDrive(driveDevice: string) {
store.dispatch({
type: Actions.SELECT_DRIVE,
data: driveDevice,
});
}
/**
* @summary Toggle drive selection
*/
export function toggleDrive(driveDevice: string) {
if (isDriveSelected(driveDevice)) {
deselectDrive(driveDevice);
} else {
selectDrive(driveDevice);
}
}
export function selectImage(image: any) {
store.dispatch({
type: Actions.SELECT_IMAGE,
data: image,
});
}
/**
* @summary Get all selected drives' devices
*/
export function getSelectedDevices(): string[] {
return store
.getState()
.getIn(['selection', 'devices'])
.toJS();
}
/**
* @summary Get all selected drive objects
*/
export function getSelectedDrives(): any[] {
const drives = availableDrives.getDrives();
return _.map(getSelectedDevices(), device => {
return _.find(drives, { device });
});
}
/**
* @summary Get the selected image
*/
export function getImage() {
return _.get(store.getState().toJS(), ['selection', 'image']);
}
export function getImagePath(): string {
return _.get(store.getState().toJS(), ['selection', 'image', 'path']);
}
export function getImageSize(): number {
return _.get(store.getState().toJS(), ['selection', 'image', 'size']);
}
export function getImageUrl(): string {
return _.get(store.getState().toJS(), ['selection', 'image', 'url']);
}
export function getImageName(): string {
return _.get(store.getState().toJS(), ['selection', 'image', 'name']);
}
export function getImageLogo(): string {
return _.get(store.getState().toJS(), ['selection', 'image', 'logo']);
}
export function getImageSupportUrl(): string {
return _.get(store.getState().toJS(), ['selection', 'image', 'supportUrl']);
}
export function getImageRecommendedDriveSize(): number {
return _.get(store.getState().toJS(), [
'selection',
'image',
'recommendedDriveSize',
]);
}
/**
* @summary Check if there is a selected drive
*/
export function hasDrive(): boolean {
return Boolean(getSelectedDevices().length);
}
/**
* @summary Check if there is a selected image
*/
export function hasImage(): boolean {
return Boolean(getImage());
}
/**
* @summary Remove drive from selection
*/
export function deselectDrive(driveDevice: string) {
store.dispatch({
type: Actions.DESELECT_DRIVE,
data: driveDevice,
});
}
export function deselectImage() {
store.dispatch({
type: Actions.DESELECT_IMAGE,
});
}
export function deselectAllDrives() {
_.each(getSelectedDevices(), deselectDrive);
}
/**
* @summary Clear selections
*/
export function clear() {
deselectImage();
deselectAllDrives();
}
/**
* @summary Check whether a given device is selected.
*/
export function isDriveSelected(driveDevice: string) {
if (!driveDevice) {
return false;
}
const selectedDriveDevices = getSelectedDevices();
return _.includes(selectedDriveDevices, driveDevice);
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _debug from 'debug';
import * as _ from 'lodash';
import * as packageJSON from '../../../../package.json';
import * as errors from '../../../shared/errors';
import * as localSettings from './local-settings';
const debug = _debug('etcher:models:settings');
// exported for tests
export const DEFAULT_SETTINGS: _.Dictionary<any> = {
unsafeMode: false,
errorReporting: true,
unmountOnSuccess: true,
validateWriteOnSuccess: true,
trim: false,
updatesEnabled:
packageJSON.updates.enabled &&
!_.includes(['rpm', 'deb'], packageJSON.packageType),
lastSleptUpdateNotifier: null,
lastSleptUpdateNotifierVersion: null,
desktopNotifications: true,
};
let settings = _.cloneDeep(DEFAULT_SETTINGS);
/**
* @summary Reset settings to their default values
*/
export async function reset(): Promise<void> {
debug('reset');
// TODO: Remove default settings from config file (?)
settings = _.cloneDeep(DEFAULT_SETTINGS);
return await localSettings.writeAll(settings);
}
/**
* @summary Extend the application state with the local settings
*/
export async function load(): Promise<void> {
debug('load');
const loadedSettings = await localSettings.readAll();
_.assign(settings, loadedSettings);
}
/**
* @summary Set a setting value
*/
export async function set(key: string, value: any): Promise<void> {
debug('set', key, value);
if (_.isNil(key)) {
throw errors.createError({
title: 'Missing setting key',
});
}
if (!_.isString(key)) {
throw errors.createError({
title: `Invalid setting key: ${key}`,
});
}
const previousValue = settings[key];
settings[key] = value;
try {
await localSettings.writeAll(settings);
} catch (error) {
// Revert to previous value if persisting settings failed
settings[key] = previousValue;
throw error;
}
}
/**
* @summary Get a setting value
*/
export function get(key: string): any {
return _.cloneDeep(_.get(settings, [key]));
}
/**
* @summary Check if setting value exists
*/
export function has(key: string): boolean {
return settings[key] != null;
}
/**
* @summary Get all setting values
*/
export function getAll() {
debug('getAll');
return _.cloneDeep(settings);
}

572
lib/gui/app/models/store.ts Normal file
View File

@@ -0,0 +1,572 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as Immutable from 'immutable';
import * as _ from 'lodash';
import * as redux from 'redux';
import * as uuidV4 from 'uuid/v4';
import * as constraints from '../../../shared/drive-constraints';
import * as errors from '../../../shared/errors';
import * as fileExtensions from '../../../shared/file-extensions';
import * as supportedFormats from '../../../shared/supported-formats';
import * as utils from '../../../shared/utils';
import * as settings from './settings';
/**
* @summary Verify and throw if any state fields are nil
*/
function verifyNoNilFields(
object: _.Dictionary<any>,
fields: string[],
name: string,
) {
const nilFields = _.filter(fields, field => {
return _.isNil(_.get(object, field));
});
if (nilFields.length) {
throw new Error(`Missing ${name} fields: ${nilFields.join(', ')}`);
}
}
/**
* @summary FLASH_STATE fields that can't be nil
*/
const flashStateNoNilFields = ['speed', 'totalSpeed'];
/**
* @summary SELECT_IMAGE fields that can't be nil
*/
const selectImageNoNilFields = ['path', 'extension'];
/**
* @summary Application default state
*/
const DEFAULT_STATE = Immutable.fromJS({
applicationSessionUuid: '',
flashingWorkflowUuid: '',
availableDrives: [],
selection: {
devices: Immutable.OrderedSet(),
},
isFlashing: false,
flashResults: {},
flashState: {
flashing: 0,
verifying: 0,
successful: 0,
failed: 0,
percentage: 0,
speed: null,
totalSpeed: null,
},
});
/**
* @summary Application supported action messages
*/
export enum Actions {
SET_AVAILABLE_DRIVES,
SET_FLASH_STATE,
RESET_FLASH_STATE,
SET_FLASHING_FLAG,
UNSET_FLASHING_FLAG,
SELECT_DRIVE,
SELECT_IMAGE,
DESELECT_DRIVE,
DESELECT_IMAGE,
SET_APPLICATION_SESSION_UUID,
SET_FLASHING_WORKFLOW_UUID,
}
interface Action {
type: Actions;
data: any;
}
/**
* @summary Get available drives from the state
*
* @param {Object} state - state object
* @returns {Object} new state
*/
function getAvailableDrives(state: typeof DEFAULT_STATE) {
return state.get('availableDrives').toJS();
}
/**
* @summary The redux store reducer
*/
function storeReducer(
state = DEFAULT_STATE,
action: Action,
): typeof DEFAULT_STATE {
switch (action.type) {
case Actions.SET_AVAILABLE_DRIVES: {
// Type: action.data : Array<DriveObject>
if (!action.data) {
throw errors.createError({
title: 'Missing drives',
});
}
let drives = action.data;
if (!_.isArray(drives) || !_.every(drives, _.isObject)) {
throw errors.createError({
title: `Invalid drives: ${drives}`,
});
}
drives = _.sortBy(drives, [
// Devices with no devicePath first (usbboot)
d => !!d.devicePath,
// Then sort by devicePath (only available on Linux with udev) or device
d => d.devicePath || d.device,
]);
const newState = state.set('availableDrives', Immutable.fromJS(drives));
const selectedDevices = newState.getIn(['selection', 'devices']).toJS();
// Remove selected drives that are stale, i.e. missing from availableDrives
const nonStaleNewState = _.reduce(
selectedDevices,
(accState, device) => {
// Check whether the drive still exists in availableDrives
if (
device &&
!_.find(drives, {
device,
})
) {
// Deselect this drive gone from availableDrives
return storeReducer(accState, {
type: Actions.DESELECT_DRIVE,
data: device,
});
}
return accState;
},
newState,
);
const shouldAutoselectAll = Boolean(
settings.get('disableExplicitDriveSelection'),
);
const AUTOSELECT_DRIVE_COUNT = 1;
const nonStaleSelectedDevices = nonStaleNewState
.getIn(['selection', 'devices'])
.toJS();
const hasSelectedDevices =
nonStaleSelectedDevices.length >= AUTOSELECT_DRIVE_COUNT;
const shouldAutoselectOne =
drives.length === AUTOSELECT_DRIVE_COUNT && !hasSelectedDevices;
if (shouldAutoselectOne || shouldAutoselectAll) {
// Even if there's no image selected, we need to call several
// drive/image related checks, and `{}` works fine with them
const image = state
.getIn(['selection', 'image'], Immutable.fromJS({}))
.toJS();
return _.reduce(
drives,
(accState, drive) => {
if (
_.every([
constraints.isDriveValid(drive, image),
constraints.isDriveSizeRecommended(drive, image),
// We don't want to auto-select large drives
!constraints.isDriveSizeLarge(drive),
// We don't want to auto-select system drives,
// even when "unsafe mode" is enabled
!constraints.isSystemDrive(drive),
]) ||
(shouldAutoselectAll && constraints.isDriveValid(drive, image))
) {
// Auto-select this drive
return storeReducer(accState, {
type: Actions.SELECT_DRIVE,
data: drive.device,
});
}
// Deselect this drive in case it still is selected
return storeReducer(accState, {
type: Actions.DESELECT_DRIVE,
data: drive.device,
});
},
nonStaleNewState,
);
}
return nonStaleNewState;
}
case Actions.SET_FLASH_STATE: {
// Type: action.data : FlashStateObject
if (!state.get('isFlashing')) {
throw errors.createError({
title: "Can't set the flashing state when not flashing",
});
}
verifyNoNilFields(action.data, flashStateNoNilFields, 'flash');
if (
!_.every(
_.pick(action.data, [
'flashing',
'verifying',
'successful',
'failed',
]),
_.isFinite,
)
) {
throw errors.createError({
title: 'State quantity field(s) not finite number',
});
}
if (
!_.isUndefined(action.data.percentage) &&
!utils.isValidPercentage(action.data.percentage)
) {
throw errors.createError({
title: `Invalid state percentage: ${action.data.percentage}`,
});
}
if (!_.isUndefined(action.data.eta) && !_.isNumber(action.data.eta)) {
throw errors.createError({
title: `Invalid state eta: ${action.data.eta}`,
});
}
return state.set('flashState', Immutable.fromJS(action.data));
}
case Actions.RESET_FLASH_STATE: {
return state
.set('isFlashing', false)
.set('flashState', DEFAULT_STATE.get('flashState'))
.set('flashResults', DEFAULT_STATE.get('flashResults'))
.delete('flashUuid');
}
case Actions.SET_FLASHING_FLAG: {
return state
.set('isFlashing', true)
.set('flashUuid', uuidV4())
.set('flashResults', DEFAULT_STATE.get('flashResults'));
}
case Actions.UNSET_FLASHING_FLAG: {
// Type: action.data : FlashResultsObject
if (!action.data) {
throw errors.createError({
title: 'Missing results',
});
}
_.defaults(action.data, {
cancelled: false,
});
if (!_.isBoolean(action.data.cancelled)) {
throw errors.createError({
title: `Invalid results cancelled: ${action.data.cancelled}`,
});
}
if (action.data.cancelled && action.data.sourceChecksum) {
throw errors.createError({
title:
"The sourceChecksum value can't exist if the flashing was cancelled",
});
}
if (
action.data.sourceChecksum &&
!_.isString(action.data.sourceChecksum)
) {
throw errors.createError({
title: `Invalid results sourceChecksum: ${action.data.sourceChecksum}`,
});
}
if (
action.data.errorCode &&
!_.isString(action.data.errorCode) &&
!_.isNumber(action.data.errorCode)
) {
throw errors.createError({
title: `Invalid results errorCode: ${action.data.errorCode}`,
});
}
return state
.set('isFlashing', false)
.set('flashResults', Immutable.fromJS(action.data))
.set('flashState', DEFAULT_STATE.get('flashState'));
}
case Actions.SELECT_DRIVE: {
// Type: action.data : String
const device = action.data;
if (!device) {
throw errors.createError({
title: 'Missing drive',
});
}
if (!_.isString(device)) {
throw errors.createError({
title: `Invalid drive: ${device}`,
});
}
const selectedDrive = _.find(getAvailableDrives(state), { device });
if (!selectedDrive) {
throw errors.createError({
title: `The drive is not available: ${device}`,
});
}
if (selectedDrive.isReadOnly) {
throw errors.createError({
title: 'The drive is write-protected',
});
}
const image = state.getIn(['selection', 'image']);
if (
image &&
!constraints.isDriveLargeEnough(selectedDrive, image.toJS())
) {
throw errors.createError({
title: 'The drive is not large enough',
});
}
const selectedDevices = state.getIn(['selection', 'devices']);
return state.setIn(['selection', 'devices'], selectedDevices.add(device));
}
// TODO(jhermsmeier): Consolidate these assertions
// with image-stream / supported-formats, and have *one*
// place where all the image extension / format handling
// takes place, to avoid having to check 2+ locations with different logic
case Actions.SELECT_IMAGE: {
// Type: action.data : ImageObject
verifyNoNilFields(action.data, selectImageNoNilFields, 'image');
if (!_.isString(action.data.path)) {
throw errors.createError({
title: `Invalid image path: ${action.data.path}`,
});
}
if (!_.isString(action.data.extension)) {
throw errors.createError({
title: `Invalid image extension: ${action.data.extension}`,
});
}
const extension = _.toLower(action.data.extension);
if (!_.includes(supportedFormats.getAllExtensions(), extension)) {
throw errors.createError({
title: `Invalid image extension: ${action.data.extension}`,
});
}
let lastImageExtension = fileExtensions.getLastFileExtension(
action.data.path,
);
lastImageExtension = _.isString(lastImageExtension)
? _.toLower(lastImageExtension)
: lastImageExtension;
if (lastImageExtension !== extension) {
if (!_.isString(action.data.archiveExtension)) {
throw errors.createError({
title: 'Missing image archive extension',
});
}
const archiveExtension = _.toLower(action.data.archiveExtension);
if (
!_.includes(supportedFormats.getAllExtensions(), archiveExtension)
) {
throw errors.createError({
title: `Invalid image archive extension: ${action.data.archiveExtension}`,
});
}
if (lastImageExtension !== archiveExtension) {
throw errors.createError({
title: `Image archive extension mismatch: ${action.data.archiveExtension} and ${lastImageExtension}`,
});
}
}
const MINIMUM_IMAGE_SIZE = 0;
if (action.data.size !== undefined) {
if (
action.data.size < MINIMUM_IMAGE_SIZE ||
!_.isInteger(action.data.size)
) {
throw errors.createError({
title: `Invalid image size: ${action.data.size}`,
});
}
}
if (!_.isUndefined(action.data.compressedSize)) {
if (
action.data.compressedSize < MINIMUM_IMAGE_SIZE ||
!_.isInteger(action.data.compressedSize)
) {
throw errors.createError({
title: `Invalid image compressed size: ${action.data.compressedSize}`,
});
}
}
if (action.data.url && !_.isString(action.data.url)) {
throw errors.createError({
title: `Invalid image url: ${action.data.url}`,
});
}
if (action.data.name && !_.isString(action.data.name)) {
throw errors.createError({
title: `Invalid image name: ${action.data.name}`,
});
}
if (action.data.logo && !_.isString(action.data.logo)) {
throw errors.createError({
title: `Invalid image logo: ${action.data.logo}`,
});
}
const selectedDevices = state.getIn(['selection', 'devices']);
// Remove image-incompatible drives from selection with `constraints.isDriveValid`
return _.reduce(
selectedDevices.toJS(),
(accState, device) => {
const drive = _.find(getAvailableDrives(state), { device });
if (
!constraints.isDriveValid(drive, action.data) ||
!constraints.isDriveSizeRecommended(drive, action.data)
) {
return storeReducer(accState, {
type: Actions.DESELECT_DRIVE,
data: device,
});
}
return accState;
},
state,
).setIn(['selection', 'image'], Immutable.fromJS(action.data));
}
case Actions.DESELECT_DRIVE: {
// Type: action.data : String
if (!action.data) {
throw errors.createError({
title: 'Missing drive',
});
}
if (!_.isString(action.data)) {
throw errors.createError({
title: `Invalid drive: ${action.data}`,
});
}
const selectedDevices = state.getIn(['selection', 'devices']);
// Remove drive from set in state
return state.setIn(
['selection', 'devices'],
selectedDevices.delete(action.data),
);
}
case Actions.DESELECT_IMAGE: {
return state.deleteIn(['selection', 'image']);
}
case Actions.SET_APPLICATION_SESSION_UUID: {
return state.set('applicationSessionUuid', action.data);
}
case Actions.SET_FLASHING_WORKFLOW_UUID: {
return state.set('flashingWorkflowUuid', action.data);
}
default: {
return state;
}
}
}
export const store = redux.createStore(storeReducer, DEFAULT_STATE);
/**
* @summary Observe the store for changes
* @param {Function} onChange - change handler
* @returns {Function} unsubscribe
*/
export function observe(onChange: (state: typeof DEFAULT_STATE) => void) {
let currentState: typeof DEFAULT_STATE | null = null;
/**
* @summary Internal change detection handler
*/
const changeHandler = () => {
const nextState = store.getState();
if (!_.isEqual(nextState, currentState)) {
currentState = nextState;
onChange(currentState);
}
};
changeHandler();
return store.subscribe(changeHandler);
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _ from 'lodash';
import * as resinCorvus from 'resin-corvus/browser';
import * as packageJSON from '../../../../package.json';
import { getConfig, hasProps } from '../../../shared/utils';
import * as settings from '../models/settings';
const sentryToken =
settings.get('analyticsSentryToken') ||
_.get(packageJSON, ['analytics', 'sentry', 'token']);
const mixpanelToken =
settings.get('analyticsMixpanelToken') ||
_.get(packageJSON, ['analytics', 'mixpanel', 'token']);
const configUrl =
settings.get('configUrl') || 'https://balena.io/etcher/static/config.json';
const DEFAULT_PROBABILITY = 0.1;
const services = {
sentry: sentryToken,
mixpanel: mixpanelToken,
};
resinCorvus.install({
services,
options: {
release: packageJSON.version,
shouldReport: () => {
return settings.get('errorReporting');
},
mixpanelDeferred: true,
},
});
let mixpanelSample = DEFAULT_PROBABILITY;
/**
* @summary Init analytics configurations
*/
async function initConfig() {
let validatedConfig = null;
try {
const config = await getConfig(configUrl);
const mixpanel = _.get(config, ['analytics', 'mixpanel'], {});
mixpanelSample = mixpanel.probability || DEFAULT_PROBABILITY;
if (isClientEligible(mixpanelSample)) {
validatedConfig = validateMixpanelConfig(mixpanel);
}
} catch (err) {
resinCorvus.logException(err);
}
resinCorvus.setConfigs({
mixpanel: validatedConfig,
});
}
initConfig();
/**
* @summary Check that the client is eligible for analytics
*/
function isClientEligible(probability: number) {
return Math.random() < probability;
}
/**
* @summary Check that config has at least HTTP_PROTOCOL and api_host
*/
function validateMixpanelConfig(config: {
api_host?: string;
HTTP_PROTOCOL?: string;
}) {
const mixpanelConfig = {
api_host: 'https://api.mixpanel.com',
};
if (hasProps(config, ['HTTP_PROTOCOL', 'api_host'])) {
mixpanelConfig.api_host = `${config.HTTP_PROTOCOL}://${config.api_host}`;
}
return mixpanelConfig;
}
/**
* @summary Log a debug message
*
* @description
* This function sends the debug message to error reporting services.
*/
export const logDebug = resinCorvus.logDebug;
/**
* @summary Log an event
*
* @description
* This function sends the debug message to product analytics services.
*/
export function logEvent(message: string, data: any) {
resinCorvus.logEvent(message, { ...data, sample: mixpanelSample });
}
/**
* @summary Log an exception
*
* @description
* This function logs an exception to error reporting services.
*/
export const logException = resinCorvus.logException;

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as sdk from 'etcher-sdk';
import { geteuid, platform } from 'process';
import * as settings from '../models/settings';
/**
* @summary returns true if system drives should be shown
*/
function includeSystemDrives() {
return settings.get('unsafeMode') && !settings.get('disableUnsafeMode');
}
const adapters: sdk.scanner.adapters.Adapter[] = [
new sdk.scanner.adapters.BlockDeviceAdapter(includeSystemDrives),
];
// Can't use permissions.isElevated() here as it returns a promise and we need to set
// module.exports = scanner right now.
if (platform !== 'linux' || geteuid() === 0) {
adapters.push(new sdk.scanner.adapters.UsbbootDeviceAdapter());
}
if (
platform === 'win32' &&
sdk.scanner.adapters.DriverlessDeviceAdapter !== undefined
) {
adapters.push(new sdk.scanner.adapters.DriverlessDeviceAdapter());
}
export const scanner = new sdk.scanner.Scanner(adapters);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 resin.io
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,16 @@
* limitations under the License.
*/
'use strict';
import { logException } from '../modules/analytics';
import { showError } from '../os/dialog';
/**
* @module Etcher.OS.Dropzone
* @summary Report an exception
*/
const angular = require('angular');
const MODULE_NAME = 'Etcher.OS.Dropzone';
const OSDropzone = angular.module(MODULE_NAME, []);
OSDropzone.directive('osDropzone', require('./directives/dropzone'));
module.exports = MODULE_NAME;
export function report(exception?: Error) {
if (exception === undefined) {
return;
}
showError(exception);
logException(exception);
}

View File

@@ -0,0 +1,353 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Drive as DrivelistDrive } from 'drivelist';
import * as electron from 'electron';
import * as sdk from 'etcher-sdk';
import * as _ from 'lodash';
import * as ipc from 'node-ipc';
import * as os from 'os';
import * as path from 'path';
import * as packageJSON from '../../../../package.json';
import * as errors from '../../../shared/errors';
import * as permissions from '../../../shared/permissions';
import * as flashState from '../models/flash-state';
import * as selectionState from '../models/selection-state';
import * as settings from '../models/settings';
import { store } from '../models/store';
import * as analytics from '../modules/analytics';
import * as windowProgress from '../os/window-progress';
import { updateLock } from './update-lock';
const THREADS_PER_CPU = 16;
// There might be multiple Etcher instances running at
// the same time, therefore we must ensure each IPC
// server/client has a different name.
const IPC_SERVER_ID = `etcher-server-${process.pid}`;
const IPC_CLIENT_ID = `etcher-client-${process.pid}`;
ipc.config.id = IPC_SERVER_ID;
ipc.config.socketRoot = path.join(
process.env.XDG_RUNTIME_DIR || os.tmpdir(),
path.sep,
);
// NOTE: Ensure this isn't disabled, as it will cause
// the stdout maxBuffer size to be exceeded when flashing
ipc.config.silent = true;
/**
* @summary Handle a flash error and log it to analytics
*/
function handleErrorLogging(
error: Error & { code: string },
analyticsData: any,
) {
const eventData = {
...analyticsData,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
flashInstanceUuid: flashState.getFlashUuid(),
};
if (error.code === 'EVALIDATION') {
analytics.logEvent('Validation error', eventData);
} else if (error.code === 'EUNPLUGGED') {
analytics.logEvent('Drive unplugged', eventData);
} else if (error.code === 'EIO') {
analytics.logEvent('Input/output error', eventData);
} else if (error.code === 'ENOSPC') {
analytics.logEvent('Out of space', eventData);
} else if (error.code === 'ECHILDDIED') {
analytics.logEvent('Child died unexpectedly', eventData);
} else {
analytics.logEvent('Flash error', {
...eventData,
error: errors.toJSON(error),
});
}
}
function terminateServer() {
// Turns out we need to destroy all sockets for
// the server to actually close. Otherwise, it
// just stops receiving any further connections,
// but remains open if there are active ones.
// @ts-ignore (no Server.sockets in @types/node-ipc)
for (const socket of ipc.server.sockets) {
socket.destroy();
}
ipc.server.stop();
}
function writerArgv(): string[] {
let entryPoint = electron.remote.app.getAppPath();
// AppImages run over FUSE, so the files inside the mount point
// can only be accessed by the user that mounted the AppImage.
// This means we can't re-spawn Etcher as root from the same
// mount-point, and as a workaround, we re-mount the original
// AppImage as root.
if (os.platform() === 'linux' && process.env.APPIMAGE && process.env.APPDIR) {
entryPoint = entryPoint.replace(process.env.APPDIR, '');
return [
process.env.APPIMAGE,
'-e',
`require(\`\${process.env.APPDIR}${entryPoint}\`)`,
];
} else {
return [process.argv[0], entryPoint];
}
}
function writerEnv() {
return {
IPC_SERVER_ID,
IPC_CLIENT_ID,
IPC_SOCKET_ROOT: ipc.config.socketRoot,
ELECTRON_RUN_AS_NODE: '1',
UV_THREADPOOL_SIZE: (os.cpus().length * THREADS_PER_CPU).toString(),
// This environment variable prevents the AppImages
// desktop integration script from presenting the
// "installation" dialog
SKIP: '1',
...(process.platform === 'win32' ? {} : process.env),
};
}
interface FlashResults {
cancelled?: boolean;
}
/**
* @summary Perform write operation
*
* @description
* This function is extracted for testing purposes.
*/
export function performWrite(
image: string,
drives: DrivelistDrive[],
onProgress: sdk.multiWrite.OnProgressFunction,
): Promise<{ cancelled?: boolean }> {
let cancelled = false;
ipc.serve();
return new Promise((resolve, reject) => {
ipc.server.on('error', error => {
terminateServer();
const errorObject = errors.fromJSON(error);
reject(errorObject);
});
ipc.server.on('log', message => {
console.log(message);
});
const flashResults: FlashResults = {};
const analyticsData = {
image,
drives,
driveCount: drives.length,
uuid: flashState.getFlashUuid(),
flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'),
};
ipc.server.on('fail', ({ error }) => {
handleErrorLogging(error, analyticsData);
});
ipc.server.on('done', event => {
event.results.errors = _.map(event.results.errors, data => {
return errors.fromJSON(data);
});
_.merge(flashResults, event);
});
ipc.server.on('abort', () => {
terminateServer();
cancelled = true;
});
// @ts-ignore
ipc.server.on('state', onProgress);
ipc.server.on('ready', (_data, socket) => {
ipc.server.emit(socket, 'write', {
imagePath: image,
destinations: drives,
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'),
unmountOnSuccess: settings.get('unmountOnSuccess'),
});
});
const argv = writerArgv();
ipc.server.on('start', async () => {
console.log(`Elevating command: ${_.join(argv, ' ')}`);
const env = writerEnv();
try {
const results = await permissions.elevateCommand(argv, {
applicationName: packageJSON.displayName,
environment: env,
});
flashResults.cancelled = cancelled || results.cancelled;
} catch (error) {
// This happens when the child is killed using SIGKILL
const SIGKILL_EXIT_CODE = 137;
if (error.code === SIGKILL_EXIT_CODE) {
error.code = 'ECHILDDIED';
}
reject(error);
} finally {
console.log('Terminating IPC server');
terminateServer();
}
console.log('Flash results', flashResults);
// This likely means the child died halfway through
if (
!flashResults.cancelled &&
!_.get(flashResults, ['results', 'bytesWritten'])
) {
reject(
errors.createUserError({
title: 'The writer process ended unexpectedly',
description:
'Please try again, and contact the Etcher team if the problem persists',
code: 'ECHILDDIED',
}),
);
return;
}
resolve(flashResults);
});
// Clear the update lock timer to prevent longer
// flashing timing it out, and releasing the lock
updateLock.pause();
ipc.server.start();
});
}
/**
* @summary Flash an image to drives
*/
export async function flash(
image: string,
drives: DrivelistDrive[],
): Promise<void> {
if (flashState.isFlashing()) {
throw new Error('There is already a flash in progress');
}
flashState.setFlashingFlag();
const analyticsData = {
image,
drives,
driveCount: drives.length,
uuid: flashState.getFlashUuid(),
status: 'started',
flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
};
analytics.logEvent('Flash', analyticsData);
try {
// Using it from exports so it can be mocked during tests
const result = await exports.performWrite(
image,
drives,
flashState.setProgressState,
);
flashState.unsetFlashingFlag(result);
} catch (error) {
flashState.unsetFlashingFlag({ cancelled: false, errorCode: error.code });
windowProgress.clear();
let { results } = flashState.getFlashResults();
results = results || {};
const eventData = {
...analyticsData,
errors: results.errors,
devices: results.devices,
status: 'failed',
error,
};
analytics.logEvent('Write failed', eventData);
throw error;
}
windowProgress.clear();
if (flashState.wasLastFlashCancelled()) {
const eventData = {
...analyticsData,
status: 'cancel',
};
analytics.logEvent('Elevation cancelled', eventData);
} else {
const { results } = flashState.getFlashResults();
const eventData = {
...analyticsData,
errors: results.errors,
devices: results.devices,
status: 'finished',
};
analytics.logEvent('Done', eventData);
}
}
/**
* @summary Cancel write operation
*/
export function cancel() {
const drives = selectionState.getSelectedDevices();
const analyticsData = {
image: selectionState.getImagePath(),
drives,
driveCount: drives.length,
uuid: flashState.getFlashUuid(),
flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
status: 'cancel',
};
analytics.logEvent('Cancel', analyticsData);
// Re-enable lock release on inactivity
updateLock.resume();
try {
// @ts-ignore (no Server.sockets in @types/node-ipc)
const [socket] = ipc.server.sockets;
if (socket !== undefined) {
ipc.server.emit(socket, 'cancel');
}
} catch (error) {
analytics.logException(error);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2017 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { bytesToClosestUnit } from '../../../shared/units';
import * as settings from '../models/settings';
export interface FlashState {
flashing: number;
verifying: number;
successful: number;
failed: number;
percentage?: number;
speed: number;
position: number;
}
/**
* @summary Make the progress status subtitle string
*
* @param {Object} state - flashing metadata
*
* @returns {String}
*
* @example
* const status = progressStatus.fromFlashState({
* flashing: 1,
* verifying: 0,
* successful: 0,
* failed: 0,
* percentage: 55,
* speed: 2049
* })
*
* console.log(status)
* // '55% Flashing'
*/
export function fromFlashState(state: FlashState): string {
const isFlashing = Boolean(state.flashing);
const isValidating = !isFlashing && Boolean(state.verifying);
const shouldValidate = settings.get('validateWriteOnSuccess');
const shouldUnmount = settings.get('unmountOnSuccess');
if (state.percentage === 0 && !state.speed) {
if (isValidating) {
return 'Validating...';
}
return 'Starting...';
} else if (state.percentage === 100) {
if ((isValidating || !shouldValidate) && shouldUnmount) {
return 'Unmounting...';
}
return 'Finishing...';
} else if (isFlashing) {
if (state.percentage != null) {
return `${state.percentage}% Flashing`;
}
return `${bytesToClosestUnit(state.position)} flashed`;
} else if (isValidating) {
return `${state.percentage}% Validating`;
} else if (!isFlashing && !isValidating) {
return 'Failed';
}
throw new Error(`Invalid state: ${JSON.stringify(state)}`);
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright 2018 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _debug from 'debug';
import * as electron from 'electron';
import { EventEmitter } from 'events';
import * as createInactivityTimer from 'inactivity-timer';
import * as settings from '../models/settings';
import { logException } from './analytics';
const debug = _debug('etcher:update-lock');
/**
* Interaction timeout in milliseconds (defaults to 5 minutes)
* @type {Number}
* @constant
*/
const INTERACTION_TIMEOUT_MS = settings.has('interactionTimeout')
? parseInt(settings.get('interactionTimeout'), 10)
: 5 * 60 * 1000;
class UpdateLock extends EventEmitter {
private paused: boolean;
private lockTimer: any;
constructor() {
super();
this.paused = false;
this.on('inactive', UpdateLock.onInactive);
this.lockTimer = createInactivityTimer(INTERACTION_TIMEOUT_MS, () => {
debug('inactive');
this.emit('inactive');
});
}
/**
* @summary Inactivity event handler, releases the balena update lock on inactivity
*/
private static onInactive() {
if (settings.get('resinUpdateLock')) {
UpdateLock.check((checkError: Error, isLocked: boolean) => {
debug('inactive-check', Boolean(checkError));
if (checkError) {
logException(checkError);
}
if (isLocked) {
UpdateLock.release((error?: Error) => {
debug('inactive-release', Boolean(error));
if (error) {
logException(error);
}
});
}
});
}
}
/**
* @summary Acquire the update lock
*/
private static acquire(callback: (error?: Error) => void) {
debug('lock');
if (settings.get('resinUpdateLock')) {
electron.ipcRenderer.once('resin-update-lock', (_event, error) => {
callback(error);
});
electron.ipcRenderer.send('resin-update-lock', 'lock');
} else {
callback(new Error('Update lock disabled'));
}
}
/**
* @summary Release the update lock
*/
public static release(callback: (error?: Error) => void) {
debug('unlock');
if (settings.get('resinUpdateLock')) {
electron.ipcRenderer.once('resin-update-lock', (_event, error) => {
callback(error);
});
electron.ipcRenderer.send('resin-update-lock', 'unlock');
} else {
callback(new Error('Update lock disabled'));
}
}
/**
* @summary Check the state of the update lock
* @param {Function} callback - callback(error, isLocked)
* @example
* UpdateLock.check((error, isLocked) => {
* if (isLocked) {
* // ...
* }
* })
*/
private static check(
callback: (error: Error | null, isLocked?: boolean) => void,
) {
debug('check');
if (settings.get('resinUpdateLock')) {
electron.ipcRenderer.once(
'resin-update-lock',
(_event, error, isLocked) => {
callback(error, isLocked);
},
);
electron.ipcRenderer.send('resin-update-lock', 'check');
} else {
callback(new Error('Update lock disabled'));
}
}
/**
* @summary Extend the lock timer
*/
public extend() {
debug('extend');
if (this.paused) {
debug('extend:paused');
return;
}
this.lockTimer.signal();
// When extending, check that we have the lock,
// and acquire it, if not
if (settings.get('resinUpdateLock')) {
UpdateLock.check((checkError, isLocked) => {
if (checkError) {
logException(checkError);
}
if (!isLocked) {
UpdateLock.acquire(error => {
if (error) {
logException(error);
}
debug('extend-acquire', Boolean(error));
});
}
});
}
}
/**
* @summary Clear the lock timer
*/
private clearTimer() {
debug('clear');
this.lockTimer.clear();
}
/**
* @summary Clear the lock timer, and pause extension, avoiding triggering until resume()d
*/
public pause() {
debug('pause');
this.paused = true;
this.clearTimer();
}
/**
* @summary Un-pause lock extension, and restart the timer
*/
public resume() {
debug('resume');
this.paused = false;
this.extend();
}
}
export const updateLock = new UpdateLock();

98
lib/gui/app/os/dialog.ts Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as electron from 'electron';
import * as _ from 'lodash';
import * as errors from '../../../shared/errors';
import { getAllExtensions } from '../../../shared/supported-formats';
/**
* @summary Open an image selection dialog
*
* @description
* Notice that by image, we mean *.img/*.iso/*.zip/etc files.
*/
export async function selectImage(): Promise<string | undefined> {
const options: electron.OpenDialogOptions = {
// This variable is set when running in GNU/Linux from
// inside an AppImage, and represents the working directory
// from where the AppImage was run (which might not be the
// place where the AppImage is located). `OWD` stands for
// "Original Working Directory".
//
// See: https://github.com/probonopd/AppImageKit/commit/1569d6f8540aa6c2c618dbdb5d6fcbf0003952b7
defaultPath: process.env.OWD,
properties: ['openFile', 'treatPackageAsDirectory'],
filters: [
{
name: 'OS Images',
extensions: [...getAllExtensions()].sort(),
},
],
};
const currentWindow = electron.remote.getCurrentWindow();
const [file] = (
await electron.remote.dialog.showOpenDialog(currentWindow, options)
).filePaths;
return file;
}
/**
* @summary Open a warning dialog
*/
export async function showWarning(options: {
confirmationLabel: string;
rejectionLabel: string;
title: string;
description: string;
}): Promise<boolean> {
_.defaults(options, {
confirmationLabel: 'OK',
rejectionLabel: 'Cancel',
});
const BUTTONS = [options.confirmationLabel, options.rejectionLabel];
const BUTTON_CONFIRMATION_INDEX = _.indexOf(
BUTTONS,
options.confirmationLabel,
);
const BUTTON_REJECTION_INDEX = _.indexOf(BUTTONS, options.rejectionLabel);
const { response } = await electron.remote.dialog.showMessageBox(
electron.remote.getCurrentWindow(),
{
type: 'warning',
buttons: BUTTONS,
defaultId: BUTTON_REJECTION_INDEX,
cancelId: BUTTON_REJECTION_INDEX,
title: 'Attention',
message: options.title,
detail: options.description,
},
);
return response === BUTTON_CONFIRMATION_INDEX;
}
/**
* @summary Show error dialog for an Error instance
*/
export function showError(error: Error) {
const title = errors.getTitle(error);
const message = errors.getDescription(error);
electron.remote.dialog.showErrorBox(title, message);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 resin.io
* Copyright 2017 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,20 +14,23 @@
* limitations under the License.
*/
'use strict';
import * as electron from 'electron';
import * as settings from '../models/settings';
/**
* @module Etcher.Components.FlashErrorModal
* @summary Send a notification
*/
export function send(title: string, body: string, icon: string) {
// Bail out if desktop notifications are disabled
if (!settings.get('desktopNotifications')) {
return;
}
const angular = require('angular');
const MODULE_NAME = 'Etcher.Components.FlashErrorModal';
const FlashErrorModal = angular.module(MODULE_NAME, [
require('../warning-modal/warning-modal'),
require('../../models/selection-state'),
require('../../modules/analytics')
]);
// `app.dock` is only defined in OS X
if (electron.remote.app.dock) {
electron.remote.app.dock.bounce();
}
FlashErrorModal.service('FlashErrorModalService', require('./services/flash-error-modal'));
module.exports = MODULE_NAME;
return new window.Notification(title, { body, icon });
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as electron from 'electron';
import * as settings from '../../../models/settings';
import { store } from '../../../models/store';
import { logEvent } from '../../../modules/analytics';
/**
* @summary Open an external resource
*/
export function open(url: string) {
// Don't open links if they're disabled by the env var
if (settings.get('disableExternalLinks')) {
return;
}
logEvent('Open external link', {
url,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
});
if (url) {
electron.shell.openExternal(url);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as electron from 'electron';
import { percentageToFloat } from '../../../shared/utils';
import { FlashState, fromFlashState } from '../modules/progress-status';
/**
* @summary The title of the main window upon program launch
*/
const INITIAL_TITLE = document.title;
/**
* @summary Make the full window status title
*/
function getWindowTitle(state?: FlashState) {
if (state) {
return `${INITIAL_TITLE} ${fromFlashState(state)}`;
}
return INITIAL_TITLE;
}
/**
* @summary A reference to the current renderer Electron window
*
* @description
* We expose this property to `this` for testability purposes.
*/
export const currentWindow = electron.remote.getCurrentWindow();
/**
* @summary Set operating system window progress
*
* @description
* Show progress inline in operating system task bar
*/
export function set(state: FlashState) {
if (state.percentage != null) {
exports.currentWindow.setProgressBar(percentageToFloat(state.percentage));
}
exports.currentWindow.setTitle(getWindowTitle(state));
}
/**
* @summary Clear the window progress bar
*/
export function clear() {
// Passing 0 or null/undefined doesn't work.
exports.currentWindow.setProgressBar(-1);
exports.currentWindow.setTitle(getWindowTitle(undefined));
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { using } from 'bluebird';
import { exec } from 'child_process';
import { readFile } from 'fs';
import { chain, trim } from 'lodash';
import { platform } from 'os';
import { join } from 'path';
import { env } from 'process';
import { promisify } from 'util';
import { tmpFileDisposer } from '../../../shared/utils';
const readFileAsync = promisify(readFile);
const execAsync = promisify(exec);
/**
* @summary Returns wmic's output for network drives
*/
export async function getWmicNetworkDrivesOutput(): Promise<string> {
// Exported for tests.
// When trying to read wmic's stdout directly from node, it is encoded with the current
// console codepage (depending on the computer).
// Decoding this would require getting this codepage somehow and using iconv as node
// doesn't know how to read cp850 directly for example.
// We could also use wmic's "/output:" switch but it doesn't work when the filename
// contains a space and the os temp dir may contain spaces ("D:\Windows Temp Files" for example).
// So we just redirect to a file and read it afterwards as we know it will be ucs2 encoded.
const options = {
// Close the file once it's created
discardDescriptor: true,
// Wmic fails with "Invalid global switch" when the "/output:" switch filename contains a dash ("-")
prefix: 'tmp',
};
return using(tmpFileDisposer(options), async ({ path }) => {
const command = [
join(env.SystemRoot as string, 'System32', 'Wbem', 'wmic'),
'path',
'Win32_LogicalDisk',
'Where',
'DriveType="4"',
'get',
'DeviceID,ProviderName',
'>',
`"${path}"`,
];
await execAsync(command.join(' '), { windowsHide: true });
return readFileAsync(path, 'ucs2');
});
}
/**
* @summary returns a Map of drive letter -> network locations on Windows: 'Z:' -> '\\\\192.168.0.1\\Public'
*/
async function getWindowsNetworkDrives(): Promise<Map<string, string>> {
// Use getWindowsNetworkDrives from "exports." so it can be mocked in tests
const result = await exports.getWmicNetworkDrivesOutput();
const couples: Array<[string, string]> = chain(result)
.split('\n')
// Remove header line
.slice(1)
// Remove extra spaces / tabs / carriage returns
.invokeMap(String.prototype.trim)
// Filter out empty lines
.compact()
.map((str: string): [string, string] => {
const colonPosition = str.indexOf(':');
if (colonPosition === -1) {
throw new Error(`Can't parse wmic output: ${result}`);
}
return [
str.slice(0, colonPosition + 1),
trim(str.slice(colonPosition + 1)),
];
})
.filter(couple => couple[1].length > 0)
.value();
return new Map(couples);
}
/**
* @summary Replaces network drive letter with network drive location in the provided filePath on Windows
*/
export async function replaceWindowsNetworkDriveLetter(
filePath: string,
): Promise<string> {
let result = filePath;
if (platform() === 'win32') {
const matches = /^([A-Z]+:)\\(.*)$/.exec(filePath);
if (matches !== null) {
const [, drive, relativePath] = matches;
const drives = await getWindowsNetworkDrives();
const location = drives.get(drive);
if (location !== undefined) {
result = `${location}\\${relativePath}`;
}
}
}
return result;
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.page-finish {
margin-top: 60px;
}
.col-xs-5.inline-flex.items-baseline > span, .col-xs-5.inline-flex.items-baseline > div {
margin-bottom: -10px;
}
.page-finish .button-label {
margin: 0 auto $spacing-medium;
// Keep some spacing at the sides
max-width: $btn-min-width - 5px;
}
.page-finish .button-primary {
min-width: $btn-min-width;
}
.page-finish .title,
.page-finish .title h3 {
color: $palette-theme-dark-foreground;
font-weight: bold;
}
.page-finish .huge-title {
font-size: 3.5em;
}
.page-finish .label {
display: inline-block;
> b {
color: $palette-theme-dark-soft-foreground;
}
}
.page-finish .soft {
color: $palette-theme-dark-soft-foreground;
}
.page-finish .separator-xs {
flex-grow: 0;
background-color: $palette-theme-dark-soft-background;
padding: 0px;
min-width: 2px;
}
.page-finish .center {
display: flex;
align-items: center;
justify-content: center;
}
.page-finish .box > div > button {
margin-right: 20px;
}
.page-finish webview {
width: 800px;
height: 300px;
position: absolute;
top: 80px;
left: 0;
z-index: 9001;
}
.page-finish .fallback-banner {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
position: absolute;
bottom: 0;
color: white;
height: 320px;
width: 100vw;
left: 0;
> * {
display: flex;
justify-content: center;
align-items: center;
}
.caption {
display: flex;
font-weight: 500;
}
.caption-big {
font-size: 28px;
font-weight: bold;
position: absolute;
top: 75px;
}
.caption-small {
font-size: 12px;
}
.fallback-footer {
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
position: absolute;
bottom: 0;
max-height: 21px;
margin-bottom: 17px;
}
.svg-icon {
margin: 0 10px;
}
.section-footer {
position: absolute;
right: 0;
bottom: 0;
.footer-right {
color: #7e8085;
font-size: 12px;
margin-right: 30px;
}
}
}
.inline-flex {
display: inline-flex;
}
.items-baseline {
align-items: baseline;
}
.page-finish .tick--success {
/* hack(Shou): for some reason the height is stretched */
height: 24px;
width: 24px;
border: none;
padding: 0;
margin: 0 15px 0 0;
justify-content: center;
align-items: center;
display: flex;
font-size: 16px;
}
.title-wrap {
margin-left: 5px;
> .title {
margin-bottom: 3px;
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _ from 'lodash';
import * as React from 'react';
import styled from 'styled-components';
import { DriveSelectorModal } from '../../components/drive-selector/DriveSelectorModal';
import { TargetSelector } from '../../components/drive-selector/target-selector';
import { SVGIcon } from '../../components/svg-icon/svg-icon';
import { getImage, getSelectedDrives } from '../../models/selection-state';
import * as settings from '../../models/settings';
import { observe, store } from '../../models/store';
import * as analytics from '../../modules/analytics';
const StepBorder = styled.div<{
disabled: boolean;
left?: boolean;
right?: boolean;
}>`
height: 2px;
background-color: ${props =>
props.disabled
? props.theme.customColors.dark.disabled.foreground
: props.theme.customColors.dark.foreground};
position: absolute;
width: 124px;
top: 19px;
left: ${props => (props.left ? '-67px' : undefined)};
right: ${props => (props.right ? '-67px' : undefined)};
`;
const getDriveListLabel = () => {
return _.join(
_.map(getSelectedDrives(), (drive: any) => {
return `${drive.description} (${drive.displayName})`;
}),
'\n',
);
};
const shouldShowDrivesButton = () => {
return !settings.get('disableExplicitDriveSelection');
};
const getDriveSelectionStateSlice = () => ({
showDrivesButton: shouldShowDrivesButton(),
driveListLabel: getDriveListLabel(),
targets: getSelectedDrives(),
image: getImage(),
});
interface DriveSelectorProps {
webviewShowing: boolean;
disabled: boolean;
nextStepDisabled: boolean;
hasDrive: boolean;
flashing: boolean;
}
export const DriveSelector = ({
webviewShowing,
disabled,
nextStepDisabled,
hasDrive,
flashing,
}: DriveSelectorProps) => {
// TODO: inject these from redux-connector
const [
{ showDrivesButton, driveListLabel, targets, image },
setStateSlice,
] = React.useState(getDriveSelectionStateSlice());
const [showDriveSelectorModal, setShowDriveSelectorModal] = React.useState(
false,
);
React.useEffect(() => {
return observe(() => {
setStateSlice(getDriveSelectionStateSlice());
});
}, []);
const showStepConnectingLines = !webviewShowing || !flashing;
return (
<div className="box text-center relative">
{showStepConnectingLines && (
<>
<StepBorder disabled={disabled} left />
<StepBorder disabled={nextStepDisabled} right />
</>
)}
<div className="center-block">
<SVGIcon paths={['../../assets/drive.svg']} disabled={disabled} />
</div>
<div className="space-vertical-large">
<TargetSelector
disabled={disabled}
show={!hasDrive && showDrivesButton}
tooltip={driveListLabel}
openDriveSelector={() => {
setShowDriveSelectorModal(true);
}}
reselectDrive={() => {
analytics.logEvent('Reselect drive', {
applicationSessionUuid: store.getState().toJS()
.applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS()
.flashingWorkflowUuid,
});
setShowDriveSelectorModal(true);
}}
flashing={flashing}
targets={targets}
image={image}
/>
</div>
{showDriveSelectorModal && (
<DriveSelectorModal
close={() => setShowDriveSelectorModal(false)}
></DriveSelectorModal>
)}
</div>
);
};

View File

@@ -0,0 +1,313 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as _ from 'lodash';
import * as path from 'path';
import * as React from 'react';
import { Modal, Txt } from 'rendition';
import * as constraints from '../../../../shared/drive-constraints';
import * as messages from '../../../../shared/messages';
import { DriveSelectorModal } from '../../components/drive-selector/DriveSelectorModal';
import { ProgressButton } from '../../components/progress-button/progress-button';
import { SVGIcon } from '../../components/svg-icon/svg-icon';
import * as availableDrives from '../../models/available-drives';
import * as flashState from '../../models/flash-state';
import * as selection from '../../models/selection-state';
import { store } from '../../models/store';
import * as analytics from '../../modules/analytics';
import { scanner as driveScanner } from '../../modules/drive-scanner';
import * as imageWriter from '../../modules/image-writer';
import * as progressStatus from '../../modules/progress-status';
import * as notification from '../../os/notification';
const COMPLETED_PERCENTAGE = 100;
const SPEED_PRECISION = 2;
const getWarningMessages = (drives: any, image: any) => {
const warningMessages = [];
for (const drive of drives) {
if (constraints.isDriveSizeLarge(drive)) {
warningMessages.push(messages.warning.largeDriveSize(drive));
} else if (!constraints.isDriveSizeRecommended(drive, image)) {
warningMessages.push(
messages.warning.unrecommendedDriveSize(image, drive),
);
}
// TODO(Shou): we should consider adding the same warning dialog for system drives and remove unsafe mode
}
return warningMessages;
};
const getErrorMessageFromCode = (errorCode: string) => {
// TODO: All these error codes to messages translations
// should go away if the writer emitted user friendly
// messages on the first place.
if (errorCode === 'EVALIDATION') {
return messages.error.validation();
} else if (errorCode === 'EUNPLUGGED') {
return messages.error.driveUnplugged();
} else if (errorCode === 'EIO') {
return messages.error.inputOutput();
} else if (errorCode === 'ENOSPC') {
return messages.error.notEnoughSpaceInDrive();
} else if (errorCode === 'ECHILDDIED') {
return messages.error.childWriterDied();
}
return '';
};
async function flashImageToDrive(goToSuccess: () => void): Promise<string> {
const devices = selection.getSelectedDevices();
const image: any = selection.getImage();
const drives = _.filter(availableDrives.getDrives(), (drive: any) => {
return _.includes(devices, drive.device);
});
if (drives.length === 0 || flashState.isFlashing()) {
return '';
}
// Stop scanning drives when flashing
// otherwise Windows throws EPERM
driveScanner.stop();
const iconPath = '../../assets/icon.png';
const basename = path.basename(image.path);
try {
await imageWriter.flash(image.path, drives);
if (!flashState.wasLastFlashCancelled()) {
const flashResults: any = flashState.getFlashResults();
notification.send(
'Flash complete!',
messages.info.flashComplete(
basename,
drives as any,
flashResults.results.devices,
),
iconPath,
);
goToSuccess();
}
} catch (error) {
// When flashing is cancelled before starting above there is no error
if (!error) {
return '';
}
notification.send(
'Oops! Looks like the flash failed.',
messages.error.flashFailure(path.basename(image.path), drives),
iconPath,
);
let errorMessage = getErrorMessageFromCode(error.code);
if (!errorMessage) {
error.image = basename;
analytics.logException(error);
errorMessage = messages.error.genericFlashError();
}
return errorMessage;
} finally {
availableDrives.setDrives([]);
driveScanner.start();
}
return '';
}
/**
* @summary Get progress button label
* @function
* @public
*
* @returns {String} progress button label
*
* @example
* const label = FlashController.getProgressButtonLabel()
*/
const getProgressButtonLabel = () => {
if (!flashState.isFlashing()) {
return 'Flash!';
}
// TODO: no any
return progressStatus.fromFlashState(flashState.getFlashState() as any);
};
const formatSeconds = (totalSeconds: number) => {
if (!totalSeconds && !_.isNumber(totalSeconds)) {
return '';
}
const minutes = Math.floor(totalSeconds / 60);
const seconds = Math.floor(totalSeconds - minutes * 60);
return `${minutes}m${seconds}s`;
};
export const Flash = ({ shouldFlashStepBeDisabled, goToSuccess }: any) => {
const state: any = flashState.getFlashState();
const isFlashing = flashState.isFlashing();
const flashErrorCode = flashState.getLastFlashErrorCode();
const [warningMessages, setWarningMessages] = React.useState<string[]>([]);
const [errorMessage, setErrorMessage] = React.useState('');
const [showDriveSelectorModal, setShowDriveSelectorModal] = React.useState(
false,
);
const handleWarningResponse = async (shouldContinue: boolean) => {
setWarningMessages([]);
if (!shouldContinue) {
setShowDriveSelectorModal(true);
return;
}
setErrorMessage(await flashImageToDrive(goToSuccess));
};
const handleFlashErrorResponse = (shouldRetry: boolean) => {
setErrorMessage('');
flashState.resetState();
if (shouldRetry) {
analytics.logEvent('Restart after failure', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
});
} else {
selection.clear();
}
};
const tryFlash = async () => {
const devices = selection.getSelectedDevices();
const image = selection.getImage();
const drives = _.filter(availableDrives.getDrives(), (drive: any) => {
return _.includes(devices, drive.device);
});
if (drives.length === 0 || flashState.isFlashing()) {
return;
}
const hasDangerStatus = constraints.hasListDriveImageCompatibilityStatus(
drives,
image,
);
if (hasDangerStatus) {
setWarningMessages(getWarningMessages(drives, image));
return;
}
setErrorMessage(await flashImageToDrive(goToSuccess));
};
return (
<>
<div className="box text-center">
<div className="center-block">
<SVGIcon
paths={['../../assets/flash.svg']}
disabled={shouldFlashStepBeDisabled}
/>
</div>
<div className="space-vertical-large">
<ProgressButton
striped={state.type === 'verifying'}
active={isFlashing}
percentage={state.percentage}
label={getProgressButtonLabel()}
disabled={Boolean(flashErrorCode) || shouldFlashStepBeDisabled}
callback={tryFlash}
></ProgressButton>
{isFlashing && (
<button
className="button button-link button-abort-write"
onClick={imageWriter.cancel}
>
<span className="glyphicon glyphicon-remove-sign"></span>
</button>
)}
{!_.isNil(state.speed) && state.percentage !== COMPLETED_PERCENTAGE && (
<p className="step-footer step-footer-split">
{Boolean(state.speed) && (
<span>{`${state.speed.toFixed(SPEED_PRECISION)} MB/s`}</span>
)}
{!_.isNil(state.eta) && (
<span>{`ETA: ${formatSeconds(state.eta)}`}</span>
)}
</p>
)}
{Boolean(state.failed) && (
<div className="target-status-wrap">
<div className="target-status-line target-status-failed">
<span className="target-status-dot"></span>
<span className="target-status-quantity">{state.failed}</span>
<span className="target-status-message">
{messages.progress.failed(state.failed)}{' '}
</span>
</div>
</div>
)}
</div>
</div>
{warningMessages && warningMessages.length > 0 && (
<Modal
width={400}
titleElement={'Attention'}
cancel={() => handleWarningResponse(false)}
done={() => handleWarningResponse(true)}
cancelButtonProps={{
children: 'Change',
}}
action={'Continue'}
primaryButtonProps={{ primary: false, warning: true }}
>
{_.map(warningMessages, (message, key) => (
<Txt key={key} whitespace="pre-line" mt={2}>
{message}
</Txt>
))}
</Modal>
)}
{errorMessage && (
<Modal
width={400}
titleElement={'Attention'}
cancel={() => handleFlashErrorResponse(false)}
done={() => handleFlashErrorResponse(true)}
action={'Retry'}
>
<Txt>{errorMessage}</Txt>
</Modal>
)}
{showDriveSelectorModal && (
<DriveSelectorModal
close={() => setShowDriveSelectorModal(false)}
></DriveSelectorModal>
)}
</>
);
};

View File

@@ -0,0 +1,262 @@
/*
* Copyright 2019 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { faCog, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import * as _ from 'lodash';
import * as path from 'path';
import * as React from 'react';
import { Button } from 'rendition';
import { FeaturedProject } from '../../components/featured-project/featured-project';
import FinishPage from '../../components/finish/finish';
import { ImageSelector } from '../../components/image-selector/image-selector';
import { ReducedFlashingInfos } from '../../components/reduced-flashing-infos/reduced-flashing-infos';
import { SafeWebview } from '../../components/safe-webview/safe-webview';
import { SettingsModal } from '../../components/settings/settings';
import { SVGIcon } from '../../components/svg-icon/svg-icon';
import * as flashState from '../../models/flash-state';
import * as selectionState from '../../models/selection-state';
import * as settings from '../../models/settings';
import { observe } from '../../models/store';
import { open as openExternal } from '../../os/open-external/services/open-external';
import { ThemedProvider } from '../../styled-components';
import { colors } from '../../theme';
import { middleEllipsis } from '../../utils/middle-ellipsis';
import { bytesToClosestUnit } from '../../../../shared/units';
import { DriveSelector } from './DriveSelector';
import { Flash } from './Flash';
function getDrivesTitle() {
const drives = selectionState.getSelectedDrives();
if (drives.length === 1) {
// @ts-ignore
return drives[0].description || 'Untitled Device';
}
if (drives.length === 0) {
return 'No targets found';
}
return `${drives.length} Targets`;
}
function getImageBasename() {
if (!selectionState.hasImage()) {
return '';
}
const selectionImageName = selectionState.getImageName();
const imageBasename = path.basename(selectionState.getImagePath());
return selectionImageName || imageBasename;
}
interface MainPageStateFromStore {
isFlashing: boolean;
hasImage: boolean;
hasDrive: boolean;
imageLogo: string;
imageSize: number;
imageName: string;
driveTitle: string;
}
interface MainPageState {
current: 'main' | 'success';
isWebviewShowing: boolean;
hideSettings: boolean;
}
export class MainPage extends React.Component<
{},
MainPageState & MainPageStateFromStore
> {
constructor(props: {}) {
super(props);
this.state = {
current: 'main',
isWebviewShowing: false,
hideSettings: true,
...this.stateHelper(),
};
}
private stateHelper(): MainPageStateFromStore {
return {
isFlashing: flashState.isFlashing(),
hasImage: selectionState.hasImage(),
hasDrive: selectionState.hasDrive(),
imageLogo: selectionState.getImageLogo(),
imageSize: selectionState.getImageSize(),
imageName: getImageBasename(),
driveTitle: getDrivesTitle(),
};
}
public componentDidMount() {
observe(() => {
this.setState(this.stateHelper());
});
}
public render() {
const shouldDriveStepBeDisabled = !this.state.hasImage;
const shouldFlashStepBeDisabled =
!this.state.hasImage || !this.state.hasDrive;
if (this.state.current === 'main') {
return (
<ThemedProvider style={{ height: '100%', width: '100%' }}>
<header
id="app-header"
style={{
width: '100%',
padding: '13px 14px',
textAlign: 'center',
}}
>
<span
style={{
cursor: 'pointer',
}}
onClick={() =>
openExternal('https://www.balena.io/etcher?ref=etcher_footer')
}
tabIndex={100}
>
<SVGIcon
paths={['../../assets/etcher.svg']}
width="123px"
height="22px"
/>
</span>
<span
style={{
float: 'right',
position: 'absolute',
right: 0,
}}
>
<Button
icon={<FontAwesomeIcon icon={faCog} />}
color={colors.secondary.background}
fontSize={24}
style={{ width: '30px' }}
plain
onClick={() => this.setState({ hideSettings: false })}
tabIndex={5}
/>
{!settings.get('disableExternalLinks') && (
<Button
icon={<FontAwesomeIcon icon={faQuestionCircle} />}
color={colors.secondary.background}
fontSize={24}
style={{ width: '30px' }}
plain
onClick={() =>
openExternal(
selectionState.getImageSupportUrl() ||
'https://github.com/balena-io/etcher/blob/master/SUPPORT.md',
)
}
tabIndex={5}
/>
)}
</span>
</header>
{this.state.hideSettings ? null : (
<SettingsModal
toggleModal={(value: boolean) => {
this.setState({ hideSettings: !value });
}}
/>
)}
<div
className="page-main row around-xs"
style={{ margin: '110px 50px' }}
>
<div className="col-xs">
<ImageSelector flashing={this.state.isFlashing} />
</div>
<div className="col-xs">
<DriveSelector
webviewShowing={this.state.isWebviewShowing}
disabled={shouldDriveStepBeDisabled}
nextStepDisabled={shouldFlashStepBeDisabled}
hasDrive={this.state.hasDrive}
flashing={this.state.isFlashing}
/>
</div>
{this.state.isFlashing && (
<div
className={`featured-project ${
this.state.isFlashing && this.state.isWebviewShowing
? 'fp-visible'
: ''
}`}
>
<FeaturedProject
onWebviewShow={(isWebviewShowing: boolean) => {
this.setState({ isWebviewShowing });
}}
/>
</div>
)}
<div>
<ReducedFlashingInfos
imageLogo={this.state.imageLogo}
imageName={middleEllipsis(this.state.imageName, 16)}
imageSize={
_.isNumber(this.state.imageSize)
? (bytesToClosestUnit(this.state.imageSize) as string)
: ''
}
driveTitle={middleEllipsis(this.state.driveTitle, 16)}
shouldShow={
this.state.isFlashing && this.state.isWebviewShowing
}
/>
</div>
<div className="col-xs">
<Flash
goToSuccess={() => this.setState({ current: 'success' })}
shouldFlashStepBeDisabled={shouldFlashStepBeDisabled}
/>
</div>
</div>
</ThemedProvider>
);
} else if (this.state.current === 'success') {
return (
<div className="section-loader isFinish">
<FinishPage goToMain={() => this.setState({ current: 'main' })} />
<SafeWebview src="https://www.balena.io/etcher/success-banner/" />
</div>
);
}
}
}
export default MainPage;

View File

@@ -0,0 +1,201 @@
/*
* Copyright 2016 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
img[disabled] {
opacity: $disabled-opacity;
}
.page-main {
flex: 1;
align-self: center;
margin: 20px;
}
.page-main > .col-xs {
height: 165px;
}
.page-main .step-selection-text {
display: flex;
flex-wrap: wrap;
justify-content: center;
color: $palette-theme-dark-foreground;
}
.page-main .text-disabled > span {
color: $palette-theme-dark-disabled-foreground;
}
.page-main .step-drive.text-warning {
color: $palette-theme-warning-background;
}
.page-main .relative {
position: relative;
}
.page-main .button-abort-write {
width: 20px;
height: 20px;
margin: 0;
padding: 0;
font-size: 16px;
position: absolute;
right: -17px;
top: 30%;
}
.button-brick {
width: 200px;
height: 48px;
font-size: 16px;
font-weight: 300;
}
.page-main .step-tooltip {
display: block;
margin: -5px auto -20px;
color: $palette-theme-dark-disabled-foreground;
font-size: 10px;
}
.page-main .step-footer {
width: 100%;
color: $palette-theme-dark-disabled-foreground;
font-size: 10px;
}
.page-main p.step-footer {
margin-top: 9px;
}
.page-main .step-footer-split {
position: absolute;
top: 39px;
left: 28px;
margin-left: auto;
margin-right: auto;
display: flex;
justify-content: space-between;
width: $btn-min-width;
}
.page-main .button.step-footer {
font-size: 16px;
color: $palette-theme-primary-background;
border-radius: 0;
padding: 0;
width: 100%;
font-weight: 300;
height: 21px;
}
.page-main .step-drive.glyphicon {
margin-top: 1px;
}
.page-main div.step-fill,
.page-main span.step-fill {
margin-top: 25px;
}
.page-main .step-drive.step-list {
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background-color: $palette-theme-dark-disabled-foreground;
border-radius: 4px;
}
}
.page-main .glyphicon {
vertical-align: text-top;
}
.page-main .step-name {
display: flex;
justify-content: center;
align-items: center;
height: 39px;
width: 100%;
font-weight: bold;
color: $palette-theme-primary-foreground;
}
.page-main .step-size {
color: $palette-theme-dark-disabled-foreground;
margin: 0 0 8px 0;
font-size: 16px;
line-height: 1.5;
height: 21px;
width: 100%;
}
.page-main .step-list {
height: 80px;
margin: 15px;
overflow-y: auto;
color: $palette-theme-dark-disabled-foreground;
}
.target-status-wrap {
display: flex;
position: absolute;
top: 62px;
flex-direction: column;
margin: 8px 28px;
align-items: flex-start;
}
.target-status-line {
display: flex;
align-items: baseline;
margin-bottom: 9px;
> .target-status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 10px;
}
&.target-status-successful > .target-status-dot {
background-color: $palette-theme-success-background;
}
&.target-status-failed > .target-status-dot {
background-color: $palette-theme-danger-background;
}
> .target-status-quantity {
color: white;
font-weight: bold;
}
> .target-status-message {
color: gray;
margin-left: 10px;
}
}
.tooltip-inner {
white-space: pre-line;
}
.space-vertical-large {
position: relative;
}

Some files were not shown because too many files have changed in this diff Show More