Skip to content

Commit

Permalink
Fix a cross-device mv error by using a tmp directory inside document …
Browse files Browse the repository at this point in the history
…root (#886)

Solves the [error discovered by
@sejas](WordPress/playground-tools#116 (comment))
caused by calling `php.mv(fromPath, toPath)` when `fromPath` is a
mounted local directory and `toPath` is a MEMFS directory. Emscripten
doesn't support such a scenario:

```
Proceeding without the Notification plugin. Could not install it in wp-admin. The original error was: Error: Could not move "/tmp/assets/Notification/notification": Cross-device link.
Error: Could not move "/tmp/assets/Notification/notification": Cross-device link.
    at descriptor.value (/playground-tools/node_modules/@php-wasm/node/index.cjs:67481:17)
```

The solution proposed in this PR replaces a `/tmp` directory with a
randomly-named temporary directory inside `wp-content`. `/tmp` doesn't
necessarily point to a system temp directory and needs to be revisited
anyway. Whether we should use a temporary directory inside `wp-content`
is another matter, but that part may be revisited once the [recursive
cp](#846) feature
is added.
  • Loading branch information
adamziel authored Dec 20, 2023
1 parent 8f8d6b3 commit f5082bf
Showing 1 changed file with 12 additions and 15 deletions.
27 changes: 12 additions & 15 deletions packages/playground/blueprints/src/lib/steps/install-asset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { UniversalPHP } from '@php-wasm/universal';
import { joinPaths } from '@php-wasm/util';
import { writeFile } from './write-file';
import { unzip } from './unzip';

Expand Down Expand Up @@ -29,30 +30,26 @@ export async function installAsset(
assetFolderName: string;
}> {
// Extract to temporary folder so we can find asset folder name

const zipFileName = zipFile.name;
const assetNameGuess = zipFileName.replace(/\.zip$/, '');

const tmpUnzippedFilesPath = `/tmp/assets/${assetNameGuess}`;
const tmpZipPath = `/tmp/${zipFileName}`;
const wpContent = joinPaths(await playground.documentRoot, 'wp-content');
const tmpDir = joinPaths(wpContent, crypto.randomUUID());
const tmpZipPath = joinPaths(tmpDir, zipFileName);
const tmpUnzippedFilesPath = joinPaths(tmpDir, 'assets', assetNameGuess);

const removeTmpFolder = () =>
playground.rmdir(tmpUnzippedFilesPath, {
if (await playground.fileExists(tmpUnzippedFilesPath)) {
await playground.rmdir(tmpDir, {
recursive: true,
});

if (await playground.fileExists(tmpUnzippedFilesPath)) {
await removeTmpFolder();
}
await playground.mkdir(tmpDir);

await writeFile(playground, {
path: tmpZipPath,
data: zipFile,
});

const cleanup = () =>
Promise.all([removeTmpFolder, () => playground.unlink(tmpZipPath)]);

try {
await unzip(playground, {
zipPath: tmpZipPath,
Expand Down Expand Up @@ -84,14 +81,14 @@ export async function installAsset(
// Move asset folder to target path
const assetFolderPath = `${targetPath}/${assetFolderName}`;
await playground.mv(tmpAssetPath, assetFolderPath);
await cleanup();

return {
assetFolderPath,
assetFolderName,
};
} catch (error) {
await cleanup();
throw error;
} finally {
await playground.rmdir(tmpDir, {
recursive: true,
});
}
}

0 comments on commit f5082bf

Please sign in to comment.