summaryrefslogtreecommitdiffstats
path: root/remote/test/puppeteer/packages/browsers/src/Cache.ts
diff options
context:
space:
mode:
Diffstat (limited to 'remote/test/puppeteer/packages/browsers/src/Cache.ts')
-rw-r--r--remote/test/puppeteer/packages/browsers/src/Cache.ts63
1 files changed, 63 insertions, 0 deletions
diff --git a/remote/test/puppeteer/packages/browsers/src/Cache.ts b/remote/test/puppeteer/packages/browsers/src/Cache.ts
index 13b465835a..e6b574d9dd 100644
--- a/remote/test/puppeteer/packages/browsers/src/Cache.ts
+++ b/remote/test/puppeteer/packages/browsers/src/Cache.ts
@@ -8,13 +8,18 @@ import fs from 'fs';
import os from 'os';
import path from 'path';
+import debug from 'debug';
+
import {
Browser,
type BrowserPlatform,
executablePathByBrowser,
+ getVersionComparator,
} from './browser-data/browser-data.js';
import {detectBrowserPlatform} from './detectPlatform.js';
+const debugCache = debug('puppeteer:browsers:cache');
+
/**
* @public
*/
@@ -57,6 +62,14 @@ export class InstalledBrowser {
this.buildId
);
}
+
+ readMetadata(): Metadata {
+ return this.#cache.readMetadata(this.browser);
+ }
+
+ writeMetadata(metadata: Metadata): void {
+ this.#cache.writeMetadata(this.browser, metadata);
+ }
}
/**
@@ -80,6 +93,11 @@ export interface ComputeExecutablePathOptions {
buildId: string;
}
+export interface Metadata {
+ // Maps an alias (canary/latest/dev/etc.) to a buildId.
+ aliases: Record<string, string>;
+}
+
/**
* The cache used by Puppeteer relies on the following structure:
*
@@ -112,6 +130,39 @@ export class Cache {
return path.join(this.#rootDir, browser);
}
+ metadataFile(browser: Browser): string {
+ return path.join(this.browserRoot(browser), '.metadata');
+ }
+
+ readMetadata(browser: Browser): Metadata {
+ const metatadaPath = this.metadataFile(browser);
+ if (!fs.existsSync(metatadaPath)) {
+ return {aliases: {}};
+ }
+ // TODO: add type-safe parsing.
+ const data = JSON.parse(fs.readFileSync(metatadaPath, 'utf8'));
+ if (typeof data !== 'object') {
+ throw new Error('.metadata is not an object');
+ }
+ return data;
+ }
+
+ writeMetadata(browser: Browser, metadata: Metadata): void {
+ const metatadaPath = this.metadataFile(browser);
+ fs.mkdirSync(path.dirname(metatadaPath), {recursive: true});
+ fs.writeFileSync(metatadaPath, JSON.stringify(metadata, null, 2));
+ }
+
+ resolveAlias(browser: Browser, alias: string): string | undefined {
+ const metadata = this.readMetadata(browser);
+ if (alias === 'latest') {
+ return Object.values(metadata.aliases || {})
+ .sort(getVersionComparator(browser))
+ .at(-1);
+ }
+ return metadata.aliases[alias];
+ }
+
installationDir(
browser: Browser,
platform: BrowserPlatform,
@@ -134,6 +185,12 @@ export class Cache {
platform: BrowserPlatform,
buildId: string
): void {
+ const metadata = this.readMetadata(browser);
+ for (const alias of Object.keys(metadata.aliases)) {
+ if (metadata.aliases[alias] === buildId) {
+ delete metadata.aliases[alias];
+ }
+ }
fs.rmSync(this.installationDir(browser, platform, buildId), {
force: true,
recursive: true,
@@ -180,6 +237,12 @@ export class Cache {
`Cannot download a binary for the provided platform: ${os.platform()} (${os.arch()})`
);
}
+ try {
+ options.buildId =
+ this.resolveAlias(options.browser, options.buildId) ?? options.buildId;
+ } catch {
+ debugCache('could not read .metadata file for the browser');
+ }
const installationDir = this.installationDir(
options.browser,
options.platform,