index.js 6.1 KB

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