(installTarget: string, url: string, algo: string, binPath: string | null = null)
| 141 | } |
| 142 | |
| 143 | async function download(installTarget: string, url: string, algo: string, binPath: string | null = null): Promise<DownloadSpec> { |
| 144 | // Creating a temporary folder inside the install folder means that we |
| 145 | // are sure it'll be in the same drive as the destination, so we can |
| 146 | // just move it there atomically once we are done |
| 147 | |
| 148 | const tmpFolder = folderUtils.getTemporaryFolder(installTarget); |
| 149 | debugUtils.log(`Downloading to ${tmpFolder}`); |
| 150 | |
| 151 | const stream = await httpUtils.fetchUrlStream(url); |
| 152 | |
| 153 | const parsedUrl = new URL(url); |
| 154 | const ext = path.posix.extname(parsedUrl.pathname); |
| 155 | |
| 156 | let outputFile: string | null = null; |
| 157 | let sendTo: any; |
| 158 | |
| 159 | if (ext === `.tgz`) { |
| 160 | const {extract: tarX} = await import(`tar/extract`); |
| 161 | sendTo = tarX({ |
| 162 | strip: 1, |
| 163 | cwd: tmpFolder, |
| 164 | filter: binPath ? path => { |
| 165 | const pos = path.indexOf(`/`); |
| 166 | return pos !== -1 && path.slice(pos + 1) === binPath; |
| 167 | } : undefined, |
| 168 | }); |
| 169 | } else if (ext === `.js`) { |
| 170 | outputFile = path.join(tmpFolder, path.posix.basename(parsedUrl.pathname)); |
| 171 | sendTo = fs.createWriteStream(outputFile); |
| 172 | } |
| 173 | stream.pipe(sendTo); |
| 174 | |
| 175 | let hash = !binPath ? stream.pipe(createHash(algo)) : null; |
| 176 | await once(sendTo, `finish`); |
| 177 | |
| 178 | if (binPath) { |
| 179 | const downloadedBin = path.join(tmpFolder, binPath); |
| 180 | outputFile = path.join(tmpFolder, path.basename(downloadedBin)); |
| 181 | try { |
| 182 | await renameSafe(downloadedBin, outputFile); |
| 183 | } catch (err) { |
| 184 | if (nodeUtils.isNodeError(err) && err.code === `ENOENT`) |
| 185 | throw new Error(`Cannot locate '${binPath}' in downloaded tarball`, {cause: err}); |
| 186 | |
| 187 | // It's alright if another process downloaded the same binary in parallel |
| 188 | if (nodeUtils.isNodeError(err) && nodeUtils.isExistError(err)) { |
| 189 | await fs.promises.rm(downloadedBin); |
| 190 | } else { |
| 191 | throw err; |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | // Calculate the hash of the bin file |
| 196 | const fileStream = fs.createReadStream(outputFile); |
| 197 | hash = fileStream.pipe(createHash(algo)); |
| 198 | await once(fileStream, `close`); |
| 199 | } |
| 200 |
no test coverage detected
searching dependent graphs…