fileUtil.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /**
  2. * @license
  3. * Copyright 2023 Google Inc.
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. import { exec as execChildProcess, spawnSync } from 'child_process';
  7. import { createReadStream } from 'fs';
  8. import { mkdir, readdir } from 'fs/promises';
  9. import * as path from 'path';
  10. import { promisify } from 'util';
  11. import extractZip from 'extract-zip';
  12. import tar from 'tar-fs';
  13. import bzip from 'unbzip2-stream';
  14. const exec = promisify(execChildProcess);
  15. /**
  16. * @internal
  17. */
  18. export async function unpackArchive(archivePath, folderPath) {
  19. if (archivePath.endsWith('.zip')) {
  20. await extractZip(archivePath, { dir: folderPath });
  21. }
  22. else if (archivePath.endsWith('.tar.bz2')) {
  23. await extractTar(archivePath, folderPath);
  24. }
  25. else if (archivePath.endsWith('.dmg')) {
  26. await mkdir(folderPath);
  27. await installDMG(archivePath, folderPath);
  28. }
  29. else if (archivePath.endsWith('.exe')) {
  30. // Firefox on Windows.
  31. const result = spawnSync(archivePath, [`/ExtractDir=${folderPath}`], {
  32. env: {
  33. __compat_layer: 'RunAsInvoker',
  34. },
  35. });
  36. if (result.status !== 0) {
  37. throw new Error(`Failed to extract ${archivePath} to ${folderPath}: ${result.output}`);
  38. }
  39. }
  40. else {
  41. throw new Error(`Unsupported archive format: ${archivePath}`);
  42. }
  43. }
  44. /**
  45. * @internal
  46. */
  47. function extractTar(tarPath, folderPath) {
  48. return new Promise((fulfill, reject) => {
  49. const tarStream = tar.extract(folderPath);
  50. tarStream.on('error', reject);
  51. tarStream.on('finish', fulfill);
  52. const readStream = createReadStream(tarPath);
  53. readStream.pipe(bzip()).pipe(tarStream);
  54. });
  55. }
  56. /**
  57. * @internal
  58. */
  59. async function installDMG(dmgPath, folderPath) {
  60. const { stdout } = await exec(`hdiutil attach -nobrowse -noautoopen "${dmgPath}"`);
  61. const volumes = stdout.match(/\/Volumes\/(.*)/m);
  62. if (!volumes) {
  63. throw new Error(`Could not find volume path in ${stdout}`);
  64. }
  65. const mountPath = volumes[0];
  66. try {
  67. const fileNames = await readdir(mountPath);
  68. const appName = fileNames.find(item => {
  69. return typeof item === 'string' && item.endsWith('.app');
  70. });
  71. if (!appName) {
  72. throw new Error(`Cannot find app in ${mountPath}`);
  73. }
  74. const mountedPath = path.join(mountPath, appName);
  75. await exec(`cp -R "${mountedPath}" "${folderPath}"`);
  76. }
  77. finally {
  78. await exec(`hdiutil detach "${mountPath}" -quiet`);
  79. }
  80. }
  81. //# sourceMappingURL=fileUtil.js.map