diff options
Diffstat (limited to 'remote/test/puppeteer/packages/browsers/src/Cache.ts')
-rw-r--r-- | remote/test/puppeteer/packages/browsers/src/Cache.ts | 63 |
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, |