respect "prefix" field

This commit is contained in:
Simon Knott 2024-12-16 09:08:20 +01:00
parent a53821415f
commit 2c9bbf78eb
No known key found for this signature in database
GPG key ID: 8CEDC00028084AEC
2 changed files with 103 additions and 78 deletions

View file

@ -16,6 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import { Writable, once } from 'stream'; import { Writable, once } from 'stream';
import assert from 'assert'; import assert from 'assert';
import { join } from 'path';
enum TarType { enum TarType {
REGTYPE, REGTYPE,
@ -36,6 +37,7 @@ class TarEntry {
linkname: string; linkname: string;
uid: number; uid: number;
gid: number; gid: number;
prefix: string;
fileStream: fs.WriteStream | null = null; fileStream: fs.WriteStream | null = null;
remainingBytes = 0; remainingBytes = 0;
@ -53,10 +55,11 @@ class TarEntry {
this.uid = parseInt(header.toString('ascii', 108, 116).trim(), 8); this.uid = parseInt(header.toString('ascii', 108, 116).trim(), 8);
this.gid = parseInt(header.toString('ascii', 116, 124).trim(), 8); this.gid = parseInt(header.toString('ascii', 116, 124).trim(), 8);
this.prefix = header.toString('utf8', 345, 500).replace(/\0/g, '');
} }
async writeToDisk(outputPath: (path: string) => string) { async writeToDisk(outputPath: (path: string) => string) {
const fullPath = outputPath(this.name); const fullPath = outputPath(this.prefix ? join(this.prefix, this.name) : this.name);
switch (this.type) { switch (this.type) {
case TarType.DIRTYPE: case TarType.DIRTYPE:
await fs.promises.mkdir(fullPath, { recursive: true, mode: 0o755 }); await fs.promises.mkdir(fullPath, { recursive: true, mode: 0o755 });

View file

@ -36,85 +36,107 @@ test('tar extractor', async () => {
expect(await readFile(test.info().outputPath('tar-example/symlink'), { encoding: 'utf-8' })).toEqual('foo-content'); expect(await readFile(test.info().outputPath('tar-example/symlink'), { encoding: 'utf-8' })).toEqual('foo-content');
}); });
test('extract browser', async () => { test.describe('browser downloads', () => {
// not run by default because it's not hermetic. i'll remove this once we use the TAR extractor in our code. // not run by default because they're not hermetic. i'll remove them once we use the TAR extractor in our code.
test.skip(process.env.TEST_TAR_BROWSER !== '1'); test.skip(process.env.TEST_TAR_BROWSER !== '1');
const response = await fetch('https://playwright.azureedge.net/download-for-internal-testing/playwright/builds/chromium/1152/chromium-headless-shell-linux-arm64.tar.br'); test('chromium-headless-shell', async () => {
const input = Readable.fromWeb(response.body as any); const response = await fetch('https://playwright.azureedge.net/download-for-internal-testing/playwright/builds/chromium/1152/chromium-headless-shell-linux-arm64.tar.br');
const decompressor = createBrotliDecompress(); const input = Readable.fromWeb(response.body as any);
const extractor = new TarExtractor(name => test.info().outputPath(name)); const decompressor = createBrotliDecompress();
await finished(input.pipe(decompressor).pipe(extractor)); const extractor = new TarExtractor(name => test.info().outputPath(name));
await finished(input.pipe(decompressor).pipe(extractor));
expect(await readdir(test.info().outputPath('chrome-linux'))).toEqual([ expect(await readdir(test.info().outputPath('chrome-linux'))).toEqual([
'headless_command_resources.pak', 'headless_command_resources.pak',
'headless_lib_data.pak', 'headless_lib_data.pak',
'headless_lib_strings.pak', 'headless_lib_strings.pak',
'headless_shell', 'headless_shell',
'hyphen-data', 'hyphen-data',
'icudtl.dat', 'icudtl.dat',
'libEGL.so', 'libEGL.so',
'libGLESv2.so', 'libGLESv2.so',
'libvk_swiftshader.so', 'libvk_swiftshader.so',
'libvulkan.so.1', 'libvulkan.so.1',
'v8_context_snapshot.bin', 'v8_context_snapshot.bin',
'vk_swiftshader_icd.json', 'vk_swiftshader_icd.json',
]); ]);
expect(await readFile(test.info().outputPath('chrome-linux/vk_swiftshader_icd.json'), { encoding: 'utf-8' })).toEqual(`{"file_format_version": "1.0.0", "ICD": {"library_path": "./libvk_swiftshader.so", "api_version": "1.0.5"}}`); expect(await readFile(test.info().outputPath('chrome-linux/vk_swiftshader_icd.json'), { encoding: 'utf-8' })).toEqual(`{"file_format_version": "1.0.0", "ICD": {"library_path": "./libvk_swiftshader.so", "api_version": "1.0.5"}}`);
expect(await readdir(test.info().outputPath('chrome-linux/hyphen-data'))).toEqual([ expect(await readdir(test.info().outputPath('chrome-linux/hyphen-data'))).toEqual([
'hyph-af.hyb', 'hyph-af.hyb',
'hyph-as.hyb', 'hyph-as.hyb',
'hyph-be.hyb', 'hyph-be.hyb',
'hyph-bg.hyb', 'hyph-bg.hyb',
'hyph-bn.hyb', 'hyph-bn.hyb',
'hyph-cs.hyb', 'hyph-cs.hyb',
'hyph-cu.hyb', 'hyph-cu.hyb',
'hyph-cy.hyb', 'hyph-cy.hyb',
'hyph-da.hyb', 'hyph-da.hyb',
'hyph-de-1901.hyb', 'hyph-de-1901.hyb',
'hyph-de-1996.hyb', 'hyph-de-1996.hyb',
'hyph-de-ch-1901.hyb', 'hyph-de-ch-1901.hyb',
'hyph-el.hyb', 'hyph-el.hyb',
'hyph-en-gb.hyb', 'hyph-en-gb.hyb',
'hyph-en-us.hyb', 'hyph-en-us.hyb',
'hyph-es.hyb', 'hyph-es.hyb',
'hyph-et.hyb', 'hyph-et.hyb',
'hyph-eu.hyb', 'hyph-eu.hyb',
'hyph-fr.hyb', 'hyph-fr.hyb',
'hyph-ga.hyb', 'hyph-ga.hyb',
'hyph-gl.hyb', 'hyph-gl.hyb',
'hyph-gu.hyb', 'hyph-gu.hyb',
'hyph-hi.hyb', 'hyph-hi.hyb',
'hyph-hr.hyb', 'hyph-hr.hyb',
'hyph-hu.hyb', 'hyph-hu.hyb',
'hyph-hy.hyb', 'hyph-hy.hyb',
'hyph-it.hyb', 'hyph-it.hyb',
'hyph-ka.hyb', 'hyph-ka.hyb',
'hyph-kn.hyb', 'hyph-kn.hyb',
'hyph-la.hyb', 'hyph-la.hyb',
'hyph-lt.hyb', 'hyph-lt.hyb',
'hyph-lv.hyb', 'hyph-lv.hyb',
'hyph-ml.hyb', 'hyph-ml.hyb',
'hyph-mn-cyrl.hyb', 'hyph-mn-cyrl.hyb',
'hyph-mr.hyb', 'hyph-mr.hyb',
'hyph-mul-ethi.hyb', 'hyph-mul-ethi.hyb',
'hyph-nb.hyb', 'hyph-nb.hyb',
'hyph-nl.hyb', 'hyph-nl.hyb',
'hyph-nn.hyb', 'hyph-nn.hyb',
'hyph-or.hyb', 'hyph-or.hyb',
'hyph-pa.hyb', 'hyph-pa.hyb',
'hyph-pt.hyb', 'hyph-pt.hyb',
'hyph-ru.hyb', 'hyph-ru.hyb',
'hyph-sk.hyb', 'hyph-sk.hyb',
'hyph-sl.hyb', 'hyph-sl.hyb',
'hyph-sq.hyb', 'hyph-sq.hyb',
'hyph-sv.hyb', 'hyph-sv.hyb',
'hyph-ta.hyb', 'hyph-ta.hyb',
'hyph-te.hyb', 'hyph-te.hyb',
'hyph-tk.hyb', 'hyph-tk.hyb',
'hyph-uk.hyb', 'hyph-uk.hyb',
'hyph-und-ethi.hyb', 'hyph-und-ethi.hyb',
'manifest.json', 'manifest.json',
]); ]);
});
test('chromium-mac-arm64', async () => {
const response = await fetch('https://playwright.azureedge.net/download-for-internal-testing/playwright/builds/chromium/1152/chromium-mac-arm64.tar.br');
const input = Readable.fromWeb(response.body as any);
const decompressor = createBrotliDecompress();
const extractor = new TarExtractor(name => test.info().outputPath(name));
await finished(input.pipe(decompressor).pipe(extractor));
expect(await readdir(test.info().outputPath('chrome-mac'))).toEqual(['Chromium.app']);
expect(await readdir(test.info().outputPath('chrome-mac/Chromium.app'))).toEqual(['Contents']);
expect(await readdir(test.info().outputPath('chrome-mac/Chromium.app/Contents'))).toEqual([
'Frameworks',
'Info.plist',
'MacOS',
'PkgInfo',
'Resources',
]);
expect(await readFile(test.info().outputPath('chrome-mac/Chromium.app/Contents/Info.plist'), { encoding: 'utf-8' })).toHaveLength(10903);
});
}); });