Skip to content

fix: shim non-existent source #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

trappar
Copy link

@trappar trappar commented Feb 25, 2023

PNPM has this long-standing issue where pnpm install fails when a package defines a bin that must be compiled first: pnpm/pnpm#1801

In this case the file can't be read and so a shebang can't be determined, and execution fails with error code ENOENT. This seems easily solvable. cmd-shim can still fall back to determining the program by using the extensionToProgramMap.

This PR is probably incomplete. Not being terribly familiar with the code, I've done my best, but the test is probably incomplete at the very least.

@zkochan
Copy link
Member

zkochan commented Mar 15, 2023

I guess we can use this approach.

@trappar trappar force-pushed the fix-shim-missing-src branch from 8855d40 to eff515f Compare April 2, 2023 06:17
@trappar
Copy link
Author

trappar commented Apr 2, 2023

I've rebased the PR on the recent changes to main. Not sure what's going on with the broken tests. Seems like the checks run on Windows, so I tried running it locally. I've run it on Windows 11 with both Node 14 and 18 and all tests pass for me. Any chance you might be willing to help push this across the finish line? Probably a lot easier for you given that you're more familiar with the code 😅

Currently I'm working around this by adding the following to my monorepo's root package.json

"scripts": {
  "pnpm:devPreinstall": "scripts/createBinStubs"
},

Which runs this script:

#!/usr/bin/env node
const { writeFileSync, mkdirSync, existsSync } = require("fs");
const { dirname } = require("path");

const shims = [
  "packages/[redacted]/dist/index.js",
];

const fileContent = `/*
 * Temp file generated by scripts/createBinStubs.js
 * This file is created as a temporary workaround for this issue: https://github.com/pnpm/pnpm/issues/1801
 * Currently PNPM fails to create a bin while installing sub-packages when the source for that bin is missing while running pnpm install.
 * This is the case for any package with a bin that is built after install. By creating this temporary file, PNPM is able to link to it.
 * Once the actual bin is built, everything works.
*/`;

shims.forEach((shim) => {
  const shimDir = dirname(shim);
  if (!existsSync(shimDir)) {
    mkdirSync(shimDir, { recursive: true });
  }
  if (!existsSync(shim)) {
    writeFileSync(shim, fileContent);
  }
});

I'd love to remove this hacky workaround from my code!

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request addresses a PNPM issue where installations fail if a package’s bin file does not exist and cannot provide a shebang, by falling back on the extensionToProgramMap.

  • Added a new test case for the scenario when the source file is missing.
  • Modified the searchScriptRuntime function to handle ENOENT errors on Windows by checking for an alternative executable extension.

Reviewed Changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.

File Description
test/test.js Added a "no src file" test to cover the fallback behavior when the source file is missing.
src/index.ts Refactored the shebang extraction and error handling logic to support the new fallback scenario.
Files not reviewed (1)
  • test/snapshots/test.js.snap: Language not supported
Comments suppressed due to low confidence (2)

test/test.js:22

  • Consider adding explicit assertions within the 'no src file' test case to verify that cmdShim correctly falls back to using the extensionToProgramMap when the source file is missing.
describe('no src file', () => {

src/index.ts:274

  • Ensure that the fallback behavior when encountering an ENOENT error on Windows is fully intended – specifically, verify that relying on fs_.stat to check for an executable version aligns with the overall design, and consider adding a clarifying comment if needed.
if (isWindows() && err.code === 'ENOENT') {

Comment on lines +274 to +282
if (isWindows() && err.code === 'ENOENT') {
if (await opts.fs_.stat(`${target}${getExeExtension()}`)) {
return {
program: null,
additionalArgs: '',
}
}
}
if (err.code !== 'ENOENT') throw err

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The operation to compare err.code to ENOENT could be executed twice on Windows. You can optimize it by moving if (err.code !== 'ENOENT') throw err up to right under catch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants