WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.46k stars 4.18k forks source link

symlink error Skipping "./index.js" listed in ".../block.json". File is located outside of the "src" directory. #44937

Closed mastermind-0xff closed 1 year ago

mastermind-0xff commented 2 years ago

Hi guys!

When trying to build multiple blocks I got the following error:

Skipping "./index.js" listed in "C:/_projects/web/wp6/www/wp-content/themes/*****/blocks_src/src/block-a/block.json". File is located outside of the "src" directory.

Some investigation led to "...\@wordpress\scripts\utils\config.js" line 256:

if ( ! filepath.startsWith( srcDirectory ) ) {
console.log(filepath);
console.log(srcDirectory);
C:\_projects\web\wp6\www\wp-content\themes\*****\blocks_src\src\block-a\index.js
d:\_projects\web\wp6\www\wp-content\themes\*****\blocks_src\src\

and "...\@wordpress\scripts\utils\package.js" line 12:

const { packageJson, path: pkgPath } = readPkgUp( {
    cwd: realpathSync( getCurrentWorkingDirectory() ),
} );

As a result filepath is the symlink path while the srcDirectory is the resolved path.

Not sure what the reason for realpathSync ussage is, but I guess it should be investigated.

Hope this saves someone's time. Cheers, Tony

t-hamano commented 1 year ago

Thank you for submitting the issue. To help us resolve this issue, could you please share the following points?

mastermind-0xff commented 1 year ago

Steps to reproduce

  1. d:\_projects is symlink for c:\_projects. d:\_project\node\test-wp-block\ is the project path in the IDE;
  2. "npx @wordpress/create-block block-a";
  3. Move all files from d:\_projects\node\test-wp-block\block-a to d:\_projects\node\test-wp-block\;
  4. Move d:\_projects\node\test-wp-block\src* to d:\_projects\node\test-wp-block\src\block-a;
  5. Copy and paste d:_projects\node\test-wp-block\block-a to d:\_projects\node\test-wp-block\block-b so you have two blocks;
  6. "npm run build" from d:\ (the symlink path) produces no blocks, but only "block.json" files. image

    • If the same project is opened from the real path (c:\_projects\node\test-wp-block\ ), there are no issues. image
t-hamano commented 1 year ago

Thanks for providing more information. I was able to reproduce the problem, so I will first describe the steps to reproduce it.

How to reproduce on Windows

  1. Move to the path to test in your environment.
  2. Create A block boilerplate: npx @wordpress/create-block test-block
  3. Create symlink: mklink /d test-block-symlink test-block
  4. Move to the symlink directory: cd test-block-symlink
  5. Generate two blocks: robocopy /move src src\block-a & xcopy src\block-a\ src\block-b\
  6. Delete build directory once: rmdir /s build
  7. build block: npm run build
  8. Confirm that no files other than the block.json file are generated in the build directory and that warning messages are displayed.
build/
├── block-a/
│   └── block.json
└── block-b/
     └── block.json
Skipping "./index.js" listed in "path/to/test-block-symlink/src/block-a/block.json". File is located outside of the "src" directory.
Skipping "./index.js" listed in "patj/to/test-block-symlink/src/block-b/block.json". File is located outside of the "src" directory.
No entry file discovered in the "src" directory.
t-hamano commented 1 year ago

Then this is the test result on WSL (Ubuntu). This one works correctly.

  1. Move to the path to test in your environment.
  2. Create A block boilerplate: npx @wordpress/create-block test-block
  3. Create symlink: ln -s test-block test-block-symlink
  4. Move to the symlink directory: cd test-block-symlink
  5. Generate two blocks: mkdir src/block-a; mv src/*.js src/*.scss src/*.json src/block-a/; cp -r src/block-a src/block-b
  6. Delete build directory once: rm -rf build
  7. build block: npm run build

Confirm that all files are generated in the build directory correctly without error messages.

t-hamano commented 1 year ago

I have found one clue. The results of fast-glob are different between Windows and Linux.

https://github.com/WordPress/gutenberg/blob/3c9a0207f51d731ff4d8cfbfa69daa16f797639f/packages/scripts/utils/config.js#L207-L214

blockMetadataFiles returns an array of simlink paths on Windows and an array of resolved paths on Linux.

As a result filepath is the symlink path while the srcDirectory is the resolved path. Not sure what the reason for realpathSync ussage is, but I guess it should be investigated.

realpathSync resolves symbolic paths, which I believe is the expected implementation. I think the problem is that the filepath (i.e., the one generated from blockMetadataFiles) is a simlink path.

Once I do, I may need to look into how fast-glob is resolving the shimlinks.

pbiron commented 1 year ago

I encountered this problem when developing plugins on a Windows machine where the plugin code is stored in a "global" directory and symlink'd into a particular WP site.

blockMetadataFiles returns an array of simlink paths on Windows and an array of resolved paths on Linux.

As a result filepath is the symlink path while the srcDirectory is the resolved path. Not sure what the reason for realpathSync ussage is, but I guess it should be investigated.

I can confirm both of the above (using WSL (CentOS7) for the linux testing).

I've looked at the PR in #54212, and have a suggestion for a simpler solution, that seems to work for me (both in Windows and linux), but there may be use cases that it doesn't account for.

in config.js L236-239, adding a realpathSync() call when constructing filepath seems to solve the problem for me. That is, replacing:

const filepath = join(
    dirname( blockMetadataFile ),
    value.replace( 'file:', '' )
);

with:

const filepath = realpathSync( join(
    dirname( blockMetadataFile ),
    value.replace( 'file:', '' )
) );

@t-hamano can you confirm that this simpler solution works for you?

gziolo commented 1 year ago

@pbiron, there is now a refactored version of #54212 that should resolve the same issue by standardizing the way it uses glob calls. Can you confirm it resolves the issue for you? I'd like to land it as soon as I hear back from you.

pbiron commented 1 year ago

@gziolo the latest PR works great for me in Windows, whether I run the scripts from the dir that is symlink'd or the target dir.

thanx!