electron-updater 4.3.4 → 4.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/out/AppImageUpdater.js +25 -3
  2. package/out/AppImageUpdater.js.map +1 -1
  3. package/out/AppUpdater.d.ts +0 -2
  4. package/out/AppUpdater.js +5 -7
  5. package/out/AppUpdater.js.map +1 -1
  6. package/out/DownloadedUpdateHelper.js +1 -2
  7. package/out/DownloadedUpdateHelper.js.map +1 -1
  8. package/out/MacUpdater.d.ts +1 -1
  9. package/out/MacUpdater.js +29 -10
  10. package/out/MacUpdater.js.map +1 -1
  11. package/out/NsisUpdater.js +23 -17
  12. package/out/NsisUpdater.js.map +1 -1
  13. package/out/differentialDownloader/DifferentialDownloader.d.ts +3 -0
  14. package/out/differentialDownloader/DifferentialDownloader.js +50 -2
  15. package/out/differentialDownloader/DifferentialDownloader.js.map +1 -1
  16. package/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js +1 -1
  17. package/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js.map +1 -1
  18. package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.d.ts +32 -0
  19. package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.js +118 -0
  20. package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.js.map +1 -0
  21. package/out/differentialDownloader/downloadPlanBuilder.js +2 -3
  22. package/out/differentialDownloader/downloadPlanBuilder.js.map +1 -1
  23. package/out/differentialDownloader/multipleRangeDownloader.js +6 -0
  24. package/out/differentialDownloader/multipleRangeDownloader.js.map +1 -1
  25. package/out/main.d.ts +0 -1
  26. package/out/main.js +0 -16
  27. package/out/main.js.map +1 -1
  28. package/out/providers/BintrayProvider.js +1 -1
  29. package/out/providers/BintrayProvider.js.map +1 -1
  30. package/out/providers/GenericProvider.js +1 -1
  31. package/out/providers/GenericProvider.js.map +1 -1
  32. package/out/providers/PrivateGitHubProvider.js +2 -2
  33. package/out/providers/PrivateGitHubProvider.js.map +1 -1
  34. package/out/providers/Provider.js +1 -1
  35. package/out/providers/Provider.js.map +1 -1
  36. package/out/windowsExecutableCodeSignatureVerifier.d.ts +1 -1
  37. package/out/windowsExecutableCodeSignatureVerifier.js +22 -2
  38. package/out/windowsExecutableCodeSignatureVerifier.js.map +1 -1
  39. package/package.json +8 -8
@@ -136,10 +136,6 @@ class NsisUpdater extends _BaseUpdater().BaseUpdater {
136
136
  downloadUpdateOptions,
137
137
  fileInfo,
138
138
  task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {
139
- if (hasQuotes(destinationFile) || packageFile != null && hasQuotes(packageFile)) {
140
- throw (0, _builderUtilRuntime().newError)(`destinationFile or packageFile contains illegal chars`, "ERR_UPDATER_ILLEGAL_FILE_NAME");
141
- }
142
-
143
139
  const packageInfo = fileInfo.packageInfo;
144
140
  const isWebInstaller = packageInfo != null && packageFile != null;
145
141
 
@@ -156,7 +152,7 @@ class NsisUpdater extends _BaseUpdater().BaseUpdater {
156
152
  }
157
153
 
158
154
  if (isWebInstaller) {
159
- if (await this.differentialDownloadWebPackage(packageInfo, packageFile, provider)) {
155
+ if (await this.differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packageFile, provider)) {
160
156
  try {
161
157
  await this.httpExecutor.download(new (_url().URL)(packageInfo.path), packageFile, {
162
158
  headers: downloadUpdateOptions.requestHeaders,
@@ -275,15 +271,22 @@ class NsisUpdater extends _BaseUpdater().BaseUpdater {
275
271
  }
276
272
  };
277
273
 
278
- const blockMapDataList = await Promise.all([downloadBlockMap(oldBlockMapUrl), downloadBlockMap(newBlockMapUrl)]);
279
- await new (_GenericDifferentialDownloader().GenericDifferentialDownloader)(fileInfo.info, this.httpExecutor, {
274
+ const downloadOptions = {
280
275
  newUrl: fileInfo.url,
281
276
  oldFile: path.join(this.downloadedUpdateHelper.cacheDir, _builderUtilRuntime().CURRENT_APP_INSTALLER_FILE_NAME),
282
277
  logger: this._logger,
283
278
  newFile: installerPath,
284
279
  isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
285
- requestHeaders: downloadUpdateOptions.requestHeaders
286
- }).download(blockMapDataList[0], blockMapDataList[1]);
280
+ requestHeaders: downloadUpdateOptions.requestHeaders,
281
+ cancellationToken: downloadUpdateOptions.cancellationToken
282
+ };
283
+
284
+ if (this.listenerCount(_main().DOWNLOAD_PROGRESS) > 0) {
285
+ downloadOptions.onProgress = it => this.emit(_main().DOWNLOAD_PROGRESS, it);
286
+ }
287
+
288
+ const blockMapDataList = await Promise.all([downloadBlockMap(oldBlockMapUrl), downloadBlockMap(newBlockMapUrl)]);
289
+ await new (_GenericDifferentialDownloader().GenericDifferentialDownloader)(fileInfo.info, this.httpExecutor, downloadOptions).download(blockMapDataList[0], blockMapDataList[1]);
287
290
  return false;
288
291
  } catch (e) {
289
292
  this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
@@ -297,20 +300,27 @@ class NsisUpdater extends _BaseUpdater().BaseUpdater {
297
300
  }
298
301
  }
299
302
 
300
- async differentialDownloadWebPackage(packageInfo, packagePath, provider) {
303
+ async differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packagePath, provider) {
301
304
  if (packageInfo.blockMapSize == null) {
302
305
  return true;
303
306
  }
304
307
 
305
308
  try {
306
- await new (_FileWithEmbeddedBlockMapDifferentialDownloader().FileWithEmbeddedBlockMapDifferentialDownloader)(packageInfo, this.httpExecutor, {
309
+ const downloadOptions = {
307
310
  newUrl: new (_url().URL)(packageInfo.path),
308
311
  oldFile: path.join(this.downloadedUpdateHelper.cacheDir, _builderUtilRuntime().CURRENT_APP_PACKAGE_FILE_NAME),
309
312
  logger: this._logger,
310
313
  newFile: packagePath,
311
314
  requestHeaders: this.requestHeaders,
312
- isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest
313
- }).download();
315
+ isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
316
+ cancellationToken: downloadUpdateOptions.cancellationToken
317
+ };
318
+
319
+ if (this.listenerCount(_main().DOWNLOAD_PROGRESS) > 0) {
320
+ downloadOptions.onProgress = it => this.emit(_main().DOWNLOAD_PROGRESS, it);
321
+ }
322
+
323
+ await new (_FileWithEmbeddedBlockMapDifferentialDownloader().FileWithEmbeddedBlockMapDifferentialDownloader)(packageInfo, this.httpExecutor, downloadOptions).download();
314
324
  } catch (e) {
315
325
  this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`); // during test (developer machine mac or linux) we must throw error
316
326
 
@@ -350,10 +360,6 @@ async function _spawn(exe, args) {
350
360
  reject(error);
351
361
  }
352
362
  });
353
- }
354
-
355
- function hasQuotes(name) {
356
- return name.includes("'") || name.includes('"') || name.includes('`');
357
363
  }
358
364
  // __ts-babel@6.0.4
359
365
  //# sourceMappingURL=NsisUpdater.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/NsisUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions, newError, PackageFileInfo, BlockMap, CURRENT_APP_PACKAGE_FILE_NAME, CURRENT_APP_INSTALLER_FILE_NAME } from \"builder-util-runtime\"\nimport { spawn } from \"child_process\"\nimport * as path from \"path\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { FileWithEmbeddedBlockMapDifferentialDownloader } from \"./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader\"\nimport { GenericDifferentialDownloader } from \"./differentialDownloader/GenericDifferentialDownloader\"\nimport { newUrlFromBase, ResolvedUpdateFileInfo } from \"./main\"\nimport { findFile, Provider } from \"./providers/Provider\"\nimport { unlink } from \"fs-extra\"\nimport { verifySignature } from \"./windowsExecutableCodeSignatureVerifier\"\nimport { URL } from \"url\"\nimport { gunzipSync } from \"zlib\"\n\nexport class NsisUpdater extends BaseUpdater {\n constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n super(options, app)\n }\n\n /*** @private */\n protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"exe\")!!\n return this.executeDownload({\n fileExtension: \"exe\",\n downloadUpdateOptions,\n fileInfo,\n task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {\n if (hasQuotes(destinationFile) || (packageFile != null && hasQuotes(packageFile))) {\n throw newError(`destinationFile or packageFile contains illegal chars`, \"ERR_UPDATER_ILLEGAL_FILE_NAME\")\n }\n\n const packageInfo = fileInfo.packageInfo\n const isWebInstaller = packageInfo != null && packageFile != null\n if (isWebInstaller || await this.differentialDownloadInstaller(fileInfo, downloadUpdateOptions, destinationFile, provider)) {\n await this.httpExecutor.download(fileInfo.url, destinationFile, downloadOptions)\n }\n\n const signatureVerificationStatus = await this.verifySignature(destinationFile)\n if (signatureVerificationStatus != null) {\n await removeTempDirIfAny()\n // noinspection ThrowInsideFinallyBlockJS\n throw newError(`New version ${downloadUpdateOptions.updateInfoAndProvider.info.version} is not signed by the application owner: ${signatureVerificationStatus}`, \"ERR_UPDATER_INVALID_SIGNATURE\")\n }\n\n if (isWebInstaller) {\n if (await this.differentialDownloadWebPackage(packageInfo!!, packageFile!!, provider)) {\n try {\n await this.httpExecutor.download(new URL(packageInfo!!.path), packageFile!!, {\n headers: downloadUpdateOptions.requestHeaders,\n cancellationToken: downloadUpdateOptions.cancellationToken,\n sha512: packageInfo!!.sha512,\n })\n }\n catch (e) {\n try {\n await unlink(packageFile!!)\n }\n catch (ignored) {\n // ignore\n }\n\n throw e\n }\n }\n }\n },\n })\n }\n\n // $certificateInfo = (Get-AuthenticodeSignature 'xxx\\yyy.exe'\n // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains(\"CN=siemens.com\")})\n // | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }\n private async verifySignature(tempUpdateFile: string): Promise<string | null> {\n let publisherName: Array<string> | string | null\n try {\n publisherName = (await this.configOnDisk.value).publisherName\n if (publisherName == null) {\n return null\n }\n }\n catch (e) {\n if (e.code === \"ENOENT\") {\n // no app-update.yml\n return null\n }\n throw e\n }\n return await verifySignature(Array.isArray(publisherName) ? publisherName : [publisherName], tempUpdateFile, this._logger)\n }\n\n protected doInstall(options: InstallOptions): boolean {\n const args = [\"--updated\"]\n if (options.isSilent) {\n args.push(\"/S\")\n }\n\n if (options.isForceRunAfter) {\n args.push(\"--force-run\")\n }\n\n const packagePath = this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.packageFile\n if (packagePath != null) {\n // only = form is supported\n args.push(`--package-file=${packagePath}`)\n }\n\n const callUsingElevation = (): void => {\n _spawn(path.join(process.resourcesPath!!, \"elevate.exe\"), [options.installerPath].concat(args))\n .catch(e => this.dispatchError(e))\n }\n\n if (options.isAdminRightsRequired) {\n this._logger.info(\"isAdminRightsRequired is set to true, run installer using elevate.exe\")\n callUsingElevation()\n return true\n }\n\n _spawn(options.installerPath, args)\n .catch((e: Error) => {\n // https://github.com/electron-userland/electron-builder/issues/1129\n // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors\n const errorCode = (e as NodeJS.ErrnoException).code\n this._logger.info(`Cannot run installer: error code: ${errorCode}, error message: \"${e.message}\", will be executed again using elevate if EACCES\"`)\n if (errorCode === \"UNKNOWN\" || errorCode === \"EACCES\") {\n callUsingElevation()\n }\n else {\n this.dispatchError(e)\n }\n })\n return true\n }\n\n private async differentialDownloadInstaller(fileInfo: ResolvedUpdateFileInfo, downloadUpdateOptions: DownloadUpdateOptions, installerPath: string, provider: Provider<any>): Promise<boolean> {\n try {\n if (this._testOnlyOptions != null && !this._testOnlyOptions.isUseDifferentialDownload) {\n return true\n }\n\n const newBlockMapUrl = newUrlFromBase(`${fileInfo.url.pathname}.blockmap`, fileInfo.url)\n const oldBlockMapUrl = newUrlFromBase(`${fileInfo.url.pathname.replace(new RegExp(downloadUpdateOptions.updateInfoAndProvider.info.version, \"g\"), this.app.version)}.blockmap`, fileInfo.url)\n this._logger.info(`Download block maps (old: \"${oldBlockMapUrl.href}\", new: ${newBlockMapUrl.href})`)\n\n const downloadBlockMap = async (url: URL): Promise<BlockMap> => {\n const data = await this.httpExecutor.downloadToBuffer(url, {\n headers: downloadUpdateOptions.requestHeaders,\n cancellationToken: downloadUpdateOptions.cancellationToken,\n })\n\n if (data == null || data.length === 0) {\n throw new Error(`Blockmap \"${url.href}\" is empty`)\n }\n\n try {\n return JSON.parse(gunzipSync(data).toString())\n }\n catch (e) {\n throw new Error(`Cannot parse blockmap \"${url.href}\", error: ${e}, raw data: ${data}`)\n }\n }\n\n const blockMapDataList = await Promise.all([downloadBlockMap(oldBlockMapUrl), downloadBlockMap(newBlockMapUrl)])\n await new GenericDifferentialDownloader(fileInfo.info, this.httpExecutor, {\n newUrl: fileInfo.url,\n oldFile: path.join(this.downloadedUpdateHelper!!.cacheDir, CURRENT_APP_INSTALLER_FILE_NAME),\n logger: this._logger,\n newFile: installerPath,\n isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n requestHeaders: downloadUpdateOptions.requestHeaders,\n })\n .download(blockMapDataList[0], blockMapDataList[1])\n return false\n }\n catch (e) {\n this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n if (this._testOnlyOptions != null) {\n // test mode\n throw e\n }\n return true\n }\n }\n\n private async differentialDownloadWebPackage(packageInfo: PackageFileInfo, packagePath: string, provider: Provider<any>): Promise<boolean> {\n if (packageInfo.blockMapSize == null) {\n return true\n }\n\n try {\n await new FileWithEmbeddedBlockMapDifferentialDownloader(packageInfo, this.httpExecutor, {\n newUrl: new URL(packageInfo.path),\n oldFile: path.join(this.downloadedUpdateHelper!!.cacheDir, CURRENT_APP_PACKAGE_FILE_NAME),\n logger: this._logger,\n newFile: packagePath,\n requestHeaders: this.requestHeaders,\n isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n })\n .download()\n }\n catch (e) {\n this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n // during test (developer machine mac or linux) we must throw error\n return process.platform === \"win32\"\n }\n return false\n }\n}\n\n/**\n * This handles both node 8 and node 10 way of emitting error when spawning a process\n * - node 8: Throws the error\n * - node 10: Emit the error(Need to listen with on)\n */\nasync function _spawn(exe: string, args: Array<string>): Promise<any> {\n return new Promise((resolve, reject) => {\n try {\n const process = spawn(exe, args, {\n detached: true,\n stdio: \"ignore\",\n })\n process.on(\"error\", error => {\n reject(error)\n })\n process.unref()\n\n if (process.pid !== undefined) {\n resolve(true)\n }\n }\n catch (error) {\n reject(error)\n }\n })\n}\n\nfunction hasQuotes(name: string): boolean {\n return name.includes(\"'\") || name.includes('\"') || name.includes('`')\n}"],"sourceRoot":""}
1
+ {"version":3,"sources":["../src/NsisUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions, newError, PackageFileInfo, BlockMap, CURRENT_APP_PACKAGE_FILE_NAME, CURRENT_APP_INSTALLER_FILE_NAME } from \"builder-util-runtime\"\nimport { spawn } from \"child_process\"\nimport * as path from \"path\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { DifferentialDownloaderOptions } from \"./differentialDownloader/DifferentialDownloader\"\nimport { FileWithEmbeddedBlockMapDifferentialDownloader } from \"./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader\"\nimport { GenericDifferentialDownloader } from \"./differentialDownloader/GenericDifferentialDownloader\"\nimport { DOWNLOAD_PROGRESS, newUrlFromBase, ResolvedUpdateFileInfo } from \"./main\"\nimport { findFile, Provider } from \"./providers/Provider\"\nimport { unlink } from \"fs-extra\"\nimport { verifySignature } from \"./windowsExecutableCodeSignatureVerifier\"\nimport { URL } from \"url\"\nimport { gunzipSync } from \"zlib\"\n\nexport class NsisUpdater extends BaseUpdater {\n constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n super(options, app)\n }\n\n /*** @private */\n protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"exe\")!!\n return this.executeDownload({\n fileExtension: \"exe\",\n downloadUpdateOptions,\n fileInfo,\n task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {\n const packageInfo = fileInfo.packageInfo\n const isWebInstaller = packageInfo != null && packageFile != null\n if (isWebInstaller || await this.differentialDownloadInstaller(fileInfo, downloadUpdateOptions, destinationFile, provider)) {\n await this.httpExecutor.download(fileInfo.url, destinationFile, downloadOptions)\n }\n\n const signatureVerificationStatus = await this.verifySignature(destinationFile)\n if (signatureVerificationStatus != null) {\n await removeTempDirIfAny()\n // noinspection ThrowInsideFinallyBlockJS\n throw newError(`New version ${downloadUpdateOptions.updateInfoAndProvider.info.version} is not signed by the application owner: ${signatureVerificationStatus}`, \"ERR_UPDATER_INVALID_SIGNATURE\")\n }\n\n if (isWebInstaller) {\n if (await this.differentialDownloadWebPackage(downloadUpdateOptions, packageInfo!!, packageFile!!, provider)) {\n try {\n await this.httpExecutor.download(new URL(packageInfo!!.path), packageFile!!, {\n headers: downloadUpdateOptions.requestHeaders,\n cancellationToken: downloadUpdateOptions.cancellationToken,\n sha512: packageInfo!!.sha512,\n })\n }\n catch (e) {\n try {\n await unlink(packageFile!!)\n }\n catch (ignored) {\n // ignore\n }\n\n throw e\n }\n }\n }\n },\n })\n }\n\n // $certificateInfo = (Get-AuthenticodeSignature 'xxx\\yyy.exe'\n // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains(\"CN=siemens.com\")})\n // | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }\n private async verifySignature(tempUpdateFile: string): Promise<string | null> {\n let publisherName: Array<string> | string | null\n try {\n publisherName = (await this.configOnDisk.value).publisherName\n if (publisherName == null) {\n return null\n }\n }\n catch (e) {\n if (e.code === \"ENOENT\") {\n // no app-update.yml\n return null\n }\n throw e\n }\n return await verifySignature(Array.isArray(publisherName) ? publisherName : [publisherName], tempUpdateFile, this._logger)\n }\n\n protected doInstall(options: InstallOptions): boolean {\n const args = [\"--updated\"]\n if (options.isSilent) {\n args.push(\"/S\")\n }\n\n if (options.isForceRunAfter) {\n args.push(\"--force-run\")\n }\n\n const packagePath = this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.packageFile\n if (packagePath != null) {\n // only = form is supported\n args.push(`--package-file=${packagePath}`)\n }\n\n const callUsingElevation = (): void => {\n _spawn(path.join(process.resourcesPath!!, \"elevate.exe\"), [options.installerPath].concat(args))\n .catch(e => this.dispatchError(e))\n }\n\n if (options.isAdminRightsRequired) {\n this._logger.info(\"isAdminRightsRequired is set to true, run installer using elevate.exe\")\n callUsingElevation()\n return true\n }\n\n _spawn(options.installerPath, args)\n .catch((e: Error) => {\n // https://github.com/electron-userland/electron-builder/issues/1129\n // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors\n const errorCode = (e as NodeJS.ErrnoException).code\n this._logger.info(`Cannot run installer: error code: ${errorCode}, error message: \"${e.message}\", will be executed again using elevate if EACCES\"`)\n if (errorCode === \"UNKNOWN\" || errorCode === \"EACCES\") {\n callUsingElevation()\n }\n else {\n this.dispatchError(e)\n }\n })\n return true\n }\n\n private async differentialDownloadInstaller(fileInfo: ResolvedUpdateFileInfo, downloadUpdateOptions: DownloadUpdateOptions, installerPath: string, provider: Provider<any>): Promise<boolean> {\n try {\n if (this._testOnlyOptions != null && !this._testOnlyOptions.isUseDifferentialDownload) {\n return true\n }\n\n const newBlockMapUrl = newUrlFromBase(`${fileInfo.url.pathname}.blockmap`, fileInfo.url)\n const oldBlockMapUrl = newUrlFromBase(`${fileInfo.url.pathname.replace(new RegExp(downloadUpdateOptions.updateInfoAndProvider.info.version, \"g\"), this.app.version)}.blockmap`, fileInfo.url)\n this._logger.info(`Download block maps (old: \"${oldBlockMapUrl.href}\", new: ${newBlockMapUrl.href})`)\n\n const downloadBlockMap = async (url: URL): Promise<BlockMap> => {\n const data = await this.httpExecutor.downloadToBuffer(url, {\n headers: downloadUpdateOptions.requestHeaders,\n cancellationToken: downloadUpdateOptions.cancellationToken,\n })\n\n if (data == null || data.length === 0) {\n throw new Error(`Blockmap \"${url.href}\" is empty`)\n }\n\n try {\n return JSON.parse(gunzipSync(data).toString())\n }\n catch (e) {\n throw new Error(`Cannot parse blockmap \"${url.href}\", error: ${e}, raw data: ${data}`)\n }\n }\n\n const downloadOptions: DifferentialDownloaderOptions = {\n newUrl: fileInfo.url,\n oldFile: path.join(this.downloadedUpdateHelper!!.cacheDir, CURRENT_APP_INSTALLER_FILE_NAME),\n logger: this._logger,\n newFile: installerPath,\n isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n requestHeaders: downloadUpdateOptions.requestHeaders,\n cancellationToken: downloadUpdateOptions.cancellationToken,\n }\n\n if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n }\n\n const blockMapDataList = await Promise.all([downloadBlockMap(oldBlockMapUrl), downloadBlockMap(newBlockMapUrl)])\n await new GenericDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions)\n .download(blockMapDataList[0], blockMapDataList[1])\n return false\n }\n catch (e) {\n this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n if (this._testOnlyOptions != null) {\n // test mode\n throw e\n }\n return true\n }\n }\n\n private async differentialDownloadWebPackage(downloadUpdateOptions: DownloadUpdateOptions, packageInfo: PackageFileInfo, packagePath: string, provider: Provider<any>): Promise<boolean> {\n if (packageInfo.blockMapSize == null) {\n return true\n }\n\n try {\n const downloadOptions: DifferentialDownloaderOptions = {\n newUrl: new URL(packageInfo.path),\n oldFile: path.join(this.downloadedUpdateHelper!!.cacheDir, CURRENT_APP_PACKAGE_FILE_NAME),\n logger: this._logger,\n newFile: packagePath,\n requestHeaders: this.requestHeaders,\n isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n cancellationToken: downloadUpdateOptions.cancellationToken,\n }\n\n if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n }\n\n await new FileWithEmbeddedBlockMapDifferentialDownloader(packageInfo, this.httpExecutor, downloadOptions)\n .download()\n }\n catch (e) {\n this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n // during test (developer machine mac or linux) we must throw error\n return process.platform === \"win32\"\n }\n return false\n }\n}\n\n/**\n * This handles both node 8 and node 10 way of emitting error when spawning a process\n * - node 8: Throws the error\n * - node 10: Emit the error(Need to listen with on)\n */\nasync function _spawn(exe: string, args: Array<string>): Promise<any> {\n return new Promise((resolve, reject) => {\n try {\n const process = spawn(exe, args, {\n detached: true,\n stdio: \"ignore\",\n })\n process.on(\"error\", error => {\n reject(error)\n })\n process.unref()\n\n if (process.pid !== undefined) {\n resolve(true)\n }\n }\n catch (error) {\n reject(error)\n }\n })\n}\n"],"sourceRoot":""}
@@ -2,6 +2,7 @@
2
2
  import { BlockMapDataHolder, HttpExecutor } from "builder-util-runtime";
3
3
  import { BlockMap } from "builder-util-runtime/out/blockMapApi";
4
4
  import { OutgoingHttpHeaders, RequestOptions } from "http";
5
+ import { ProgressInfo, CancellationToken } from "builder-util-runtime";
5
6
  import { Logger } from "../main";
6
7
  import { URL } from "url";
7
8
  export interface DifferentialDownloaderOptions {
@@ -11,6 +12,8 @@ export interface DifferentialDownloaderOptions {
11
12
  readonly newFile: string;
12
13
  readonly requestHeaders: OutgoingHttpHeaders | null;
13
14
  readonly isUseMultipleRangeRequest?: boolean;
15
+ readonly cancellationToken: CancellationToken;
16
+ onProgress?(progress: ProgressInfo): void;
14
17
  }
15
18
  export declare abstract class DifferentialDownloader {
16
19
  protected readonly blockAwareFileInfo: BlockMapDataHolder;
@@ -67,6 +67,16 @@ function _multipleRangeDownloader() {
67
67
  return data;
68
68
  }
69
69
 
70
+ function _ProgressDifferentialDownloadCallbackTransform() {
71
+ const data = require("./ProgressDifferentialDownloadCallbackTransform");
72
+
73
+ _ProgressDifferentialDownloadCallbackTransform = function () {
74
+ return data;
75
+ };
76
+
77
+ return data;
78
+ }
79
+
70
80
  class DifferentialDownloader {
71
81
  // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected
72
82
  constructor(blockAwareFileInfo, httpExecutor, options) {
@@ -171,7 +181,30 @@ class DifferentialDownloader {
171
181
  fd: newFileFd
172
182
  });
173
183
  await new Promise((resolve, reject) => {
174
- const streams = [];
184
+ const streams = []; // Create our download info transformer if we have one
185
+
186
+ let downloadInfoTransform = undefined;
187
+
188
+ if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {
189
+ // TODO: Does not support multiple ranges (someone feel free to PR this!)
190
+ const expectedByteCounts = [];
191
+ let grandTotalBytes = 0;
192
+
193
+ for (const task of tasks) {
194
+ if (task.kind === _downloadPlanBuilder().OperationKind.DOWNLOAD) {
195
+ expectedByteCounts.push(task.end - task.start);
196
+ grandTotalBytes += task.end - task.start;
197
+ }
198
+ }
199
+
200
+ const progressDifferentialDownloadInfo = {
201
+ expectedByteCounts: expectedByteCounts,
202
+ grandTotal: grandTotalBytes
203
+ };
204
+ downloadInfoTransform = new (_ProgressDifferentialDownloadCallbackTransform().ProgressDifferentialDownloadCallbackTransform)(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress);
205
+ streams.push(downloadInfoTransform);
206
+ }
207
+
175
208
  const digestTransform = new (_builderUtilRuntime().DigestTransform)(this.blockAwareFileInfo.sha512); // to simply debug, do manual validation to allow file to be fully written
176
209
 
177
210
  digestTransform.isValidateOnEnd = false;
@@ -189,7 +222,7 @@ class DifferentialDownloader {
189
222
  return;
190
223
  }
191
224
 
192
- resolve();
225
+ resolve(undefined);
193
226
  });
194
227
  });
195
228
  streams.push(fileOut);
@@ -233,6 +266,11 @@ class DifferentialDownloader {
233
266
  const operation = tasks[index++];
234
267
 
235
268
  if (operation.kind === _downloadPlanBuilder().OperationKind.COPY) {
269
+ // We are copying, let's not send status updates to the UI
270
+ if (downloadInfoTransform) {
271
+ downloadInfoTransform.beginFileCopy();
272
+ }
273
+
236
274
  (0, _DataSplitter().copyData)(operation, firstStream, oldFileFd, reject, () => w(index));
237
275
  return;
238
276
  }
@@ -243,6 +281,11 @@ class DifferentialDownloader {
243
281
 
244
282
  if (debug != null) {
245
283
  debug(`download range: ${range}`);
284
+ } // We are starting to download
285
+
286
+
287
+ if (downloadInfoTransform) {
288
+ downloadInfoTransform.beginRangeDownload();
246
289
  }
247
290
 
248
291
  const request = this.httpExecutor.createRequest(requestOptions, response => {
@@ -255,6 +298,11 @@ class DifferentialDownloader {
255
298
  end: false
256
299
  });
257
300
  response.once("end", () => {
301
+ // Pass on that we are downloading a segment
302
+ if (downloadInfoTransform) {
303
+ downloadInfoTransform.endRangeDownload();
304
+ }
305
+
258
306
  if (++downloadOperationCount === 100) {
259
307
  downloadOperationCount = 0;
260
308
  setTimeout(() => w(index), 1000);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/differentialDownloader/DifferentialDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMapDataHolder, createHttpError, DigestTransform, HttpExecutor, configureRequestUrl, configureRequestOptions } from \"builder-util-runtime\"\nimport { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, open } from \"fs-extra\"\nimport { createWriteStream } from \"fs\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { Logger } from \"../main\"\nimport { copyData } from \"./DataSplitter\"\nimport { URL } from \"url\"\nimport { computeOperations, Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from \"./multipleRangeDownloader\"\n\nexport interface DifferentialDownloaderOptions {\n readonly oldFile: string\n readonly newUrl: URL\n readonly logger: Logger\n readonly newFile: string\n\n readonly requestHeaders: OutgoingHttpHeaders | null\n\n readonly isUseMultipleRangeRequest?: boolean\n}\n\nexport abstract class DifferentialDownloader {\n fileMetadataBuffer: Buffer | null = null\n\n private readonly logger: Logger\n\n // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected\n constructor(protected readonly blockAwareFileInfo: BlockMapDataHolder, readonly httpExecutor: HttpExecutor<any>, readonly options: DifferentialDownloaderOptions) {\n this.logger = options.logger\n }\n\n createRequestOptions(): RequestOptions {\n const result = {\n headers: {\n ...this.options.requestHeaders,\n accept: \"*/*\",\n },\n }\n configureRequestUrl(this.options.newUrl, result)\n // user-agent, cache-control and other common options\n configureRequestOptions(result)\n return result\n }\n\n protected doDownload(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it\n if (oldBlockMap.version !== newBlockMap.version) {\n throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`)\n }\n\n const logger = this.logger\n const operations = computeOperations(oldBlockMap, newBlockMap, logger)\n if (logger.debug != null) {\n logger.debug(JSON.stringify(operations, null, 2))\n }\n\n let downloadSize = 0\n let copySize = 0\n for (const operation of operations) {\n const length = operation.end - operation.start\n if (operation.kind === OperationKind.DOWNLOAD) {\n downloadSize += length\n }\n else {\n copySize += length\n }\n }\n\n const newSize = this.blockAwareFileInfo.size\n if ((downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length)) !== newSize) {\n throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`)\n }\n\n logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`)\n\n return this.downloadFile(operations)\n }\n\n private downloadFile(tasks: Array<Operation>): Promise<any> {\n const fdList: Array<OpenedFile> = []\n const closeFiles = (): Promise<Array<void>> => {\n return Promise.all(fdList.map(openedFile => {\n return close(openedFile.descriptor)\n .catch(e => {\n this.logger.error(`cannot close file \"${openedFile.path}\": ${e}`)\n })\n }))\n }\n return this.doDownloadFile(tasks, fdList)\n .then(closeFiles)\n .catch(e => {\n // then must be after catch here (since then always throws error)\n return closeFiles()\n .catch(closeFilesError => {\n // closeFiles never throw error, but just to be sure\n try {\n this.logger.error(`cannot close files: ${closeFilesError}`)\n }\n catch (errorOnLog) {\n try {\n console.error(errorOnLog)\n }\n catch (ignored) {\n // ok, give up and ignore error\n }\n }\n throw e\n })\n .then(() => {\n throw e\n })\n })\n }\n\n private async doDownloadFile(tasks: Array<Operation>, fdList: Array<OpenedFile>): Promise<any> {\n const oldFileFd = await open(this.options.oldFile, \"r\")\n fdList.push({descriptor: oldFileFd, path: this.options.oldFile})\n const newFileFd = await open(this.options.newFile, \"w\")\n fdList.push({descriptor: newFileFd, path: this.options.newFile})\n const fileOut = createWriteStream(this.options.newFile, {fd: newFileFd})\n await new Promise((resolve, reject) => {\n const streams: Array<any> = []\n const digestTransform = new DigestTransform(this.blockAwareFileInfo.sha512)\n // to simply debug, do manual validation to allow file to be fully written\n digestTransform.isValidateOnEnd = false\n streams.push(digestTransform)\n\n // noinspection JSArrowFunctionCanBeReplacedWithShorthand\n fileOut.on(\"finish\", () => {\n (fileOut.close as any)(() => {\n // remove from fd list because closed successfully\n fdList.splice(1, 1)\n try {\n digestTransform.validate()\n }\n catch (e) {\n reject(e)\n return\n }\n\n resolve()\n })\n })\n\n streams.push(fileOut)\n\n let lastStream = null\n for (const stream of streams) {\n stream.on(\"error\", reject)\n if (lastStream == null) {\n lastStream = stream\n }\n else {\n lastStream = lastStream.pipe(stream)\n }\n }\n\n const firstStream = streams[0]\n\n let w: any\n if (this.options.isUseMultipleRangeRequest) {\n w = executeTasksUsingMultipleRangeRequests(this, tasks, firstStream, oldFileFd, reject)\n w(0)\n return\n }\n\n let downloadOperationCount = 0\n let actualUrl: string | null = null\n this.logger.info(`Differential download: ${this.options.newUrl}`)\n\n const requestOptions = this.createRequestOptions();\n (requestOptions as any).redirect = \"manual\"\n\n w = (index: number): void => {\n if (index >= tasks.length) {\n if (this.fileMetadataBuffer != null) {\n firstStream.write(this.fileMetadataBuffer)\n }\n firstStream.end()\n return\n }\n\n const operation = tasks[index++]\n if (operation.kind === OperationKind.COPY) {\n copyData(operation, firstStream, oldFileFd, reject, () => w(index))\n return\n }\n\n const range = `bytes=${operation.start}-${operation.end - 1}`\n requestOptions.headers!!.range = range\n\n const debug = this.logger.debug\n if (debug != null) {\n debug(`download range: ${range}`)\n }\n\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n if (response.statusCode >= 400) {\n reject(createHttpError(response))\n }\n\n response.pipe(firstStream, {\n end: false\n })\n response.once(\"end\", () => {\n if (++downloadOperationCount === 100) {\n downloadOperationCount = 0\n setTimeout(() => w(index), 1000)\n }\n else {\n w(index)\n }\n })\n })\n request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`)\n actualUrl = redirectUrl\n configureRequestUrl(new URL(actualUrl), requestOptions)\n request.followRedirect()\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n }\n\n w(0)\n })\n }\n\n protected async readRemoteBytes(start: number, endInclusive: number): Promise<Buffer> {\n const buffer = Buffer.allocUnsafe((endInclusive + 1) - start)\n const requestOptions = this.createRequestOptions()\n requestOptions.headers!!.range = `bytes=${start}-${endInclusive}`\n let position = 0\n await this.request(requestOptions, chunk => {\n chunk.copy(buffer, position)\n position += chunk.length\n })\n\n if (position !== buffer.length) {\n throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`)\n }\n return buffer\n }\n\n private request(requestOptions: RequestOptions, dataHandler: (chunk: Buffer) => void): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n response.on(\"data\", dataHandler)\n response.on(\"end\", () => resolve())\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n })\n }\n}\n\nfunction formatBytes(value: number, symbol = \" KB\"): string {\n return new Intl.NumberFormat(\"en\").format((value / 1024).toFixed(2) as any) + symbol\n}\n\n// safety\nfunction removeQuery(url: string): string {\n const index = url.indexOf(\"?\")\n return index < 0 ? url : url.substring(0, index)\n}\n\ninterface OpenedFile {\n readonly descriptor: number\n readonly path: string\n}"],"sourceRoot":""}
1
+ {"version":3,"sources":["../../src/differentialDownloader/DifferentialDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMapDataHolder, createHttpError, DigestTransform, HttpExecutor, configureRequestUrl, configureRequestOptions } from \"builder-util-runtime\"\nimport { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, open } from \"fs-extra\"\nimport { createWriteStream } from \"fs\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { ProgressInfo, CancellationToken } from \"builder-util-runtime\"\nimport { Logger } from \"../main\"\nimport { copyData } from \"./DataSplitter\"\nimport { URL } from \"url\"\nimport { computeOperations, Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from \"./multipleRangeDownloader\"\nimport { ProgressDifferentialDownloadCallbackTransform, ProgressDifferentialDownloadInfo } from \"./ProgressDifferentialDownloadCallbackTransform\"\n\nexport interface DifferentialDownloaderOptions {\n readonly oldFile: string\n readonly newUrl: URL\n readonly logger: Logger\n readonly newFile: string\n\n readonly requestHeaders: OutgoingHttpHeaders | null\n\n readonly isUseMultipleRangeRequest?: boolean\n\n readonly cancellationToken: CancellationToken\n onProgress?(progress: ProgressInfo): void\n}\n\nexport abstract class DifferentialDownloader {\n fileMetadataBuffer: Buffer | null = null\n\n private readonly logger: Logger\n\n // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected\n constructor(protected readonly blockAwareFileInfo: BlockMapDataHolder, readonly httpExecutor: HttpExecutor<any>, readonly options: DifferentialDownloaderOptions) {\n this.logger = options.logger\n }\n\n createRequestOptions(): RequestOptions {\n const result = {\n headers: {\n ...this.options.requestHeaders,\n accept: \"*/*\",\n },\n }\n configureRequestUrl(this.options.newUrl, result)\n // user-agent, cache-control and other common options\n configureRequestOptions(result)\n return result\n }\n\n protected doDownload(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it\n if (oldBlockMap.version !== newBlockMap.version) {\n throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`)\n }\n\n const logger = this.logger\n const operations = computeOperations(oldBlockMap, newBlockMap, logger)\n if (logger.debug != null) {\n logger.debug(JSON.stringify(operations, null, 2))\n }\n\n let downloadSize = 0\n let copySize = 0\n for (const operation of operations) {\n const length = operation.end - operation.start\n if (operation.kind === OperationKind.DOWNLOAD) {\n downloadSize += length\n }\n else {\n copySize += length\n }\n }\n\n const newSize = this.blockAwareFileInfo.size\n if ((downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length)) !== newSize) {\n throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`)\n }\n\n logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`)\n\n return this.downloadFile(operations)\n }\n\n private downloadFile(tasks: Array<Operation>): Promise<any> {\n const fdList: Array<OpenedFile> = []\n const closeFiles = (): Promise<Array<void>> => {\n return Promise.all(fdList.map(openedFile => {\n return close(openedFile.descriptor)\n .catch(e => {\n this.logger.error(`cannot close file \"${openedFile.path}\": ${e}`)\n })\n }))\n }\n return this.doDownloadFile(tasks, fdList)\n .then(closeFiles)\n .catch(e => {\n // then must be after catch here (since then always throws error)\n return closeFiles()\n .catch(closeFilesError => {\n // closeFiles never throw error, but just to be sure\n try {\n this.logger.error(`cannot close files: ${closeFilesError}`)\n }\n catch (errorOnLog) {\n try {\n console.error(errorOnLog)\n }\n catch (ignored) {\n // ok, give up and ignore error\n }\n }\n throw e\n })\n .then(() => {\n throw e\n })\n })\n }\n\n private async doDownloadFile(tasks: Array<Operation>, fdList: Array<OpenedFile>): Promise<any> {\n const oldFileFd = await open(this.options.oldFile, \"r\")\n fdList.push({descriptor: oldFileFd, path: this.options.oldFile})\n const newFileFd = await open(this.options.newFile, \"w\")\n fdList.push({descriptor: newFileFd, path: this.options.newFile})\n const fileOut = createWriteStream(this.options.newFile, {fd: newFileFd})\n await new Promise((resolve, reject) => {\n const streams: Array<any> = []\n\n // Create our download info transformer if we have one\n let downloadInfoTransform: ProgressDifferentialDownloadCallbackTransform | undefined = undefined\n if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) { // TODO: Does not support multiple ranges (someone feel free to PR this!)\n const expectedByteCounts: Array<number> = []\n let grandTotalBytes = 0\n\n for (const task of tasks) {\n if (task.kind === OperationKind.DOWNLOAD) {\n expectedByteCounts.push(task.end - task.start)\n grandTotalBytes += task.end - task.start\n }\n }\n\n const progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo = {\n expectedByteCounts: expectedByteCounts,\n grandTotal: grandTotalBytes\n }\n\n downloadInfoTransform = new ProgressDifferentialDownloadCallbackTransform(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress)\n streams.push(downloadInfoTransform)\n }\n\n const digestTransform = new DigestTransform(this.blockAwareFileInfo.sha512)\n // to simply debug, do manual validation to allow file to be fully written\n digestTransform.isValidateOnEnd = false\n streams.push(digestTransform)\n\n // noinspection JSArrowFunctionCanBeReplacedWithShorthand\n fileOut.on(\"finish\", () => {\n (fileOut.close as any)(() => {\n // remove from fd list because closed successfully\n fdList.splice(1, 1)\n try {\n digestTransform.validate()\n }\n catch (e) {\n reject(e)\n return\n }\n\n resolve(undefined)\n })\n })\n\n streams.push(fileOut)\n\n let lastStream = null\n for (const stream of streams) {\n stream.on(\"error\", reject)\n if (lastStream == null) {\n lastStream = stream\n }\n else {\n lastStream = lastStream.pipe(stream)\n }\n }\n\n const firstStream = streams[0]\n\n let w: any\n if (this.options.isUseMultipleRangeRequest) {\n w = executeTasksUsingMultipleRangeRequests(this, tasks, firstStream, oldFileFd, reject)\n w(0)\n return\n }\n\n let downloadOperationCount = 0\n let actualUrl: string | null = null\n this.logger.info(`Differential download: ${this.options.newUrl}`)\n\n const requestOptions = this.createRequestOptions();\n (requestOptions as any).redirect = \"manual\"\n\n w = (index: number): void => {\n if (index >= tasks.length) {\n if (this.fileMetadataBuffer != null) {\n firstStream.write(this.fileMetadataBuffer)\n }\n firstStream.end()\n return\n }\n\n const operation = tasks[index++]\n if (operation.kind === OperationKind.COPY) {\n // We are copying, let's not send status updates to the UI\n if (downloadInfoTransform) {\n downloadInfoTransform.beginFileCopy()\n }\n\n copyData(operation, firstStream, oldFileFd, reject, () => w(index))\n return\n }\n\n const range = `bytes=${operation.start}-${operation.end - 1}`\n requestOptions.headers!!.range = range\n\n const debug = this.logger.debug\n if (debug != null) {\n debug(`download range: ${range}`)\n }\n\n // We are starting to download\n if (downloadInfoTransform) {\n downloadInfoTransform.beginRangeDownload()\n }\n\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n if (response.statusCode >= 400) {\n reject(createHttpError(response))\n }\n\n response.pipe(firstStream, {\n end: false\n })\n response.once(\"end\", () => {\n // Pass on that we are downloading a segment\n if (downloadInfoTransform) {\n downloadInfoTransform.endRangeDownload()\n }\n\n if (++downloadOperationCount === 100) {\n downloadOperationCount = 0\n setTimeout(() => w(index), 1000)\n }\n else {\n w(index)\n }\n })\n })\n request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`)\n actualUrl = redirectUrl\n configureRequestUrl(new URL(actualUrl), requestOptions)\n request.followRedirect()\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n }\n\n w(0)\n })\n }\n\n protected async readRemoteBytes(start: number, endInclusive: number): Promise<Buffer> {\n const buffer = Buffer.allocUnsafe((endInclusive + 1) - start)\n const requestOptions = this.createRequestOptions()\n requestOptions.headers!!.range = `bytes=${start}-${endInclusive}`\n let position = 0\n await this.request(requestOptions, chunk => {\n chunk.copy(buffer, position)\n position += chunk.length\n })\n\n if (position !== buffer.length) {\n throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`)\n }\n return buffer\n }\n\n private request(requestOptions: RequestOptions, dataHandler: (chunk: Buffer) => void): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n response.on(\"data\", dataHandler)\n response.on(\"end\", () => resolve())\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n })\n }\n}\n\nfunction formatBytes(value: number, symbol = \" KB\"): string {\n return new Intl.NumberFormat(\"en\").format((value / 1024).toFixed(2) as any) + symbol\n}\n\n// safety\nfunction removeQuery(url: string): string {\n const index = url.indexOf(\"?\")\n return index < 0 ? url : url.substring(0, index)\n}\n\ninterface OpenedFile {\n readonly descriptor: number\n readonly path: string\n}\n"],"sourceRoot":""}
@@ -42,7 +42,7 @@ class FileWithEmbeddedBlockMapDifferentialDownloader extends _DifferentialDownlo
42
42
  const offset = fileSize - (packageInfo.blockMapSize + 4);
43
43
  this.fileMetadataBuffer = await this.readRemoteBytes(offset, fileSize - 1);
44
44
  const newBlockMap = readBlockMap(this.fileMetadataBuffer.slice(0, this.fileMetadataBuffer.length - 4));
45
- await this.doDownload((await readEmbeddedBlockMapData(this.options.oldFile)), newBlockMap);
45
+ await this.doDownload(await readEmbeddedBlockMapData(this.options.oldFile), newBlockMap);
46
46
  }
47
47
 
48
48
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts"],"names":[],"mappings":";;;;;;;AACA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AACA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AACA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAEM,MAAO,8CAAP,SAA8D,gDAA9D,CAAoF;AACxF,QAAM,QAAN,GAAc;AACZ,UAAM,WAAW,GAAG,KAAK,kBAAzB;AACA,UAAM,QAAQ,GAAG,WAAW,CAAC,IAA7B;AACA,UAAM,MAAM,GAAG,QAAQ,IAAI,WAAW,CAAC,YAAZ,GAA6B,CAAjC,CAAvB;AACA,SAAK,kBAAL,GAA0B,MAAM,KAAK,eAAL,CAAqB,MAArB,EAA6B,QAAQ,GAAG,CAAxC,CAAhC;AACA,UAAM,WAAW,GAAG,YAAY,CAAC,KAAK,kBAAL,CAAwB,KAAxB,CAA8B,CAA9B,EAAiC,KAAK,kBAAL,CAAwB,MAAxB,GAAiC,CAAlE,CAAD,CAAhC;AACA,UAAM,KAAK,UAAL,EAAgB,MAAM,wBAAwB,CAAC,KAAK,OAAL,CAAa,OAAd,CAA9C,GAAsE,WAAtE,CAAN;AACD;;AARuF;;;;AAW1F,SAAS,YAAT,CAAsB,IAAtB,EAAkC;AAChC,SAAO,IAAI,CAAC,KAAL,CAAW,4BAAe,IAAf,EAAqB,QAArB,EAAX,CAAP;AACD;;AAED,eAAe,wBAAf,CAAwC,IAAxC,EAAoD;AAClD,QAAM,EAAE,GAAG,MAAM,qBAAK,IAAL,EAAW,GAAX,CAAjB;;AACA,MAAI;AACF,UAAM,QAAQ,GAAG,CAAC,MAAM,sBAAM,EAAN,CAAP,EAAkB,IAAnC;AACA,UAAM,UAAU,GAAG,MAAM,CAAC,WAAP,CAAmB,CAAnB,CAAnB;AACA,UAAM,qBAAK,EAAL,EAAS,UAAT,EAAqB,CAArB,EAAwB,UAAU,CAAC,MAAnC,EAA2C,QAAQ,GAAG,UAAU,CAAC,MAAjE,CAAN;AAEA,UAAM,UAAU,GAAG,MAAM,CAAC,WAAP,CAAmB,UAAU,CAAC,YAAX,CAAwB,CAAxB,CAAnB,CAAnB;AACA,UAAM,qBAAK,EAAL,EAAS,UAAT,EAAqB,CAArB,EAAwB,UAAU,CAAC,MAAnC,EAA2C,QAAQ,GAAG,UAAU,CAAC,MAAtB,GAA+B,UAAU,CAAC,MAArF,CAAN;AACA,UAAM,sBAAM,EAAN,CAAN;AAEA,WAAO,YAAY,CAAC,UAAD,CAAnB;AACD,GAVD,CAWA,OAAO,CAAP,EAAU;AACR,UAAM,sBAAM,EAAN,CAAN;AACA,UAAM,CAAN;AACD;AACF,C","sourcesContent":["import { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, fstat, open, read } from \"fs-extra\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { inflateRawSync } from \"zlib\"\n\nexport class FileWithEmbeddedBlockMapDifferentialDownloader extends DifferentialDownloader {\n async download(): Promise<void> {\n const packageInfo = this.blockAwareFileInfo\n const fileSize = packageInfo.size!!\n const offset = fileSize - (packageInfo.blockMapSize!! + 4)\n this.fileMetadataBuffer = await this.readRemoteBytes(offset, fileSize - 1)\n const newBlockMap = readBlockMap(this.fileMetadataBuffer.slice(0, this.fileMetadataBuffer.length - 4))\n await this.doDownload(await readEmbeddedBlockMapData(this.options.oldFile), newBlockMap)\n }\n}\n\nfunction readBlockMap(data: Buffer): BlockMap {\n return JSON.parse(inflateRawSync(data).toString())\n}\n\nasync function readEmbeddedBlockMapData(file: string): Promise<BlockMap> {\n const fd = await open(file, \"r\")\n try {\n const fileSize = (await fstat(fd)).size\n const sizeBuffer = Buffer.allocUnsafe(4)\n await read(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length)\n\n const dataBuffer = Buffer.allocUnsafe(sizeBuffer.readUInt32BE(0))\n await read(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length)\n await close(fd)\n\n return readBlockMap(dataBuffer)\n }\n catch (e) {\n await close(fd)\n throw e\n }\n}"],"sourceRoot":""}
1
+ {"version":3,"sources":["../../src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts"],"names":[],"mappings":";;;;;;;AACA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AACA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AACA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAEM,MAAO,8CAAP,SAA8D,gDAA9D,CAAoF;AACxF,QAAM,QAAN,GAAc;AACZ,UAAM,WAAW,GAAG,KAAK,kBAAzB;AACA,UAAM,QAAQ,GAAG,WAAW,CAAC,IAA7B;AACA,UAAM,MAAM,GAAG,QAAQ,IAAI,WAAW,CAAC,YAAZ,GAA6B,CAAjC,CAAvB;AACA,SAAK,kBAAL,GAA0B,MAAM,KAAK,eAAL,CAAqB,MAArB,EAA6B,QAAQ,GAAG,CAAxC,CAAhC;AACA,UAAM,WAAW,GAAG,YAAY,CAAC,KAAK,kBAAL,CAAwB,KAAxB,CAA8B,CAA9B,EAAiC,KAAK,kBAAL,CAAwB,MAAxB,GAAiC,CAAlE,CAAD,CAAhC;AACA,UAAM,KAAK,UAAL,CAAgB,MAAM,wBAAwB,CAAC,KAAK,OAAL,CAAa,OAAd,CAA9C,EAAsE,WAAtE,CAAN;AACD;;AARuF;;;;AAW1F,SAAS,YAAT,CAAsB,IAAtB,EAAkC;AAChC,SAAO,IAAI,CAAC,KAAL,CAAW,4BAAe,IAAf,EAAqB,QAArB,EAAX,CAAP;AACD;;AAED,eAAe,wBAAf,CAAwC,IAAxC,EAAoD;AAClD,QAAM,EAAE,GAAG,MAAM,qBAAK,IAAL,EAAW,GAAX,CAAjB;;AACA,MAAI;AACF,UAAM,QAAQ,GAAG,CAAC,MAAM,sBAAM,EAAN,CAAP,EAAkB,IAAnC;AACA,UAAM,UAAU,GAAG,MAAM,CAAC,WAAP,CAAmB,CAAnB,CAAnB;AACA,UAAM,qBAAK,EAAL,EAAS,UAAT,EAAqB,CAArB,EAAwB,UAAU,CAAC,MAAnC,EAA2C,QAAQ,GAAG,UAAU,CAAC,MAAjE,CAAN;AAEA,UAAM,UAAU,GAAG,MAAM,CAAC,WAAP,CAAmB,UAAU,CAAC,YAAX,CAAwB,CAAxB,CAAnB,CAAnB;AACA,UAAM,qBAAK,EAAL,EAAS,UAAT,EAAqB,CAArB,EAAwB,UAAU,CAAC,MAAnC,EAA2C,QAAQ,GAAG,UAAU,CAAC,MAAtB,GAA+B,UAAU,CAAC,MAArF,CAAN;AACA,UAAM,sBAAM,EAAN,CAAN;AAEA,WAAO,YAAY,CAAC,UAAD,CAAnB;AACD,GAVD,CAWA,OAAO,CAAP,EAAU;AACR,UAAM,sBAAM,EAAN,CAAN;AACA,UAAM,CAAN;AACD;AACF,C","sourcesContent":["import { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, fstat, open, read } from \"fs-extra\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { inflateRawSync } from \"zlib\"\n\nexport class FileWithEmbeddedBlockMapDifferentialDownloader extends DifferentialDownloader {\n async download(): Promise<void> {\n const packageInfo = this.blockAwareFileInfo\n const fileSize = packageInfo.size!!\n const offset = fileSize - (packageInfo.blockMapSize!! + 4)\n this.fileMetadataBuffer = await this.readRemoteBytes(offset, fileSize - 1)\n const newBlockMap = readBlockMap(this.fileMetadataBuffer.slice(0, this.fileMetadataBuffer.length - 4))\n await this.doDownload(await readEmbeddedBlockMapData(this.options.oldFile), newBlockMap)\n }\n}\n\nfunction readBlockMap(data: Buffer): BlockMap {\n return JSON.parse(inflateRawSync(data).toString())\n}\n\nasync function readEmbeddedBlockMapData(file: string): Promise<BlockMap> {\n const fd = await open(file, \"r\")\n try {\n const fileSize = (await fstat(fd)).size\n const sizeBuffer = Buffer.allocUnsafe(4)\n await read(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length)\n\n const dataBuffer = Buffer.allocUnsafe(sizeBuffer.readUInt32BE(0))\n await read(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length)\n await close(fd)\n\n return readBlockMap(dataBuffer)\n }\n catch (e) {\n await close(fd)\n throw e\n }\n}"],"sourceRoot":""}
@@ -0,0 +1,32 @@
1
+ /// <reference types="node" />
2
+ import { Transform } from "stream";
3
+ import { CancellationToken } from "builder-util-runtime";
4
+ export interface ProgressInfo {
5
+ total: number;
6
+ delta: number;
7
+ transferred: number;
8
+ percent: number;
9
+ bytesPerSecond: number;
10
+ }
11
+ export interface ProgressDifferentialDownloadInfo {
12
+ expectedByteCounts: Array<number>;
13
+ grandTotal: number;
14
+ }
15
+ export declare class ProgressDifferentialDownloadCallbackTransform extends Transform {
16
+ private readonly progressDifferentialDownloadInfo;
17
+ private readonly cancellationToken;
18
+ private readonly onProgress;
19
+ private start;
20
+ private transferred;
21
+ private delta;
22
+ private expectedBytes;
23
+ private index;
24
+ private operationType;
25
+ private nextUpdate;
26
+ constructor(progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo, cancellationToken: CancellationToken, onProgress: (info: ProgressInfo) => any);
27
+ _transform(chunk: any, encoding: string, callback: any): void;
28
+ beginFileCopy(): void;
29
+ beginRangeDownload(): void;
30
+ endRangeDownload(): void;
31
+ _flush(callback: any): void;
32
+ }
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ProgressDifferentialDownloadCallbackTransform = void 0;
7
+
8
+ function _stream() {
9
+ const data = require("stream");
10
+
11
+ _stream = function () {
12
+ return data;
13
+ };
14
+
15
+ return data;
16
+ }
17
+
18
+ var OperationKind;
19
+
20
+ (function (OperationKind) {
21
+ OperationKind[OperationKind["COPY"] = 0] = "COPY";
22
+ OperationKind[OperationKind["DOWNLOAD"] = 1] = "DOWNLOAD";
23
+ })(OperationKind || (OperationKind = {}));
24
+
25
+ class ProgressDifferentialDownloadCallbackTransform extends _stream().Transform {
26
+ constructor(progressDifferentialDownloadInfo, cancellationToken, onProgress) {
27
+ super();
28
+ this.progressDifferentialDownloadInfo = progressDifferentialDownloadInfo;
29
+ this.cancellationToken = cancellationToken;
30
+ this.onProgress = onProgress;
31
+ this.start = Date.now();
32
+ this.transferred = 0;
33
+ this.delta = 0;
34
+ this.expectedBytes = 0;
35
+ this.index = 0;
36
+ this.operationType = OperationKind.COPY;
37
+ this.nextUpdate = this.start + 1000;
38
+ }
39
+
40
+ _transform(chunk, encoding, callback) {
41
+ if (this.cancellationToken.cancelled) {
42
+ callback(new Error("cancelled"), null);
43
+ return;
44
+ } // Don't send progress update when copying from disk
45
+
46
+
47
+ if (this.operationType == OperationKind.COPY) {
48
+ callback(null, chunk);
49
+ return;
50
+ }
51
+
52
+ this.transferred += chunk.length;
53
+ this.delta += chunk.length;
54
+ const now = Date.now();
55
+
56
+ if (now >= this.nextUpdate && this.transferred !== this.expectedBytes
57
+ /* will be emitted by endRangeDownload() */
58
+ && this.transferred !== this.progressDifferentialDownloadInfo.grandTotal
59
+ /* will be emitted on _flush */
60
+ ) {
61
+ this.nextUpdate = now + 1000;
62
+ this.onProgress({
63
+ total: this.progressDifferentialDownloadInfo.grandTotal,
64
+ delta: this.delta,
65
+ transferred: this.transferred,
66
+ percent: this.transferred / this.progressDifferentialDownloadInfo.grandTotal * 100,
67
+ bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000))
68
+ });
69
+ this.delta = 0;
70
+ }
71
+
72
+ callback(null, chunk);
73
+ }
74
+
75
+ beginFileCopy() {
76
+ this.operationType = OperationKind.COPY;
77
+ }
78
+
79
+ beginRangeDownload() {
80
+ this.operationType = OperationKind.DOWNLOAD;
81
+ this.expectedBytes += this.progressDifferentialDownloadInfo.expectedByteCounts[this.index++];
82
+ }
83
+
84
+ endRangeDownload() {
85
+ // _flush() will doour final 100%
86
+ if (this.transferred !== this.progressDifferentialDownloadInfo.grandTotal) {
87
+ this.onProgress({
88
+ total: this.progressDifferentialDownloadInfo.grandTotal,
89
+ delta: this.delta,
90
+ transferred: this.transferred,
91
+ percent: this.transferred / this.progressDifferentialDownloadInfo.grandTotal * 100,
92
+ bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000))
93
+ });
94
+ }
95
+ } // Called when we are 100% done with the connection/download
96
+
97
+
98
+ _flush(callback) {
99
+ if (this.cancellationToken.cancelled) {
100
+ callback(new Error("cancelled"));
101
+ return;
102
+ }
103
+
104
+ this.onProgress({
105
+ total: this.progressDifferentialDownloadInfo.grandTotal,
106
+ delta: this.delta,
107
+ transferred: this.transferred,
108
+ percent: 100,
109
+ bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000))
110
+ });
111
+ this.delta = 0;
112
+ this.transferred = 0;
113
+ callback(null);
114
+ }
115
+
116
+ } exports.ProgressDifferentialDownloadCallbackTransform = ProgressDifferentialDownloadCallbackTransform;
117
+ // __ts-babel@6.0.4
118
+ //# sourceMappingURL=ProgressDifferentialDownloadCallbackTransform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.ts"],"names":[],"mappings":"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","sourcesContent":["import { Transform } from \"stream\"\nimport { CancellationToken } from \"builder-util-runtime\"\n\nenum OperationKind {\n COPY, DOWNLOAD\n}\n\nexport interface ProgressInfo {\n total: number\n delta: number\n transferred: number\n percent: number\n bytesPerSecond: number\n}\n\nexport interface ProgressDifferentialDownloadInfo {\n expectedByteCounts: Array<number>\n grandTotal: number\n}\n\nexport class ProgressDifferentialDownloadCallbackTransform extends Transform {\n private start = Date.now()\n private transferred = 0\n private delta = 0\n private expectedBytes = 0\n private index = 0\n private operationType = OperationKind.COPY\n\n private nextUpdate = this.start + 1000\n\n constructor(private readonly progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo, private readonly cancellationToken: CancellationToken, private readonly onProgress: (info: ProgressInfo) => any) {\n super()\n }\n\n _transform(chunk: any, encoding: string, callback: any) {\n if (this.cancellationToken.cancelled) {\n callback(new Error(\"cancelled\"), null)\n return\n }\n\n // Don't send progress update when copying from disk\n if (this.operationType == OperationKind.COPY) {\n callback(null, chunk)\n return\n }\n\n this.transferred += chunk.length\n this.delta += chunk.length\n\n const now = Date.now()\n if (now >= this.nextUpdate\n && this.transferred !== this.expectedBytes /* will be emitted by endRangeDownload() */\n && this.transferred !== this.progressDifferentialDownloadInfo.grandTotal /* will be emitted on _flush */) {\n this.nextUpdate = now + 1000\n\n this.onProgress({\n total: this.progressDifferentialDownloadInfo.grandTotal,\n delta: this.delta,\n transferred: this.transferred,\n percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,\n bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000))\n })\n this.delta = 0\n }\n\n callback(null, chunk)\n }\n\n beginFileCopy(): void {\n this.operationType = OperationKind.COPY\n }\n\n beginRangeDownload(): void {\n this.operationType = OperationKind.DOWNLOAD\n\n this.expectedBytes += this.progressDifferentialDownloadInfo.expectedByteCounts[this.index++]\n }\n\n endRangeDownload(): void {\n // _flush() will doour final 100%\n if (this.transferred !== this.progressDifferentialDownloadInfo.grandTotal) {\n this.onProgress({\n total: this.progressDifferentialDownloadInfo.grandTotal,\n delta: this.delta,\n transferred: this.transferred,\n percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,\n bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000))\n })\n }\n }\n\n // Called when we are 100% done with the connection/download\n _flush(callback: any): void {\n if (this.cancellationToken.cancelled) {\n callback(new Error(\"cancelled\"))\n return\n }\n\n this.onProgress({\n total: this.progressDifferentialDownloadInfo.grandTotal,\n delta: this.delta,\n transferred: this.transferred,\n percent: 100,\n bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000))\n })\n this.delta = 0\n this.transferred = 0\n\n\n callback(null)\n }\n}\n"],"sourceRoot":""}
@@ -102,7 +102,6 @@ function buildChecksumMap(file, fileOffset, logger) {
102
102
  const checksumToOffset = new Map();
103
103
  const checksumToSize = new Map();
104
104
  let offset = fileOffset;
105
- const debugLog = logger.debug;
106
105
 
107
106
  for (let i = 0; i < file.checksums.length; i++) {
108
107
  const checksum = file.checksums[i];
@@ -112,9 +111,9 @@ function buildChecksumMap(file, fileOffset, logger) {
112
111
  if (existing === undefined) {
113
112
  checksumToOffset.set(checksum, offset);
114
113
  checksumToSize.set(checksum, size);
115
- } else if (debugLog != null) {
114
+ } else if (logger.debug != null) {
116
115
  const sizeExplanation = existing === size ? "(same size)" : `(size: ${existing}, this size: ${size})`;
117
- debugLog(`${checksum} duplicated in blockmap ${sizeExplanation}, it doesn't lead to broken differential downloader, just corresponding block will be skipped)`);
116
+ logger.debug(`${checksum} duplicated in blockmap ${sizeExplanation}, it doesn't lead to broken differential downloader, just corresponding block will be skipped)`);
118
117
  }
119
118
 
120
119
  offset += size;