Skip to content

fix(link-bins): apply bin ownership overrides in conflict resolution#10975

Merged
zkochan merged 9 commits into
pnpm:mainfrom
nyxsky404:fix/link-bins-owner-overrides
Mar 22, 2026
Merged

fix(link-bins): apply bin ownership overrides in conflict resolution#10975
zkochan merged 9 commits into
pnpm:mainfrom
nyxsky404:fix/link-bins-owner-overrides

Conversation

@nyxsky404

Copy link
Copy Markdown
Contributor

Problem

checkGlobalBinConflicts has a BIN_OWNER_OVERRIDES map that recognizes certain bins as logically owned by a specific package even when the bin name doesn't match the package name (e.g., npx is owned by npm). This is used during global installs to decide whether a new package is allowed to override an existing bin.

However, the link-bins conflict resolution (compareCommandsInConflict in pkg-manager/link-bins/src/index.ts) only checks ownName (cmd.name === manifest.name). It has no awareness of these ownership overrides. This means that in a non-global install, if multiple packages provide the same bin (e.g., npx), the override owner (npm) doesn't get priority — the conflict falls through to alphabetical package name comparison.

Solution

Apply the same ownership override rules in link-bins' compareCommandsInConflict so that conflict resolution is consistent between global conflict checking and actual bin linking.

Changes

  • Added BIN_OWNER_OVERRIDES constant to link-bins/src/index.ts (same as in checkGlobalBinConflicts)
  • Added pkgOwnsBin() function
  • Updated compareCommandsInConflict() to check ownership overrides first

Test

Added test to verify npm gets priority for npx bin when multiple packages provide it.

Closes #10850

BIN_OWNER_OVERRIDES was only used in checkGlobalBinConflicts for global
installs. This change applies the same ownership rules in
compareCommandsInConflict so that conflict resolution is consistent
between global conflict checking and actual bin linking.

This ensures packages like npm get priority for bins like npx even in
non-global installs.

Closes pnpm#10850
Copilot AI review requested due to automatic review settings March 15, 2026 17:29
@nyxsky404 nyxsky404 requested a review from zkochan as a code owner March 15, 2026 17:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aligns @pnpm/link-bins bin-conflict resolution with global install conflict logic by recognizing “bin ownership overrides” (e.g., treating npx as owned by npm) so the intended owner package wins conflicts consistently across install modes.

Changes:

  • Added BIN_OWNER_OVERRIDES + pkgOwnsBin() to link-bins and used them in compareCommandsInConflict().
  • Updated conflict resolution ordering to prioritize override owners before the existing ownName/name/version tie-breakers.
  • Added a test intended to verify npm wins the npx bin conflict.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
pkg-manager/link-bins/src/index.ts Adds ownership-override awareness to bin conflict resolution.
pkg-manager/link-bins/test/index.ts Adds a regression test for npx being owned by npm.
.changeset/apply-bin-owner-overrides-link-bins.md Declares a minor release for the behavior change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread bins/linker/test/index.ts Outdated
@zkochan

zkochan commented Mar 15, 2026

Copy link
Copy Markdown
Member

sounds good but don't duplicate code.

Move shared logic to avoid code duplication between link-bins
and checkGlobalBinConflicts.
@nyxsky404

Copy link
Copy Markdown
Contributor Author

I've refactored the code to extract BIN_OWNER_OVERRIDES and pkgOwnsBin to @pnpm/package-bins. Both link-bins and checkGlobalBinConflicts now import from the shared package.

Comment thread pkg-manager/link-bins/src/index.ts Outdated
Comment on lines 179 to 180
if (a.ownName && !b.ownName) return 1
if (!a.ownName && b.ownName) return -1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

shouldn't this now just be removed? this check is already handled by pkgOwnsBin. The ownName field can probably be removed to.

Or alternatively, assign ownName the value returned by pkgOwnsBin. That way it will be cached.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done! Removed the redundant ownName field and checks since pkgOwnsBin already covers that case. Skipped caching as the performance gain would be negligible.

nyxsky404 and others added 5 commits March 17, 2026 12:23
pkgOwnsBin already handles the binName === pkgName case, making
the ownName field and its associated checks redundant.
Package renames on main:
- @pnpm/package-bins -> @pnpm/bins.resolver
- @pnpm/link-bins -> @pnpm/bins.linker
- pkg-manager/link-bins -> bins/linker
- pkg-manager/package-bins -> bins/resolver

Updated imports, changeset package names, and moved test fixture
to new location.
Added BIN_OWNER_OVERRIDES and pkgOwnsBin to @pnpm/bins.resolver for improved conflict resolution in bin linking.
Move fixture packages to the directory root instead of nesting them
inside node_modules, avoiding committing node_modules to the repo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zkochan zkochan enabled auto-merge (squash) March 22, 2026 10:57
@zkochan zkochan merged commit 449dacf into pnpm:main Mar 22, 2026
8 checks passed
@welcome

welcome Bot commented Mar 22, 2026

Copy link
Copy Markdown

Congrats on merging your first pull request! 🎉🎉🎉

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.

link-bins: apply bin ownership overrides in conflict resolution

3 participants