index.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import debug from 'debug';
  2. import * as fs from 'fs-extra';
  3. import * as path from 'path';
  4. import * as semver from 'semver';
  5. import * as sumchecker from 'sumchecker';
  6. import { getArtifactFileName, getArtifactRemoteURL, getArtifactVersion } from './artifact-utils';
  7. import { Cache } from './Cache';
  8. import { getDownloaderForSystem } from './downloader-resolver';
  9. import { initializeProxy } from './proxy';
  10. import { withTempDirectoryIn, getHostArch, getNodeArch, ensureIsTruthyString, isOfficialLinuxIA32Download, } from './utils';
  11. export { getHostArch } from './utils';
  12. export { initializeProxy } from './proxy';
  13. const d = debug('@electron/get:index');
  14. if (process.env.ELECTRON_GET_USE_PROXY) {
  15. initializeProxy();
  16. }
  17. async function validateArtifact(artifactDetails, downloadedAssetPath, _downloadArtifact) {
  18. return await withTempDirectoryIn(artifactDetails.tempDirectory, async (tempFolder) => {
  19. // Don't try to verify the hash of the hash file itself
  20. // and for older versions that don't have a SHASUMS256.txt
  21. if (!artifactDetails.artifactName.startsWith('SHASUMS256') &&
  22. !artifactDetails.unsafelyDisableChecksums &&
  23. semver.gte(artifactDetails.version, '1.3.2')) {
  24. let shasumPath;
  25. const checksums = artifactDetails.checksums;
  26. if (checksums) {
  27. shasumPath = path.resolve(tempFolder, 'SHASUMS256.txt');
  28. const fileNames = Object.keys(checksums);
  29. if (fileNames.length === 0) {
  30. throw new Error('Provided "checksums" object is empty, cannot generate a valid SHASUMS256.txt');
  31. }
  32. const generatedChecksums = fileNames
  33. .map(fileName => `${checksums[fileName]} *${fileName}`)
  34. .join('\n');
  35. await fs.writeFile(shasumPath, generatedChecksums);
  36. }
  37. else {
  38. shasumPath = await _downloadArtifact({
  39. isGeneric: true,
  40. version: artifactDetails.version,
  41. artifactName: 'SHASUMS256.txt',
  42. force: artifactDetails.force,
  43. downloadOptions: artifactDetails.downloadOptions,
  44. cacheRoot: artifactDetails.cacheRoot,
  45. downloader: artifactDetails.downloader,
  46. mirrorOptions: artifactDetails.mirrorOptions,
  47. });
  48. }
  49. // For versions 1.3.2 - 1.3.4, need to overwrite the `defaultTextEncoding` option:
  50. // https://github.com/electron/electron/pull/6676#discussion_r75332120
  51. if (semver.satisfies(artifactDetails.version, '1.3.2 - 1.3.4')) {
  52. const validatorOptions = {};
  53. validatorOptions.defaultTextEncoding = 'binary';
  54. const checker = new sumchecker.ChecksumValidator('sha256', shasumPath, validatorOptions);
  55. await checker.validate(path.dirname(downloadedAssetPath), path.basename(downloadedAssetPath));
  56. }
  57. else {
  58. await sumchecker('sha256', shasumPath, path.dirname(downloadedAssetPath), [
  59. path.basename(downloadedAssetPath),
  60. ]);
  61. }
  62. }
  63. });
  64. }
  65. /**
  66. * Downloads an artifact from an Electron release and returns an absolute path
  67. * to the downloaded file.
  68. *
  69. * @param artifactDetails - The information required to download the artifact
  70. */
  71. export async function downloadArtifact(_artifactDetails) {
  72. const artifactDetails = Object.assign({}, _artifactDetails);
  73. if (!_artifactDetails.isGeneric) {
  74. const platformArtifactDetails = artifactDetails;
  75. if (!platformArtifactDetails.platform) {
  76. d('No platform found, defaulting to the host platform');
  77. platformArtifactDetails.platform = process.platform;
  78. }
  79. if (platformArtifactDetails.arch) {
  80. platformArtifactDetails.arch = getNodeArch(platformArtifactDetails.arch);
  81. }
  82. else {
  83. d('No arch found, defaulting to the host arch');
  84. platformArtifactDetails.arch = getHostArch();
  85. }
  86. }
  87. ensureIsTruthyString(artifactDetails, 'version');
  88. artifactDetails.version = getArtifactVersion(artifactDetails);
  89. const fileName = getArtifactFileName(artifactDetails);
  90. const url = await getArtifactRemoteURL(artifactDetails);
  91. const cache = new Cache(artifactDetails.cacheRoot);
  92. // Do not check if the file exists in the cache when force === true
  93. if (!artifactDetails.force) {
  94. d(`Checking the cache (${artifactDetails.cacheRoot}) for ${fileName} (${url})`);
  95. const cachedPath = await cache.getPathForFileInCache(url, fileName);
  96. if (cachedPath === null) {
  97. d('Cache miss');
  98. }
  99. else {
  100. d('Cache hit');
  101. try {
  102. await validateArtifact(artifactDetails, cachedPath, downloadArtifact);
  103. return cachedPath;
  104. }
  105. catch (err) {
  106. d("Artifact in cache didn't match checksums", err);
  107. d('falling back to re-download');
  108. }
  109. }
  110. }
  111. if (!artifactDetails.isGeneric &&
  112. isOfficialLinuxIA32Download(artifactDetails.platform, artifactDetails.arch, artifactDetails.version, artifactDetails.mirrorOptions)) {
  113. console.warn('Official Linux/ia32 support is deprecated.');
  114. console.warn('For more info: https://electronjs.org/blog/linux-32bit-support');
  115. }
  116. return await withTempDirectoryIn(artifactDetails.tempDirectory, async (tempFolder) => {
  117. const tempDownloadPath = path.resolve(tempFolder, getArtifactFileName(artifactDetails));
  118. const downloader = artifactDetails.downloader || (await getDownloaderForSystem());
  119. d(`Downloading ${url} to ${tempDownloadPath} with options: ${JSON.stringify(artifactDetails.downloadOptions)}`);
  120. await downloader.download(url, tempDownloadPath, artifactDetails.downloadOptions);
  121. await validateArtifact(artifactDetails, tempDownloadPath, downloadArtifact);
  122. return await cache.putFileInCache(url, tempDownloadPath, fileName);
  123. });
  124. }
  125. /**
  126. * Downloads a specific version of Electron and returns an absolute path to a
  127. * ZIP file.
  128. *
  129. * @param version - The version of Electron you want to download
  130. */
  131. export function download(version, options) {
  132. return downloadArtifact(Object.assign(Object.assign({}, options), { version, platform: process.platform, arch: process.arch, artifactName: 'electron' }));
  133. }
  134. //# sourceMappingURL=index.js.map