Skip to content

Commit 5320f4e

Browse files
committed
Make APK downloading more reliable
1 parent 3ac6f8c commit 5320f4e

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

src/interceptors/android/fetch-apk.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as stream from 'stream';
44
import * as semver from 'semver';
55
import fetch from 'node-fetch';
66

7-
import { readDir, createTmp, renameFile, deleteFile } from '../../util';
7+
import { readDir, createTmp, moveFile, deleteFile } from '../../util';
88
import { HtkConfig } from '../../config';
99
import { reportError } from '../../error-tracking';
1010

@@ -85,7 +85,7 @@ async function updateLocalApk(
8585

8686
console.log(`Local APK written to ${tmpApk}`);
8787

88-
await renameFile(tmpApk, path.join(config.configPath, `httptoolkit-${version}.apk`));
88+
await moveFile(tmpApk, path.join(config.configPath, `httptoolkit-${version}.apk`));
8989
console.log(`Local APK moved to ${path.join(config.configPath, `httptoolkit-${version}.apk`)}`);
9090
await cleanupOldApks(config);
9191
}
@@ -123,7 +123,7 @@ export async function streamLatestApk(config: HtkConfig): Promise<stream.Readabl
123123
} else {
124124
console.log('Streaming remote APK directly');
125125
const apkStream = (await fetch(latestApkRelease.url)).body;
126-
updateLocalApk(latestApkRelease.version, apkStream, config);
126+
updateLocalApk(latestApkRelease.version, apkStream, config).catch(reportError);
127127
return apkStream as stream.Readable;
128128
}
129129
}
@@ -138,7 +138,7 @@ export async function streamLatestApk(config: HtkConfig): Promise<stream.Readabl
138138
// Try to update it async, and use the local APK in the meantime.
139139
fetch(latestApkRelease.url).then((apkResponse) => {
140140
const apkStream = apkResponse.body;
141-
updateLocalApk(latestApkRelease.version, apkStream, config);
141+
return updateLocalApk(latestApkRelease.version, apkStream, config);
142142
}).catch(reportError);
143143

144144
console.log('Streaming local APK, and updating it async');

src/util.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const checkAccess = promisify(fs.access);
5858
export const mkDir = promisify(fs.mkdir);
5959
export const writeFile = promisify(fs.writeFile);
6060
export const renameFile = promisify(fs.rename);
61+
export const copyFile = promisify(fs.copyFile);
6162

6263
export const canAccess = (path: string) => checkAccess(path).then(() => true).catch(() => false);
6364

@@ -75,4 +76,17 @@ export const createTmp = (options: tmp.Options = {}) => new Promise<{
7576
if (err) return reject(err);
7677
resolve({ path, fd, cleanupCallback });
7778
});
78-
});
79+
});
80+
81+
export const moveFile = async (oldPath: string, newPath: string) => {
82+
try {
83+
await renameFile(oldPath, newPath);
84+
} catch (e) {
85+
if (e.code === 'EXDEV') {
86+
// Cross-device - can't rename files across partions etc.
87+
// In that case, we fallback to copy then delete:
88+
await copyFile(oldPath, newPath);
89+
await deleteFile(oldPath);
90+
}
91+
}
92+
};

0 commit comments

Comments
 (0)