diff --git a/packages/playground/blueprints/src/lib/v1/resources.spec.ts b/packages/playground/blueprints/src/lib/v1/resources.spec.ts index d892699957..19772fd3a8 100644 --- a/packages/playground/blueprints/src/lib/v1/resources.spec.ts +++ b/packages/playground/blueprints/src/lib/v1/resources.spec.ts @@ -55,9 +55,6 @@ describe('GitDirectoryResource', () => { it('defaults to the repo root when path is omitted', async () => { const url = 'https://github.com/WordPress/wordpress-playground'; - const fallbackName = url - .replaceAll(/[^a-zA-Z0-9-.]/g, '-') - .replaceAll(/-+/g, '-'); const resource = new GitDirectoryResource({ resource: 'git:directory', url, @@ -67,11 +64,53 @@ describe('GitDirectoryResource', () => { }); const { files, name } = await resource.resolve(); - expect(name).toBe(fallbackName); - expect(resource.name).toBe('.github'); + // Human-readable name + expect(resource.name).toBe( + 'https://github.com/WordPress/wordpress-playground (trunk) at .github' + ); + + // Filename + expect(name).toBe( + 'https-github.com-WordPress-wordpress-playground-trunk-at-.github' + ); expect(files['dependabot.yml']).toBeInstanceOf(Uint8Array); }); }); + + describe('name', () => { + it('should return a non-empty name when path is omitted', async () => { + const resource = new GitDirectoryResource({ + resource: 'git:directory', + url: 'https://github.com/WordPress/link-manager', + ref: 'trunk', + }); + const { name } = await resource.resolve(); + expect(name).toBe('https-github.com-WordPress-link-manager-trunk'); + }); + + it('should return a non-empty name when path is empty', async () => { + const resource = new GitDirectoryResource({ + resource: 'git:directory', + url: 'https://github.com/WordPress/link-manager', + ref: 'trunk', + path: '', + }); + const { name } = await resource.resolve(); + expect(name).toBe('https-github.com-WordPress-link-manager-trunk'); + }); + + it('should return a non-empty name when path has no letters', async () => { + const resource = new GitDirectoryResource({ + resource: 'git:directory', + url: 'https://github.com/WordPress/link-manager', + ref: 'trunk', + // A path with only a few files to avoid timing out. + path: '/', + }); + const { name } = await resource.resolve(); + expect(name).toBe('https-github.com-WordPress-link-manager-trunk'); + }); + }); }); describe('BlueprintResource', () => { diff --git a/packages/playground/blueprints/src/lib/v1/resources.ts b/packages/playground/blueprints/src/lib/v1/resources.ts index 17e9df4c63..c9ce9a1d66 100644 --- a/packages/playground/blueprints/src/lib/v1/resources.ts +++ b/packages/playground/blueprints/src/lib/v1/resources.ts @@ -5,7 +5,7 @@ import { } from '@php-wasm/progress'; import type { FileTree, UniversalPHP } from '@php-wasm/universal'; import type { Semaphore } from '@php-wasm/util'; -import { dirname } from '@php-wasm/util'; +import { randomFilename } from '@php-wasm/util'; import { listDescendantFiles, listGitFiles, @@ -586,24 +586,35 @@ export class GitDirectoryResource extends Resource { name.substring(requestedPath.length).replace(/^\/+/, '') ); return { - name: - dirname(this.reference.path || '') || - this.reference.url - .replaceAll(/[^a-zA-Z0-9-.]/g, '-') - .replaceAll(/-+/g, '-'), + name: this.filename, files, }; } + /** + * Generate a nice, non-empty filename – the installPlugin step depends on it. + */ + get filename() { + return ( + this.name + .replaceAll(/[^a-zA-Z0-9-.]/g, '-') + .replaceAll(/-+/g, '-') + .replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, '') || + randomFilename() + ); + } + /** @inheritDoc */ get name() { - const path = this.reference.path ?? ''; - if (!path) { - return this.reference.url - .replaceAll(/[^a-zA-Z0-9-.]/g, '-') - .replaceAll(/-+/g, '-'); - } - return path.split('/').pop() || ''; + return [ + this.reference.url, + this.reference.ref ? `(${this.reference.ref})` : '', + this.reference.path?.replace(/^\/+/, '') + ? `at ${this.reference.path}` + : '', + ] + .filter((segment) => segment.length > 0) + .join(' '); } }