mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-23 19:26:33 +00:00
commit
55d2400ac7
@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"builder": {
|
"builder": {
|
||||||
"appId": "io.balena.etcher",
|
"appId": "io.balena.etcher",
|
||||||
"copyright": "Copyright 2016-2020 Balena Ltd",
|
"copyright": "Copyright 2016-2021 Balena Ltd",
|
||||||
"productName": "balenaEtcher",
|
"productName": "balenaEtcher",
|
||||||
"nodeGypRebuild": false,
|
"nodeGypRebuild": false,
|
||||||
"afterPack": "./afterPack.js",
|
"afterPack": "./afterPack.js",
|
||||||
@ -30,7 +30,8 @@
|
|||||||
"category": "public.app-category.developer-tools",
|
"category": "public.app-category.developer-tools",
|
||||||
"hardenedRuntime": true,
|
"hardenedRuntime": true,
|
||||||
"entitlements": "entitlements.mac.plist",
|
"entitlements": "entitlements.mac.plist",
|
||||||
"entitlementsInherit": "entitlements.mac.plist"
|
"entitlementsInherit": "entitlements.mac.plist",
|
||||||
|
"artifactName": "${productName}-${version}.${ext}"
|
||||||
},
|
},
|
||||||
"dmg": {
|
"dmg": {
|
||||||
"iconSize": 110,
|
"iconSize": 110,
|
||||||
|
103
README.md
103
README.md
@ -5,16 +5,16 @@
|
|||||||
Etcher is a powerful OS image flasher built with web technologies to ensure
|
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
|
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
|
you from accidentally writing to your hard-drives, ensures every byte of data
|
||||||
was written correctly and much more. It can also flash directly Raspberry Pi devices that support the usbboot protocol
|
was written correctly, and much more. It can also directly flash Raspberry Pi devices that support [USB device boot mode](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/device.md).
|
||||||
|
|
||||||
[](https://balena.io/etcher)
|
[](https://balena.io/etcher)
|
||||||
[](https://github.com/balena-io/etcher/blob/master/LICENSE)
|
[](https://github.com/balena-io/etcher/blob/master/LICENSE)
|
||||||
[](https://david-dm.org/balena-io/etcher)
|
[](https://david-dm.org/balena-io/etcher)
|
||||||
[](https://forums.balena.io/c/etcher)
|
[](https://forums.balena.io/c/etcher)
|
||||||
|
|
||||||
***
|
---
|
||||||
|
|
||||||
[**Download**][etcher] | [**Support**][SUPPORT] | [**Documentation**][USER-DOCUMENTATION] | [**Contributing**][CONTRIBUTING] | [**Roadmap**][milestones]
|
[**Download**][etcher] | [**Support**][support] | [**Documentation**][user-documentation] | [**Contributing**][contributing] | [**Roadmap**][milestones]
|
||||||
|
|
||||||
## Supported Operating Systems
|
## Supported Operating Systems
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ was written correctly and much more. It can also flash directly Raspberry Pi dev
|
|||||||
- macOS 10.10 (Yosemite) and later
|
- macOS 10.10 (Yosemite) and later
|
||||||
- Microsoft Windows 7 and later
|
- Microsoft Windows 7 and later
|
||||||
|
|
||||||
Note that Etcher will run on any platform officially supported by
|
**Note**: Etcher will run on any platform officially supported by
|
||||||
[Electron][electron]. Read more in their
|
[Electron][electron]. Read more in their
|
||||||
[documentation][electron-supported-platforms].
|
[documentation][electron-supported-platforms].
|
||||||
|
|
||||||
@ -33,24 +33,24 @@ installers for all supported operating systems.
|
|||||||
|
|
||||||
#### Debian and Ubuntu based Package Repository (GNU/Linux x86/x64)
|
#### Debian and Ubuntu based Package Repository (GNU/Linux x86/x64)
|
||||||
|
|
||||||
1. Add Etcher debian repository:
|
1. Add Etcher Debian repository:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
echo "deb https://deb.etcher.io stable etcher" | sudo tee /etc/apt/sources.list.d/balena-etcher.list
|
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:
|
2. Trust Bintray.com's GPG key:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv-keys 379CE192D401AB61
|
sudo apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv-keys 379CE192D401AB61
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Update and install:
|
3. Update and install:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install balena-etcher-electron
|
sudo apt-get install balena-etcher-electron
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Uninstall
|
##### Uninstall
|
||||||
|
|
||||||
@ -74,25 +74,46 @@ sudo zypper in balena-etcher-electron
|
|||||||
sudo zypper rm balena-etcher-electron
|
sudo zypper rm balena-etcher-electron
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Redhat (RHEL) and Fedora based Package Repository (GNU/Linux x86/x64)
|
#### Redhat (RHEL) and Fedora-based Package Repository (GNU/Linux x86/x64)
|
||||||
|
|
||||||
|
##### DNF
|
||||||
|
|
||||||
1. Add Etcher rpm repository:
|
1. Add Etcher rpm repository:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo wget https://balena.io/etcher/static/etcher-rpm.repo -O /etc/yum.repos.d/etcher-rpm.repo
|
sudo sudo dnf config-manager --add-repo https://balena.io/etcher/static/etcher-rpm.repo
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Update and install:
|
2. Update and install:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo yum install -y balena-etcher-electron
|
sudo dnf install -y balena-etcher-electron
|
||||||
```
|
```
|
||||||
or
|
|
||||||
```sh
|
|
||||||
sudo dnf install -y balena-etcher-electron
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Uninstall
|
###### Uninstall
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf remove -y balena-etcher-electron
|
||||||
|
sudo rm /etc/yum.repos.d/etcher-rpm.repo
|
||||||
|
sudo dnf clean all
|
||||||
|
sudo dnf makecache
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Yum
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Uninstall
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo yum remove -y balena-etcher-electron
|
sudo yum remove -y balena-etcher-electron
|
||||||
@ -100,13 +121,6 @@ sudo rm /etc/yum.repos.d/etcher-rpm.repo
|
|||||||
sudo yum clean all
|
sudo yum clean all
|
||||||
sudo yum makecache fast
|
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)
|
#### Solus (GNU/Linux x64)
|
||||||
|
|
||||||
@ -120,11 +134,10 @@ sudo eopkg it etcher
|
|||||||
sudo eopkg rm etcher
|
sudo eopkg rm etcher
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Arch Linux / Manjaro (GNU/Linux x64)
|
#### Arch/Manjaro Linux (GNU/Linux x64)
|
||||||
|
|
||||||
Etcher is offered through the Arch User Repository and can be installed on both Manjaro and Arch systems. You can compile it from the source code in this repository using [`balena-etcher`](https://aur.archlinux.org/packages/balena-etcher/). The following example uses a common AUR helper to install the latest release:
|
Etcher is offered through the Arch User Repository and can be installed on both Manjaro and Arch systems. You can compile it from the source code in this repository using [`balena-etcher`](https://aur.archlinux.org/packages/balena-etcher/). The following example uses a common AUR helper to install the latest release:
|
||||||
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yay -S balena-etcher
|
yay -S balena-etcher
|
||||||
```
|
```
|
||||||
@ -135,20 +148,20 @@ yay -S balena-etcher
|
|||||||
yay -R balena-etcher
|
yay -R balena-etcher
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Brew Cask (macOS)
|
#### Brew (macOS)
|
||||||
|
|
||||||
Note that the Etcher Cask has to be updated manually to point to new versions,
|
**Note**: Etcher has to be updated manually to point to new versions,
|
||||||
so it might not refer to the latest version immediately after an Etcher
|
so it might not refer to the latest version immediately after an Etcher
|
||||||
release.
|
release.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew cask install balenaetcher
|
brew install balenaetcher
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Uninstall
|
##### Uninstall
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew cask uninstall balenaetcher
|
brew uninstall balenaetcher
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Chocolatey (Windows)
|
#### Chocolatey (Windows)
|
||||||
@ -168,20 +181,20 @@ choco uninstall etcher
|
|||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
If you're having any problem, please [raise an issue][newissue] on GitHub and
|
If you're having any problem, please [raise an issue][newissue] on GitHub, and
|
||||||
the balena.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
|
Etcher is free software and may be redistributed under the terms specified in
|
||||||
the [license].
|
the [license].
|
||||||
|
|
||||||
[etcher]: https://balena.io/etcher
|
[etcher]: https://balena.io/etcher
|
||||||
[electron]: https://electronjs.org/
|
[electron]: https://electronjs.org/
|
||||||
[electron-supported-platforms]: https://electronjs.org/docs/tutorial/support#supported-platforms
|
[electron-supported-platforms]: https://electronjs.org/docs/tutorial/support#supported-platforms
|
||||||
[SUPPORT]: https://github.com/balena-io/etcher/blob/master/SUPPORT.md
|
[support]: https://github.com/balena-io/etcher/blob/master/SUPPORT.md
|
||||||
[CONTRIBUTING]: https://github.com/balena-io/etcher/blob/master/docs/CONTRIBUTING.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
|
[user-documentation]: https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md
|
||||||
[milestones]: https://github.com/balena-io/etcher/milestones
|
[milestones]: https://github.com/balena-io/etcher/milestones
|
||||||
[newissue]: https://github.com/balena-io/etcher/issues/new
|
[newissue]: https://github.com/balena-io/etcher/issues/new
|
||||||
[license]: https://github.com/balena-io/etcher/blob/master/LICENSE
|
[license]: https://github.com/balena-io/etcher/blob/master/LICENSE
|
||||||
|
@ -6,21 +6,28 @@ const process = require('process');
|
|||||||
|
|
||||||
// Rebuild native modules for ia32 and run webpack again for the ia32 part of windows packages
|
// Rebuild native modules for ia32 and run webpack again for the ia32 part of windows packages
|
||||||
exports.default = function(context) {
|
exports.default = function(context) {
|
||||||
if (context.platform.name === 'windows') {
|
if (['windows', 'mac'].includes(context.platform.name)) {
|
||||||
cp.execFileSync(
|
const run = context.platform.name === 'windows' ? 'sh' : 'node';
|
||||||
'bash',
|
cp.execFileSync(
|
||||||
['./node_modules/.bin/electron-rebuild', '--types', 'dev', '--arch', context.arch],
|
run,
|
||||||
);
|
['node_modules/.bin/electron-rebuild', '--types', 'dev', '--arch', context.arch],
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
npm_config_msvs_version: '2019',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
rimraf.sync('generated');
|
rimraf.sync('generated');
|
||||||
cp.execFileSync(
|
cp.execFileSync(
|
||||||
'bash',
|
run,
|
||||||
['./node_modules/.bin/webpack'],
|
['node_modules/.bin/webpack'],
|
||||||
{
|
{
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
npm_config_target_arch: context.arch,
|
npm_config_target_arch: context.arch,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
appId: io.balena.etcher
|
appId: io.balena.etcher
|
||||||
copyright: Copyright 2016-2020 Balena Ltd
|
copyright: Copyright 2016-2021 Balena Ltd
|
||||||
productName: balenaEtcher
|
productName: balenaEtcher
|
||||||
npmRebuild: true
|
npmRebuild: true
|
||||||
nodeGypRebuild: false
|
nodeGypRebuild: false
|
||||||
@ -16,6 +16,7 @@ mac:
|
|||||||
hardenedRuntime: true
|
hardenedRuntime: true
|
||||||
entitlements: "entitlements.mac.plist"
|
entitlements: "entitlements.mac.plist"
|
||||||
entitlementsInherit: "entitlements.mac.plist"
|
entitlementsInherit: "entitlements.mac.plist"
|
||||||
|
artifactName: "${productName}-${version}.${ext}"
|
||||||
dmg:
|
dmg:
|
||||||
background: assets/dmg/background.tiff
|
background: assets/dmg/background.tiff
|
||||||
icon: assets/icon.icns
|
icon: assets/icon.icns
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Drive as DrivelistDrive } from 'drivelist';
|
import { Drive as DrivelistDrive } from 'drivelist';
|
||||||
import * as electron from 'electron';
|
|
||||||
import * as sdk from 'etcher-sdk';
|
import * as sdk from 'etcher-sdk';
|
||||||
import { Dictionary } from 'lodash';
|
import { Dictionary } from 'lodash';
|
||||||
import * as ipc from 'node-ipc';
|
import * as ipc from 'node-ipc';
|
||||||
@ -25,6 +24,7 @@ import * as path from 'path';
|
|||||||
import * as packageJSON from '../../../../package.json';
|
import * as packageJSON from '../../../../package.json';
|
||||||
import * as errors from '../../../shared/errors';
|
import * as errors from '../../../shared/errors';
|
||||||
import * as permissions from '../../../shared/permissions';
|
import * as permissions from '../../../shared/permissions';
|
||||||
|
import { getAppPath } from '../../../shared/utils';
|
||||||
import { SourceMetadata } from '../components/source-selector/source-selector';
|
import { SourceMetadata } from '../components/source-selector/source-selector';
|
||||||
import * as flashState from '../models/flash-state';
|
import * as flashState from '../models/flash-state';
|
||||||
import * as selectionState from '../models/selection-state';
|
import * as selectionState from '../models/selection-state';
|
||||||
@ -93,11 +93,7 @@ function terminateServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writerArgv(): string[] {
|
function writerArgv(): string[] {
|
||||||
let entryPoint = path.join(
|
let entryPoint = path.join(getAppPath(), 'generated', 'child-writer.js');
|
||||||
electron.remote.app.getAppPath(),
|
|
||||||
'generated',
|
|
||||||
'child-writer.js',
|
|
||||||
);
|
|
||||||
// AppImages run over FUSE, so the files inside the mount point
|
// AppImages run over FUSE, so the files inside the mount point
|
||||||
// can only be accessed by the user that mounted the AppImage.
|
// can only be accessed by the user that mounted the AppImage.
|
||||||
// This means we can't re-spawn Etcher as root from the same
|
// This means we can't re-spawn Etcher as root from the same
|
||||||
|
@ -278,7 +278,7 @@ export class MainPage extends React.Component<
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
'-webkit-app-region': 'drag',
|
'-webkit-app-region': 'drag',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
zIndex: 1,
|
zIndex: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex width="100%" />
|
<Flex width="100%" />
|
||||||
|
@ -147,6 +147,7 @@ async function createMainWindow() {
|
|||||||
webPreferences: {
|
webPreferences: {
|
||||||
backgroundThrottling: false,
|
backgroundThrottling: false,
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false,
|
||||||
webviewTag: true,
|
webviewTag: true,
|
||||||
zoomFactor: width / defaultWidth,
|
zoomFactor: width / defaultWidth,
|
||||||
enableRemoteModule: true,
|
enableRemoteModule: true,
|
||||||
|
@ -15,11 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { execFile } from 'child_process';
|
import { execFile } from 'child_process';
|
||||||
import { app, remote } from 'electron';
|
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { env } from 'process';
|
import { env } from 'process';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
|
|
||||||
|
import { getAppPath } from '../utils';
|
||||||
|
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
const SUCCESSFUL_AUTH_MARKER = 'AUTHENTICATION SUCCEEDED';
|
const SUCCESSFUL_AUTH_MARKER = 'AUTHENTICATION SUCCEEDED';
|
||||||
@ -37,7 +38,7 @@ export async function sudo(
|
|||||||
env: {
|
env: {
|
||||||
PATH: env.PATH,
|
PATH: env.PATH,
|
||||||
SUDO_ASKPASS: join(
|
SUDO_ASKPASS: join(
|
||||||
(app || remote.app).getAppPath(),
|
getAppPath(),
|
||||||
__dirname,
|
__dirname,
|
||||||
'sudo-askpass.osascript.js',
|
'sudo-askpass.osascript.js',
|
||||||
),
|
),
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { app, remote } from 'electron';
|
||||||
import { Dictionary } from 'lodash';
|
import { Dictionary } from 'lodash';
|
||||||
|
|
||||||
import * as errors from './errors';
|
import * as errors from './errors';
|
||||||
@ -47,3 +48,16 @@ export async function delay(duration: number): Promise<void> {
|
|||||||
setTimeout(resolve, duration);
|
setTimeout(resolve, duration);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAppPath(): string {
|
||||||
|
return (
|
||||||
|
(app || remote.app)
|
||||||
|
.getAppPath()
|
||||||
|
// With macOS universal builds, getAppPath() returns the path to an app.asar file containing an index.js file which will
|
||||||
|
// include the app-x64 or app-arm64 folder depending on the arch.
|
||||||
|
// We don't care about the app.asar file, we want the actual folder.
|
||||||
|
.replace(/\.asar$/, () =>
|
||||||
|
process.platform === 'darwin' ? '-' + process.arch : '',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
3758
npm-shrinkwrap.json
generated
3758
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@ -46,6 +46,14 @@
|
|||||||
"author": "Balena Inc. <hello@etcher.io>",
|
"author": "Balena Inc. <hello@etcher.io>",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"platformSpecificDependencies": [
|
"platformSpecificDependencies": [
|
||||||
|
"xmlbuilder",
|
||||||
|
"xmldom",
|
||||||
|
"@types/plist",
|
||||||
|
"@types/verror",
|
||||||
|
"crc",
|
||||||
|
"iconv-corefoundation",
|
||||||
|
"plist",
|
||||||
|
"dmg-license",
|
||||||
"fsevents",
|
"fsevents",
|
||||||
"winusb-driver-generator"
|
"winusb-driver-generator"
|
||||||
],
|
],
|
||||||
@ -66,18 +74,19 @@
|
|||||||
"@types/terser-webpack-plugin": "^5.0.2",
|
"@types/terser-webpack-plugin": "^5.0.2",
|
||||||
"@types/tmp": "^0.2.0",
|
"@types/tmp": "^0.2.0",
|
||||||
"@types/webpack-node-externals": "^2.5.0",
|
"@types/webpack-node-externals": "^2.5.0",
|
||||||
|
"aws4-axios": "2.2.1",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"copy-webpack-plugin": "^7.0.0",
|
"copy-webpack-plugin": "^7.0.0",
|
||||||
"css-loader": "^5.0.1",
|
"css-loader": "^5.0.1",
|
||||||
"d3": "^4.13.0",
|
"d3": "^4.13.0",
|
||||||
"debug": "^4.2.0",
|
"debug": "^4.2.0",
|
||||||
"electron": "9.4.1",
|
"electron": "12.0.2",
|
||||||
"electron-builder": "^22.9.1",
|
"electron-builder": "^22.10.5",
|
||||||
"electron-mocha": "^9.3.2",
|
"electron-mocha": "^9.3.2",
|
||||||
"electron-notarize": "^1.0.0",
|
"electron-notarize": "^1.0.0",
|
||||||
"electron-rebuild": "^2.3.2",
|
"electron-rebuild": "^2.3.2",
|
||||||
"electron-updater": "^4.3.5",
|
"electron-updater": "^4.3.5",
|
||||||
"etcher-sdk": "^6.1.0",
|
"etcher-sdk": "^6.2.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"husky": "^4.2.5",
|
"husky": "^4.2.5",
|
||||||
"immutable": "^3.8.1",
|
"immutable": "^3.8.1",
|
||||||
@ -99,7 +108,7 @@
|
|||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
"simple-progress-webpack-plugin": "^1.1.2",
|
"simple-progress-webpack-plugin": "^1.1.2",
|
||||||
"sinon": "^9.0.2",
|
"sinon": "^9.0.2",
|
||||||
"spectron": "^11.0.0",
|
"spectron": "^14.0.0",
|
||||||
"string-replace-loader": "^3.0.1",
|
"string-replace-loader": "^3.0.1",
|
||||||
"styled-components": "^5.1.0",
|
"styled-components": "^5.1.0",
|
||||||
"sudo-prompt": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91",
|
"sudo-prompt": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91",
|
||||||
|
@ -29,6 +29,10 @@ const SHRINKWRAP_FILENAME = path.join(__dirname, '..', 'npm-shrinkwrap.json');
|
|||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
const cleaned = omit(shrinkwrap, packageInfo.platformSpecificDependencies);
|
const cleaned = omit(shrinkwrap, packageInfo.platformSpecificDependencies);
|
||||||
|
for (const item of Object.values(cleaned.dependencies)) {
|
||||||
|
// @ts-ignore
|
||||||
|
item.dev = true;
|
||||||
|
}
|
||||||
await writeFileAsync(
|
await writeFileAsync(
|
||||||
SHRINKWRAP_FILENAME,
|
SHRINKWRAP_FILENAME,
|
||||||
JSON.stringify(cleaned, null, JSON_INDENT),
|
JSON.stringify(cleaned, null, JSON_INDENT),
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 214ddc7e3d35f7c37424c5a7696e33b10e424f43
|
Subproject commit d1b05ad312e65ea82b1c16b31f5af3c0b5fa2777
|
@ -15,46 +15,52 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
|
import { platform } from 'os';
|
||||||
import { Application } from 'spectron';
|
import { Application } from 'spectron';
|
||||||
import * as electronPath from 'electron';
|
import * as electronPath from 'electron';
|
||||||
|
|
||||||
describe('Spectron', function () {
|
// TODO: spectron fails to start on the CI with:
|
||||||
// Mainly for CI jobs
|
// Error: Failed to create session.
|
||||||
this.timeout(40000);
|
// unknown error: Chrome failed to start: exited abnormally
|
||||||
|
if (platform() !== 'darwin') {
|
||||||
|
describe('Spectron', function () {
|
||||||
|
// Mainly for CI jobs
|
||||||
|
this.timeout(40000);
|
||||||
|
|
||||||
const app = new Application({
|
const app = new Application({
|
||||||
path: (electronPath as unknown) as string,
|
path: (electronPath as unknown) as string,
|
||||||
args: ['--no-sandbox', '.'],
|
args: ['--no-sandbox', '.'],
|
||||||
});
|
|
||||||
|
|
||||||
before('app:start', async () => {
|
|
||||||
await app.start();
|
|
||||||
});
|
|
||||||
|
|
||||||
after('app:stop', async () => {
|
|
||||||
if (app && app.isRunning()) {
|
|
||||||
await app.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Browser Window', () => {
|
|
||||||
it('should open a browser window', async () => {
|
|
||||||
// We can't use `isVisible()` here as it won't work inside
|
|
||||||
// a Windows Docker container, but we can approximate it
|
|
||||||
// with these set of checks:
|
|
||||||
const bounds = await app.browserWindow.getBounds();
|
|
||||||
expect(bounds.height).to.be.above(0);
|
|
||||||
expect(bounds.width).to.be.above(0);
|
|
||||||
expect(await app.browserWindow.isMinimized()).to.be.false;
|
|
||||||
expect(
|
|
||||||
(await app.browserWindow.isVisible()) ||
|
|
||||||
(await app.browserWindow.isFocused()),
|
|
||||||
).to.be.true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set a proper title', async () => {
|
before('app:start', async () => {
|
||||||
// @ts-ignore (SpectronClient.getTitle exists)
|
await app.start();
|
||||||
return expect(await app.client.getTitle()).to.equal('Etcher');
|
});
|
||||||
|
|
||||||
|
after('app:stop', async () => {
|
||||||
|
if (app && app.isRunning()) {
|
||||||
|
await app.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Browser Window', () => {
|
||||||
|
it('should open a browser window', async () => {
|
||||||
|
// We can't use `isVisible()` here as it won't work inside
|
||||||
|
// a Windows Docker container, but we can approximate it
|
||||||
|
// with these set of checks:
|
||||||
|
const bounds = await app.browserWindow.getBounds();
|
||||||
|
expect(bounds.height).to.be.above(0);
|
||||||
|
expect(bounds.width).to.be.above(0);
|
||||||
|
expect(await app.browserWindow.isMinimized()).to.be.false;
|
||||||
|
expect(
|
||||||
|
(await app.browserWindow.isVisible()) ||
|
||||||
|
(await app.browserWindow.isFocused()),
|
||||||
|
).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set a proper title', async () => {
|
||||||
|
// @ts-ignore (SpectronClient.getTitle exists)
|
||||||
|
return expect(await app.client.getTitle()).to.equal('Etcher');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
@ -68,6 +68,8 @@ function renameNodeModules(resourcePath: string) {
|
|||||||
path
|
path
|
||||||
.relative(__dirname, resourcePath)
|
.relative(__dirname, resourcePath)
|
||||||
.replace('node_modules', 'modules')
|
.replace('node_modules', 'modules')
|
||||||
|
// use the same name on all architectures so electron-builder can build a universal dmg on mac
|
||||||
|
.replace(LZMA_BINDINGS_FOLDER, LZMA_BINDINGS_FOLDER_RENAMED)
|
||||||
// file-loader expects posix paths, even on Windows
|
// file-loader expects posix paths, even on Windows
|
||||||
.replace(/\\/g, '/')
|
.replace(/\\/g, '/')
|
||||||
);
|
);
|
||||||
@ -87,6 +89,7 @@ function findLzmaNativeBindingsFolder(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const LZMA_BINDINGS_FOLDER = findLzmaNativeBindingsFolder();
|
const LZMA_BINDINGS_FOLDER = findLzmaNativeBindingsFolder();
|
||||||
|
const LZMA_BINDINGS_FOLDER_RENAMED = 'binding';
|
||||||
|
|
||||||
interface ReplacementRule {
|
interface ReplacementRule {
|
||||||
search: string;
|
search: string;
|
||||||
@ -117,7 +120,15 @@ function fetchWasm(...where: string[]) {
|
|||||||
} catch {
|
} catch {
|
||||||
}
|
}
|
||||||
function appPath() {
|
function appPath() {
|
||||||
return Path.isAbsolute(__dirname) ? __dirname : Path.join(electron.remote.app.getAppPath(), 'generated');
|
return Path.isAbsolute(__dirname) ?
|
||||||
|
__dirname :
|
||||||
|
Path.join(
|
||||||
|
// With macOS universal builds, getAppPath() returns the path to an app.asar file containing an index.js file which will
|
||||||
|
// include the app-x64 or app-arm64 folder depending on the arch.
|
||||||
|
// We don't care about the app.asar file, we want the actual folder.
|
||||||
|
electron.remote.app.getAppPath().replace(/\\.asar$/, () => process.platform === 'darwin' ? '-' + process.arch : ''),
|
||||||
|
'generated'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
scriptDirectory = Path.join(appPath(), 'modules', ${whereStr}, '/');
|
scriptDirectory = Path.join(appPath(), 'modules', ${whereStr}, '/');
|
||||||
`;
|
`;
|
||||||
@ -126,6 +137,7 @@ function fetchWasm(...where: string[]) {
|
|||||||
const commonConfig = {
|
const commonConfig = {
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
optimization: {
|
optimization: {
|
||||||
|
moduleIds: 'natural',
|
||||||
minimize: true,
|
minimize: true,
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new TerserPlugin({
|
new TerserPlugin({
|
||||||
@ -190,12 +202,7 @@ const commonConfig = {
|
|||||||
// remove node-pre-gyp magic from lzma-native
|
// remove node-pre-gyp magic from lzma-native
|
||||||
{
|
{
|
||||||
search: 'require(binding_path)',
|
search: 'require(binding_path)',
|
||||||
replace: () => {
|
replace: `require('./${LZMA_BINDINGS_FOLDER}/lzma_native.node')`,
|
||||||
return `require('./${path.posix.join(
|
|
||||||
LZMA_BINDINGS_FOLDER,
|
|
||||||
'lzma_native.node',
|
|
||||||
)}')`;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
// use regular stream module instead of readable-stream
|
// use regular stream module instead of readable-stream
|
||||||
{
|
{
|
||||||
@ -239,7 +246,19 @@ const commonConfig = {
|
|||||||
"return await readFile(Path.join(__dirname, '..', 'blobs', filename));",
|
"return await readFile(Path.join(__dirname, '..', 'blobs', filename));",
|
||||||
replace: outdent`
|
replace: outdent`
|
||||||
const { app, remote } = require('electron');
|
const { app, remote } = require('electron');
|
||||||
return await readFile(Path.join((app || remote.app).getAppPath(), 'generated', __dirname.replace('node_modules', 'modules'), '..', 'blobs', filename));
|
return await readFile(
|
||||||
|
Path.join(
|
||||||
|
// With macOS universal builds, getAppPath() returns the path to an app.asar file containing an index.js file which will
|
||||||
|
// include the app-x64 or app-arm64 folder depending on the arch.
|
||||||
|
// We don't care about the app.asar file, we want the actual folder.
|
||||||
|
(app || remote.app).getAppPath().replace(/\\.asar$/, () => process.platform === 'darwin' ? '-' + process.arch : ''),
|
||||||
|
'generated',
|
||||||
|
__dirname.replace('node_modules', 'modules'),
|
||||||
|
'..',
|
||||||
|
'blobs',
|
||||||
|
filename
|
||||||
|
)
|
||||||
|
);
|
||||||
`,
|
`,
|
||||||
}),
|
}),
|
||||||
// Use the libext2fs.wasm file in the generated folder
|
// Use the libext2fs.wasm file in the generated folder
|
||||||
@ -317,7 +336,7 @@ if (os.platform() === 'win32') {
|
|||||||
// liblzma.dll is required on Windows for lzma-native
|
// liblzma.dll is required on Windows for lzma-native
|
||||||
guiConfigCopyPatterns.push({
|
guiConfigCopyPatterns.push({
|
||||||
from: `node_modules/lzma-native/${LZMA_BINDINGS_FOLDER}/liblzma.dll`,
|
from: `node_modules/lzma-native/${LZMA_BINDINGS_FOLDER}/liblzma.dll`,
|
||||||
to: `modules/lzma-native/${LZMA_BINDINGS_FOLDER}/liblzma.dll`,
|
to: `modules/lzma-native/${LZMA_BINDINGS_FOLDER_RENAMED}/liblzma.dll`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user