From 790db6aabfaefca7a9f61c176f7fea4a6188d445 Mon Sep 17 00:00:00 2001
From: Alexey Kuzmin <alex.s.kuzmin@gmail.com>
Date: Sat, 16 Nov 2019 01:15:42 +0100
Subject: [PATCH] feat: add optional "tempDirectory" download request option
 (#127)

---
 src/index.ts |  4 ++--
 src/types.ts |  5 +++++
 src/utils.ts | 29 ++++++++++++++++++-----------
 3 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/src/index.ts b/src/index.ts
index 2ab568d5c..b929d71e0 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -11,7 +11,7 @@ import { Cache } from './Cache';
 import { getDownloaderForSystem } from './downloader-resolver';
 import { initializeProxy } from './proxy';
 import {
-  withTempDirectory,
+  withTempDirectoryIn,
   normalizeVersion,
   getHostArch,
   ensureIsTruthyString,
@@ -99,7 +99,7 @@ export async function downloadArtifact(
     console.warn('For more info: https://electronjs.org/blog/linux-32bit-support');
   }
 
-  return await withTempDirectory(async tempFolder => {
+  return await withTempDirectoryIn(artifactDetails.tempDirectory, async tempFolder => {
     const tempDownloadPath = path.resolve(tempFolder, getArtifactFileName(artifactDetails));
 
     const downloader = artifactDetails.downloader || (await getDownloaderForSystem());
diff --git a/src/types.ts b/src/types.ts
index 1b6a9998b..1f72c51fd 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -60,6 +60,11 @@ export interface ElectronDownloadRequestOptions {
    * built-in [[GotDownloader]].
    */
   downloader?: Downloader<any>;
+  /**
+   * A temporary directory for downloads.
+   * It is used before artifacts are put into cache.
+   */
+  tempDirectory?: string;
 }
 
 export type ElectronPlatformArtifactDetails = {
diff --git a/src/utils.ts b/src/utils.ts
index d84543af1..03f629549 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -3,25 +3,32 @@ import * as fs from 'fs-extra';
 import * as os from 'os';
 import * as path from 'path';
 
-export async function withTempDirectory<T>(fn: (directory: string) => Promise<T>): Promise<T> {
-  const directory = await fs.mkdtemp(path.resolve(os.tmpdir(), 'electron-download-'));
-
+async function useAndRemoveDirectory<T>(
+  directory: string,
+  fn: (directory: string) => Promise<T>,
+): Promise<T> {
   let result: T;
   try {
     result = await fn(directory);
-  } catch (err) {
-    await fs.remove(directory);
-    throw err;
-  }
-
-  try {
+  } finally {
     await fs.remove(directory);
-  } catch {
-    // Ignore error, it's just a temp dir
   }
   return result;
 }
 
+export async function withTempDirectoryIn<T>(
+  parentDirectory: string = os.tmpdir(),
+  fn: (directory: string) => Promise<T>,
+): Promise<T> {
+  const tempDirectoryPrefix = 'electron-download-';
+  const tempDirectory = await fs.mkdtemp(path.resolve(parentDirectory, tempDirectoryPrefix));
+  return useAndRemoveDirectory(tempDirectory, fn);
+}
+
+export async function withTempDirectory<T>(fn: (directory: string) => Promise<T>): Promise<T> {
+  return withTempDirectoryIn(undefined, fn);
+}
+
 export function normalizeVersion(version: string) {
   if (!version.startsWith('v')) {
     return `v${version}`;