mhassan1 / yarn-plugin-licenses

Yarn Berry plugin that adds `yarn licenses` commands
42 stars 11 forks source link

missing dependencies with alternate virtual hash #20

Closed felabr closed 2 years ago

felabr commented 2 years ago

First of all, thank you for providing this plugin!

I noticed something odd, but I'm not quite sure if this is a bug, or intended, or just something weird with my project ...

When im running yarn licenses list --json sometimes dependencies are missing from the output. I debugged a bit and found that getPackagePath can't find anything in yarnState and then returns null. https://github.com/mhassan1/yarn-plugin-licenses/blob/d9eb166066d59561da64cf2e2d1c78ab3eb0c0d7/src/linkers/node-modules.ts#L16 This happens when the virtual hash part is different, e.g. I'm looking for

markdown-to-jsx@virtual:61765caf8e0149763d5dc1377f0bc2cdb8e53e430f5b5c7203d4fed5d970d1024c6a32438588c8bbb858277818fea6228f98cccacf945128b03c88a76e21c522#npm:7.1.7

but there's

markdown-to-jsx@virtual:0a1e65485788e9f3d822adc69fdc40378ecd6d6333e3711924b7ac04f243560996ea683005418a4537063f30bb3a1512c32f36f9d25a1f72cababbe104c055e9#npm:7.1.7

in the yarnState instead.

I'm not aware there's anything special with the missing dependencies, there are others right next to them that work just fine.

Assuming the license is the same when scope, name, and version are the same I came up with this little "fix" to ignore the virtual hash part:

  if (!entry) {
    const nameWithScope = locator.scope ? `@${locator.scope}/${locator.name}`: locator.name;
    const version = locator.reference.slice(locator.reference.lastIndexOf(':'));
    const key = Object.keys(yarnState).find(key => key.startsWith(nameWithScope) && key.endsWith(version));
    if (!key) {
      return null;
    }
    entry = yarnState[key];
  }

I have no idea why the virtual parts are different, so I don't know if ignoring them is a good idea or if this can and should be fixed elsewhere.

mhassan1 commented 2 years ago

Thanks for the report. Can you provide a minimal reproduction so I can troubleshoot?

felabr commented 2 years ago

Hi @mhassan1,

I've created this repo here to reproduce the issue: https://github.com/felabr/licenses-test

It's a stripped down version of an actual project, so it's not really minimal, but I noticed that further removing dependencies would change the yarnState too much for it to be much use in debugging this issue.

There are a few console.logs in the plugin-licenses.cjs now, so if you run yarn and yarn licenses list --json you should see something like this:

getPackagePath entry lookup failed...
looking for: @test/icons-core@workspace:packages/icons-core
found these in the yarnState: [
  '@test/icons-core@virtual:4fd27bfb4fef2a97fab07ca81aac379f760b95dba46545439850929e7f52c7df191aa0d8a7aed4961fa96541ea85790cf0c49255bc8f535ea667a8fa6eb80228#workspace:packages/icons-core',
  '@test/icons-core@virtual:9bbb472e31e921f714ad399fa9007c7804e0d0afa32acc3ecaf0bc70926b127392ab25d13eab771ab63de3f2d02e8a99b764276ae4de12587d40200d80e50af9#workspace:packages/icons-core'
]
looking for: babel-loader@virtual:9bbb472e31e921f714ad399fa9007c7804e0d0afa32acc3ecaf0bc70926b127392ab25d13eab771ab63de3f2d02e8a99b764276ae4de12587d40200d80e50af9#npm:8.2.3
found these in the yarnState: [
  'babel-loader@virtual:30932a454d09d1f3ef2fb64c8bbfac83e99058216b8b2c2460da2b461abf94c1d0749b20581bc729782fb3d4e971cc510bd12ce8923c023a5bff638b7d0549ca#npm:8.2.3'
]

(The markdown-to-jsx dependency mentioned above stopped being an issue when I removed stuff from the project.)

Thank you for looking into this.

mhassan1 commented 2 years ago

Thanks for the reproduction. I'm confused about what's missing from the output. I see this:

├─ UNLICENSED
│  ├─ @test/icons-core@workspace:packages/icons-core [4fd27] (via ^63.27.2 [4fd27])
│  ├─ @test/icons-core@workspace:packages/icons-core (via workspace:packages/icons-core)

├─ MIT
│  ├─babel-loader@npm:8.2.3 [9bbb4] (via npm:^8.2.2 [9bbb4])
│  │  ├─ URL: https://github.com/babel/babel-loader.git
│  │  ├─ VendorName: Luis Couto
│  │  └─ VendorUrl: https://github.com/babel/babel-loader

What should I be seeing in the output?

felabr commented 2 years ago

I modified the plugin with some debug code:

  let entry = yarnState[structUtils.stringifyLocator(locator)]
  if (!entry) {
    console.log('getPackagePath entry lookup failed...');
    console.log('looking for:', structUtils.stringifyLocator(locator));
    const nameWithScope = locator.scope ? `@${locator.scope}/${locator.name}`: locator.name;
    const version = locator.reference.slice(locator.reference.lastIndexOf(':'));
    const keysInState = Object.keys(yarnState).filter(key => key.startsWith(nameWithScope) && key.endsWith(version));
    console.log('found these in the yarnState:', keysInState);
    const key = Object.keys(yarnState).find(key => key.startsWith(nameWithScope) && key.endsWith(version));
    console.log('using this one instead:', key);
    if (!key) {
      console.log('nothing found');
      return null;
    }
    entry = yarnState[key];
  }

So there should be some debug output right above the tree or the JSON if the entry cannot be found. If you do not have any debug output there then you are probably not going into that if (!entry) { condition.

mhassan1 commented 2 years ago

I understand the issue. I will put up a PR tomorrow.

mhassan1 commented 2 years ago

This should be resolved in v0.8.1 of the plugin.

felabr commented 2 years ago

Hi @mhassan1 , I can confirm that v0.8.1 solves the issue I reported. Thanks again for looking into this.