AppUpdater.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.NoOpLogger = exports.AppUpdater = void 0;
  6. function _bluebirdLst() {
  7. const data = require("bluebird-lst");
  8. _bluebirdLst = function () {
  9. return data;
  10. };
  11. return data;
  12. }
  13. function _builderUtilRuntime() {
  14. const data = require("builder-util-runtime");
  15. _builderUtilRuntime = function () {
  16. return data;
  17. };
  18. return data;
  19. }
  20. function _crypto() {
  21. const data = require("crypto");
  22. _crypto = function () {
  23. return data;
  24. };
  25. return data;
  26. }
  27. function _electron() {
  28. const data = require("electron");
  29. _electron = function () {
  30. return data;
  31. };
  32. return data;
  33. }
  34. function _electronIsDev() {
  35. const data = _interopRequireDefault(require("electron-is-dev"));
  36. _electronIsDev = function () {
  37. return data;
  38. };
  39. return data;
  40. }
  41. function _events() {
  42. const data = require("events");
  43. _events = function () {
  44. return data;
  45. };
  46. return data;
  47. }
  48. function _fsExtraP() {
  49. const data = require("fs-extra-p");
  50. _fsExtraP = function () {
  51. return data;
  52. };
  53. return data;
  54. }
  55. function _jsYaml() {
  56. const data = require("js-yaml");
  57. _jsYaml = function () {
  58. return data;
  59. };
  60. return data;
  61. }
  62. function _lazyVal() {
  63. const data = require("lazy-val");
  64. _lazyVal = function () {
  65. return data;
  66. };
  67. return data;
  68. }
  69. var path = _interopRequireWildcard(require("path"));
  70. function _semver() {
  71. const data = require("semver");
  72. _semver = function () {
  73. return data;
  74. };
  75. return data;
  76. }
  77. require("source-map-support/register");
  78. function _DownloadedUpdateHelper() {
  79. const data = require("./DownloadedUpdateHelper");
  80. _DownloadedUpdateHelper = function () {
  81. return data;
  82. };
  83. return data;
  84. }
  85. function _electronHttpExecutor() {
  86. const data = require("./electronHttpExecutor");
  87. _electronHttpExecutor = function () {
  88. return data;
  89. };
  90. return data;
  91. }
  92. function _GenericProvider() {
  93. const data = require("./providers/GenericProvider");
  94. _GenericProvider = function () {
  95. return data;
  96. };
  97. return data;
  98. }
  99. function _main() {
  100. const data = require("./main");
  101. _main = function () {
  102. return data;
  103. };
  104. return data;
  105. }
  106. function _providerFactory() {
  107. const data = require("./providerFactory");
  108. _providerFactory = function () {
  109. return data;
  110. };
  111. return data;
  112. }
  113. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
  114. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  115. class AppUpdater extends _events().EventEmitter {
  116. constructor(options, app) {
  117. super();
  118. /**
  119. * Whether to automatically download an update when it is found.
  120. */
  121. this.autoDownload = true;
  122. /**
  123. * Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).
  124. *
  125. * Applicable only on Windows and Linux.
  126. */
  127. this.autoInstallOnAppQuit = true;
  128. /**
  129. * *GitHub provider only.* Whether to allow update to pre-release versions. Defaults to `true` if application version contains prerelease components (e.g. `0.12.1-alpha.1`, here `alpha` is a prerelease component), otherwise `false`.
  130. *
  131. * If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).
  132. */
  133. this.allowPrerelease = false;
  134. /**
  135. * *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.
  136. * @default false
  137. */
  138. this.fullChangelog = false;
  139. /**
  140. * Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
  141. *
  142. * Taken in account only if channel differs (pre-release version component in terms of semantic versioning).
  143. *
  144. * @default false
  145. */
  146. this.allowDowngrade = false;
  147. this._channel = null;
  148. /**
  149. * The request headers.
  150. */
  151. this.requestHeaders = null;
  152. this._logger = console; // noinspection JSUnusedGlobalSymbols
  153. /**
  154. * For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`
  155. */
  156. this.signals = new (_main().UpdaterSignal)(this);
  157. this._appUpdateConfigPath = null;
  158. this.clientPromise = null;
  159. this.stagingUserIdPromise = new (_lazyVal().Lazy)(() => this.getOrCreateStagingUserId()); // public, allow to read old config for anyone
  160. /** @internal */
  161. this.configOnDisk = new (_lazyVal().Lazy)(() => this.loadUpdateConfig());
  162. this.checkForUpdatesPromise = null;
  163. this.updateInfo = null;
  164. this.on("error", error => {
  165. this._logger.error(`Error: ${error.stack || error.message}`);
  166. });
  167. if (app != null || global.__test_app != null) {
  168. this.app = app || global.__test_app;
  169. this.untilAppReady = Promise.resolve();
  170. this.httpExecutor = null;
  171. } else {
  172. this.app = require("electron").app;
  173. this.httpExecutor = new (_electronHttpExecutor().ElectronHttpExecutor)((authInfo, callback) => this.emit("login", authInfo, callback));
  174. this.untilAppReady = new Promise(resolve => {
  175. if (this.app.isReady()) {
  176. resolve();
  177. } else {
  178. this.app.on("ready", resolve);
  179. }
  180. });
  181. }
  182. this.downloadedUpdateHelper = new (_DownloadedUpdateHelper().DownloadedUpdateHelper)(path.join(this.app.getPath("userData"), "__update__"));
  183. const currentVersionString = this.app.getVersion();
  184. const currentVersion = (0, _semver().parse)(currentVersionString);
  185. if (currentVersion == null) {
  186. throw (0, _builderUtilRuntime().newError)(`App version is not a valid semver version: "${currentVersionString}"`, "ERR_UPDATER_INVALID_VERSION");
  187. }
  188. this.currentVersion = currentVersion;
  189. this.allowPrerelease = hasPrereleaseComponents(currentVersion);
  190. if (options != null) {
  191. this.setFeedURL(options);
  192. }
  193. }
  194. /**
  195. * Get the update channel. Not applicable for GitHub. Doesn't return `channel` from the update configuration, only if was previously set.
  196. */
  197. get channel() {
  198. return this._channel;
  199. }
  200. /**
  201. * Set the update channel. Not applicable for GitHub. Overrides `channel` in the update configuration.
  202. *
  203. * `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.
  204. */
  205. set channel(value) {
  206. if (this._channel != null) {
  207. // noinspection SuspiciousTypeOfGuard
  208. if (typeof value !== "string") {
  209. throw (0, _builderUtilRuntime().newError)(`Channel must be a string, but got: ${value}`, "ERR_UPDATER_INVALID_CHANNEL");
  210. } else if (value.length === 0) {
  211. throw (0, _builderUtilRuntime().newError)(`Channel must be not an empty string`, "ERR_UPDATER_INVALID_CHANNEL");
  212. }
  213. }
  214. this._channel = value;
  215. this.allowDowngrade = true;
  216. }
  217. /**
  218. * The logger. You can pass [electron-log](https://github.com/megahertz/electron-log), [winston](https://github.com/winstonjs/winston) or another logger with the following interface: `{ info(), warn(), error() }`.
  219. * Set it to `null` if you would like to disable a logging feature.
  220. */
  221. get logger() {
  222. return this._logger;
  223. }
  224. set logger(value) {
  225. this._logger = value == null ? new NoOpLogger() : value;
  226. } // noinspection JSUnusedGlobalSymbols
  227. /**
  228. * test only
  229. * @private
  230. */
  231. set updateConfigPath(value) {
  232. this.clientPromise = null;
  233. this._appUpdateConfigPath = value;
  234. this.configOnDisk = new (_lazyVal().Lazy)(() => this.loadUpdateConfig());
  235. }
  236. get provider() {
  237. return this.clientPromise;
  238. } //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
  239. getFeedURL() {
  240. return "Deprecated. Do not use it.";
  241. }
  242. /**
  243. * Configure update provider. If value is `string`, [GenericServerOptions](/configuration/publish.md#genericserveroptions) will be set with value as `url`.
  244. * @param options If you want to override configuration in the `app-update.yml`.
  245. */
  246. setFeedURL(options) {
  247. // https://github.com/electron-userland/electron-builder/issues/1105
  248. let provider;
  249. if (typeof options === "string") {
  250. provider = new (_GenericProvider().GenericProvider)({
  251. provider: "generic",
  252. url: options
  253. }, this, (0, _providerFactory().isUrlProbablySupportMultiRangeRequests)(options));
  254. } else {
  255. provider = (0, _providerFactory().createClient)(options, this);
  256. }
  257. this.clientPromise = Promise.resolve(provider);
  258. }
  259. /**
  260. * Asks the server whether there is an update.
  261. */
  262. checkForUpdates() {
  263. let checkForUpdatesPromise = this.checkForUpdatesPromise;
  264. if (checkForUpdatesPromise != null) {
  265. return checkForUpdatesPromise;
  266. }
  267. checkForUpdatesPromise = this._checkForUpdates();
  268. this.checkForUpdatesPromise = checkForUpdatesPromise;
  269. const nullizePromise = () => this.checkForUpdatesPromise = null;
  270. checkForUpdatesPromise.then(nullizePromise).catch(nullizePromise);
  271. return checkForUpdatesPromise;
  272. }
  273. checkForUpdatesAndNotify() {
  274. if (_electronIsDev().default) {
  275. return Promise.resolve(null);
  276. }
  277. const checkForUpdatesPromise = this.checkForUpdates();
  278. checkForUpdatesPromise.then(it => {
  279. const downloadPromise = it.downloadPromise;
  280. if (downloadPromise == null) {
  281. const debug = this._logger.debug;
  282. if (debug != null) {
  283. debug("checkForUpdatesAndNotify called, downloadPromise is null");
  284. }
  285. return;
  286. }
  287. downloadPromise.then(() => {
  288. new (_electron().Notification)({
  289. title: "A new update is ready to install",
  290. body: `${this.app.getName()} version ${it.updateInfo.version} is downloaded and will be automatically installed on exit`
  291. }).show();
  292. });
  293. });
  294. return checkForUpdatesPromise;
  295. }
  296. isStagingMatch(updateInfo) {
  297. var _this = this;
  298. return (0, _bluebirdLst().coroutine)(function* () {
  299. const rawStagingPercentage = updateInfo.stagingPercentage;
  300. let stagingPercentage = rawStagingPercentage;
  301. if (stagingPercentage == null) {
  302. return true;
  303. }
  304. stagingPercentage = parseInt(stagingPercentage, 10);
  305. if (isNaN(stagingPercentage)) {
  306. _this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`);
  307. return true;
  308. } // convert from user 0-100 to internal 0-1
  309. stagingPercentage = stagingPercentage / 100;
  310. const stagingUserId = yield _this.stagingUserIdPromise.value;
  311. const val = _builderUtilRuntime().UUID.parse(stagingUserId).readUInt32BE(12);
  312. const percentage = val / 0xFFFFFFFF;
  313. _this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`);
  314. return percentage < stagingPercentage;
  315. })();
  316. }
  317. _checkForUpdates() {
  318. var _this2 = this;
  319. return (0, _bluebirdLst().coroutine)(function* () {
  320. try {
  321. yield _this2.untilAppReady;
  322. _this2._logger.info("Checking for update");
  323. _this2.emit("checking-for-update");
  324. return yield _this2.doCheckForUpdates();
  325. } catch (e) {
  326. _this2.emit("error", e, `Cannot check for updates: ${(e.stack || e).toString()}`);
  327. throw e;
  328. }
  329. })();
  330. }
  331. computeFinalHeaders(headers) {
  332. if (this.requestHeaders != null) {
  333. Object.assign(headers, this.requestHeaders);
  334. }
  335. return headers;
  336. }
  337. isUpdateAvailable(updateInfo) {
  338. var _this3 = this;
  339. return (0, _bluebirdLst().coroutine)(function* () {
  340. const latestVersion = (0, _semver().parse)(updateInfo.version);
  341. if (latestVersion == null) {
  342. throw (0, _builderUtilRuntime().newError)(`This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: "${latestVersion}"`, "ERR_UPDATER_INVALID_VERSION");
  343. }
  344. const currentVersion = _this3.currentVersion;
  345. if ((0, _semver().eq)(latestVersion, currentVersion)) {
  346. return false;
  347. }
  348. const isStagingMatch = yield _this3.isStagingMatch(updateInfo);
  349. if (!isStagingMatch) {
  350. return false;
  351. } // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227
  352. // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797
  353. const isLatestVersionNewer = (0, _semver().gt)(latestVersion, currentVersion);
  354. if (!_this3.allowDowngrade) {
  355. return isLatestVersionNewer;
  356. }
  357. const currentVersionPrereleaseComponent = (0, _semver().prerelease)(currentVersion);
  358. const latestVersionPrereleaseComponent = (0, _semver().prerelease)(latestVersion);
  359. if (currentVersionPrereleaseComponent === latestVersionPrereleaseComponent) {
  360. // allowDowngrade taken in account only if channel differs
  361. return isLatestVersionNewer;
  362. }
  363. return true;
  364. })();
  365. }
  366. getUpdateInfo() {
  367. var _this4 = this;
  368. return (0, _bluebirdLst().coroutine)(function* () {
  369. yield _this4.untilAppReady;
  370. if (_this4.clientPromise == null) {
  371. _this4.clientPromise = _this4.configOnDisk.value.then(it => (0, _providerFactory().createClient)(it, _this4));
  372. }
  373. const client = yield _this4.clientPromise;
  374. const stagingUserId = yield _this4.stagingUserIdPromise.value;
  375. client.setRequestHeaders(_this4.computeFinalHeaders({
  376. "x-user-staging-id": stagingUserId
  377. }));
  378. return yield client.getLatestVersion();
  379. })();
  380. }
  381. doCheckForUpdates() {
  382. var _this5 = this;
  383. return (0, _bluebirdLst().coroutine)(function* () {
  384. const updateInfo = yield _this5.getUpdateInfo();
  385. if (!(yield _this5.isUpdateAvailable(updateInfo))) {
  386. _this5._logger.info(`Update for version ${_this5.currentVersion} is not available (latest version: ${updateInfo.version}, downgrade is ${_this5.allowDowngrade ? "allowed" : "disallowed"}).`);
  387. _this5.emit("update-not-available", updateInfo);
  388. return {
  389. versionInfo: updateInfo,
  390. updateInfo
  391. };
  392. }
  393. _this5.updateInfo = updateInfo;
  394. _this5.onUpdateAvailable(updateInfo);
  395. const cancellationToken = new (_builderUtilRuntime().CancellationToken)(); //noinspection ES6MissingAwait
  396. return {
  397. versionInfo: updateInfo,
  398. updateInfo,
  399. cancellationToken,
  400. downloadPromise: _this5.autoDownload ? _this5.downloadUpdate(cancellationToken) : null
  401. };
  402. })();
  403. }
  404. onUpdateAvailable(updateInfo) {
  405. this._logger.info(`Found version ${updateInfo.version} (url: ${(0, _builderUtilRuntime().asArray)(updateInfo.files).map(it => it.url).join(", ")})`);
  406. this.emit("update-available", updateInfo);
  407. }
  408. /**
  409. * Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.
  410. * @returns {Promise<string>} Path to downloaded file.
  411. */
  412. downloadUpdate(cancellationToken = new (_builderUtilRuntime().CancellationToken)()) {
  413. var _this6 = this;
  414. return (0, _bluebirdLst().coroutine)(function* () {
  415. const updateInfo = _this6.updateInfo;
  416. if (updateInfo == null) {
  417. const error = new Error("Please check update first");
  418. _this6.dispatchError(error);
  419. throw error;
  420. }
  421. _this6._logger.info(`Downloading update from ${(0, _builderUtilRuntime().asArray)(updateInfo.files).map(it => it.url).join(", ")}`);
  422. try {
  423. return yield _this6.doDownloadUpdate({
  424. updateInfo,
  425. requestHeaders: yield _this6.computeRequestHeaders(),
  426. cancellationToken
  427. });
  428. } catch (e) {
  429. _this6.dispatchError(e);
  430. throw e;
  431. }
  432. })();
  433. }
  434. dispatchError(e) {
  435. this.emit("error", e, (e.stack || e).toString());
  436. }
  437. loadUpdateConfig() {
  438. var _this7 = this;
  439. return (0, _bluebirdLst().coroutine)(function* () {
  440. if (_this7._appUpdateConfigPath == null) {
  441. _this7._appUpdateConfigPath = _electronIsDev().default ? path.join(_this7.app.getAppPath(), "dev-app-update.yml") : path.join(process.resourcesPath, "app-update.yml");
  442. }
  443. return (0, _jsYaml().safeLoad)((yield (0, _fsExtraP().readFile)(_this7._appUpdateConfigPath, "utf-8")));
  444. })();
  445. }
  446. computeRequestHeaders() {
  447. var _this8 = this;
  448. return (0, _bluebirdLst().coroutine)(function* () {
  449. const fileExtraDownloadHeaders = (yield _this8.provider).fileExtraDownloadHeaders;
  450. if (fileExtraDownloadHeaders != null) {
  451. const requestHeaders = _this8.requestHeaders;
  452. return requestHeaders == null ? fileExtraDownloadHeaders : Object.assign({}, fileExtraDownloadHeaders, requestHeaders);
  453. }
  454. return _this8.computeFinalHeaders({
  455. accept: "*/*"
  456. });
  457. })();
  458. }
  459. getOrCreateStagingUserId() {
  460. var _this9 = this;
  461. return (0, _bluebirdLst().coroutine)(function* () {
  462. const file = path.join(_this9.app.getPath("userData"), ".updaterId");
  463. try {
  464. const id = yield (0, _fsExtraP().readFile)(file, "utf-8");
  465. if (_builderUtilRuntime().UUID.check(id)) {
  466. return id;
  467. } else {
  468. _this9._logger.warn(`Staging user id file exists, but content was invalid: ${id}`);
  469. }
  470. } catch (e) {
  471. if (e.code !== "ENOENT") {
  472. _this9._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`);
  473. }
  474. }
  475. const id = _builderUtilRuntime().UUID.v5((0, _crypto().randomBytes)(4096), _builderUtilRuntime().UUID.OID);
  476. _this9._logger.info(`Generated new staging user ID: ${id}`);
  477. try {
  478. yield (0, _fsExtraP().outputFile)(file, id);
  479. } catch (e) {
  480. _this9._logger.warn(`Couldn't write out staging user ID: ${e}`);
  481. }
  482. return id;
  483. })();
  484. }
  485. /** @internal */
  486. get isAddNoCacheQuery() {
  487. const headers = this.requestHeaders; // https://github.com/electron-userland/electron-builder/issues/3021
  488. if (headers == null) {
  489. return true;
  490. }
  491. for (const headerName of Object.keys(headers)) {
  492. const s = headerName.toLowerCase();
  493. if (s === "authorization" || s === "private-token") {
  494. return false;
  495. }
  496. }
  497. return true;
  498. }
  499. executeDownload(taskOptions) {
  500. var _this10 = this;
  501. return (0, _bluebirdLst().coroutine)(function* () {
  502. const fileInfo = taskOptions.fileInfo;
  503. const downloadOptions = {
  504. skipDirCreation: true,
  505. headers: taskOptions.downloadUpdateOptions.requestHeaders,
  506. cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,
  507. sha2: fileInfo.info.sha2,
  508. sha512: fileInfo.info.sha512
  509. };
  510. if (_this10.listenerCount(_main().DOWNLOAD_PROGRESS) > 0) {
  511. downloadOptions.onProgress = it => _this10.emit(_main().DOWNLOAD_PROGRESS, it);
  512. }
  513. const updateInfo = taskOptions.downloadUpdateOptions.updateInfo;
  514. const version = updateInfo.version;
  515. const packageInfo = fileInfo.packageInfo;
  516. function getCacheUpdateFileName() {
  517. // bloody NodeJS URL doesn't decode automatically
  518. const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname);
  519. if (urlPath.endsWith(`.${taskOptions.fileExtension}`)) {
  520. return path.posix.basename(urlPath);
  521. } else {
  522. // url like /latest, generate name
  523. return `update.${taskOptions.fileExtension}`;
  524. }
  525. }
  526. const cacheDir = _this10.downloadedUpdateHelper.cacheDir;
  527. yield (0, _fsExtraP().ensureDir)(cacheDir);
  528. const updateFileName = getCacheUpdateFileName();
  529. let updateFile = path.join(cacheDir, updateFileName);
  530. const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || ".7z"}`);
  531. const done = (() => {
  532. var _ref = (0, _bluebirdLst().coroutine)(function* (isSaveCache) {
  533. _this10.downloadedUpdateHelper.setDownloadedFile(updateFile, packageFile, updateInfo, fileInfo);
  534. if (isSaveCache) {
  535. yield _this10.downloadedUpdateHelper.cacheUpdateInfo(updateFileName);
  536. }
  537. _this10.emit(_main().UPDATE_DOWNLOADED, updateInfo);
  538. yield taskOptions.done(updateFile);
  539. return packageFile == null ? [updateFile] : [updateFile, packageFile];
  540. });
  541. return function done(_x) {
  542. return _ref.apply(this, arguments);
  543. };
  544. })();
  545. const log = _this10._logger;
  546. const cachedUpdateFile = yield _this10.downloadedUpdateHelper.validateDownloadedPath(updateFile, updateInfo, fileInfo, log);
  547. if (cachedUpdateFile != null) {
  548. updateFile = cachedUpdateFile;
  549. return yield done(false);
  550. }
  551. const removeFileIfAny = (() => {
  552. var _ref2 = (0, _bluebirdLst().coroutine)(function* () {
  553. yield _this10.downloadedUpdateHelper.clear().catch(() => {// ignore
  554. });
  555. return yield (0, _fsExtraP().unlink)(updateFile).catch(() => {// ignore
  556. });
  557. });
  558. return function removeFileIfAny() {
  559. return _ref2.apply(this, arguments);
  560. };
  561. })(); // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912
  562. let nameCounter = 0;
  563. let tempUpdateFile = path.join(cacheDir, `temp-${updateFileName}`);
  564. for (let i = 0; i < 3; i++) {
  565. try {
  566. yield (0, _fsExtraP().unlink)(tempUpdateFile);
  567. } catch (e) {
  568. if (e.code === "ENOENT") {
  569. break;
  570. }
  571. log.warn(`Error on remove temp update file: ${e}`);
  572. tempUpdateFile = path.join(cacheDir, `temp-${nameCounter++}-${updateFileName}`);
  573. }
  574. }
  575. try {
  576. yield taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny);
  577. yield (0, _fsExtraP().rename)(tempUpdateFile, updateFile);
  578. } catch (e) {
  579. yield removeFileIfAny();
  580. if (e instanceof _builderUtilRuntime().CancellationError) {
  581. log.info("Cancelled");
  582. _this10.emit("update-cancelled", updateInfo);
  583. }
  584. throw e;
  585. }
  586. log.info(`New version ${version} has been downloaded to ${updateFile}`);
  587. return yield done(true);
  588. })();
  589. }
  590. }
  591. exports.AppUpdater = AppUpdater;
  592. function hasPrereleaseComponents(version) {
  593. const versionPrereleaseComponent = (0, _semver().prerelease)(version);
  594. return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0;
  595. }
  596. /** @private */
  597. class NoOpLogger {
  598. info(message) {// ignore
  599. }
  600. warn(message) {// ignore
  601. }
  602. error(message) {// ignore
  603. }
  604. } exports.NoOpLogger = NoOpLogger;
  605. //# sourceMappingURL=AppUpdater.js.map