download-binary.ts 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import stream from 'stream'
  2. import { promisify } from 'util'
  3. import fs from 'fs'
  4. import got from 'got'
  5. import { CargoManifest } from '../types/cargo'
  6. import path from 'path'
  7. const pipeline = promisify(stream.pipeline)
  8. // Webpack reads the file at build-time, so this becomes a static var
  9. // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
  10. const tauriCliManifest = require('../../../cli.rs/Cargo.toml') as CargoManifest
  11. const downloads: { [url: string]: boolean } = {}
  12. async function downloadBinaryRelease(
  13. tag: string,
  14. asset: string,
  15. outPath: string
  16. ): Promise<void> {
  17. const url = `https://github.com/tauri-apps/binary-releases/releases/download/${tag}/${asset}`
  18. const removeDownloadedCliIfNeeded = (): void => {
  19. try {
  20. if (!(url in downloads)) {
  21. // eslint-disable-next-line security/detect-non-literal-fs-filename
  22. fs.unlinkSync(outPath)
  23. }
  24. } finally {
  25. process.exit()
  26. }
  27. }
  28. // on exit, we remove the `tauri-cli` file if the download didn't complete
  29. process.on('exit', removeDownloadedCliIfNeeded)
  30. process.on('SIGINT', removeDownloadedCliIfNeeded)
  31. process.on('SIGTERM', removeDownloadedCliIfNeeded)
  32. process.on('SIGHUP', removeDownloadedCliIfNeeded)
  33. process.on('SIGBREAK', removeDownloadedCliIfNeeded)
  34. // TODO: Check hash of download
  35. // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, security/detect-non-literal-fs-filename
  36. await pipeline(got.stream(url), fs.createWriteStream(outPath)).catch((e) => {
  37. removeDownloadedCliIfNeeded()
  38. throw e
  39. })
  40. // eslint-disable-next-line security/detect-object-injection
  41. downloads[url] = true
  42. // eslint-disable-next-line security/detect-non-literal-fs-filename
  43. fs.chmodSync(outPath, 0o700)
  44. console.log('Download Complete')
  45. }
  46. async function downloadCli(): Promise<void> {
  47. const version = tauriCliManifest.package.version
  48. let platform: string = process.platform
  49. if (platform === 'win32') {
  50. platform = 'windows'
  51. } else if (platform === 'linux') {
  52. platform = 'linux'
  53. } else if (platform === 'darwin') {
  54. platform = 'macos'
  55. } else {
  56. throw Error('Unsupported platform')
  57. }
  58. const extension = platform === 'windows' ? '.exe' : ''
  59. const outPath = path.join(__dirname, `../../bin/tauri-cli${extension}`)
  60. console.log('Downloading Rust CLI...')
  61. await downloadBinaryRelease(
  62. `tauri-cli-v${version}`,
  63. `tauri-cli_${platform}${extension}`,
  64. outPath
  65. )
  66. }
  67. async function downloadRustup(): Promise<void> {
  68. const assetName =
  69. process.platform === 'win32' ? 'rustup-init.exe' : 'rustup-init.sh'
  70. console.log('Downloading Rustup...')
  71. return await downloadBinaryRelease(
  72. 'rustup',
  73. assetName,
  74. path.join(__dirname, `../../bin/${assetName}`)
  75. )
  76. }
  77. export { downloadCli, downloadRustup }