Commit Graph

5 Commits

Author SHA1 Message Date
Zoltan Kochan
35d5318ed7 fix: resolve relative path params in global add against CWD (#10848)
* fix: resolve relative path params in global add against CWD

When running `pnpm -g add .`, the "." was resolved relative to the
temporary install directory instead of the user's working directory.
This happened because handleGlobalAdd switches opts.dir to a fresh
temp directory before the dependency selectors are resolved.

Now relative path params (., ./foo, ../bar, file:./foo, link:../bar)
are resolved to absolute paths before the directory is switched.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve relative local selectors against opts.dir instead of process.cwd()

This fixes `pnpm -C <dir> -g add .` where the relative selector would
incorrectly resolve against process.cwd() instead of the user's intended
directory. Also adds test coverage for file: and link: prefixed selectors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(config): stop overwriting dir to globalPkgDir for global commands

Previously, `pnpmConfig.dir` was set to `globalPkgDir` when `--global`
was used. This caused `opts.dir` to point to the global packages
directory instead of the user's CWD, breaking `pnpm -g add .` because
relative paths resolved against the wrong directory.

Now `pnpmConfig.dir` is always set to the user's CWD. Global command
handlers already use `opts.globalPkgDir` where they need the global
packages directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use globalPkgDir in pnpm root -g handler

The root command handler was using opts.dir which no longer points to
the global packages directory. Use opts.globalPkgDir instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:52:53 +01:00
Zoltan Kochan
00e7787097 feat: allow global install to override bins owned by the new package (#10828)
* feat: allow global install to override bins owned by the new package

When a package name matches the bin name (e.g., `npm` package providing
`npm` bin), the new package gets priority and can override an existing
bin from another global package. The `npx` bin is also treated as owned
by the `npm` package via a hardcoded override map.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: run benchmarks on node.js 25

* feat: skip linking bins owned by existing global packages instead of failing

When installing a package globally (e.g. node) whose bins conflict with
an already-installed package that owns those bins (e.g. npm owns npm/npx),
the install now succeeds and skips linking the conflicting bins rather
than aborting with GLOBAL_BIN_CONFLICT.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: improve global bin conflict checks for aliased packages and multi-provider bins

Track all new bin providers (not just the last one) so ownership is
correctly resolved when multiple new packages provide the same bin.
Use manifest.name instead of the dependency alias when checking
existing package ownership, fixing incorrect decisions for aliased
installs. Use symlink-dir in tests for Windows compatibility and
remove a non-null assertion in link-bins.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use Set for conflicting bins lookup and fix error hint to use alias

Convert the conflicting bins collection from an array to a Set for O(1)
lookups. Use the dependency alias in the `pnpm remove -g` hint since
that is what the user originally installed with, showing both alias and
manifest name when they differ.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: remove changeset

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 15:42:04 +01:00
Zoltan Kochan
b07c371047 fix: remove not needed tsconfig.json 2026-03-02 23:20:04 +01:00
Zoltan Kochan
4793a9380a ci: run benchmarks on node.js 25 2026-03-02 17:10:46 +01:00
Zoltan Kochan
fd511e4676 feat: isolated global packages (#10697)
**TLDR:** Global packages in pnpm v10 are annoying and slow because they all are installed to a single global package. Instead, we will now use a system that is similar to the one used by "pnpm dlx" (aka "pnpx").

Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own `package.json`, `node_modules`, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts or version resolution shifts.

## Changes

- Add `@pnpm/global-packages` shared utilities package for scanning, hashing, and managing isolated global installs
- `pnpm add -g` creates isolated installs in `{pnpmHomeDir}/global/v11/{hash}/`
- `pnpm remove -g` removes the entire installation group containing the package
- `pnpm update -g` re-installs into new isolated directories and swaps symlinks
- `pnpm list -g` scans isolated directories to show installed global packages
- `pnpm outdated -g` checks each isolated installation for outdated dependencies
- `pnpm store prune` cleans up orphaned global installation directories

## Breaking changes

- `pnpm install -g` (no args) is no longer supported — use `pnpm add -g <pkg>`
- `pnpm link <pkg-name>` no longer resolves packages from the global store — only relative or absolute paths are accepted
- `pnpm link --global` is removed — use `pnpm add -g .` to register a local package's bins globally
2026-03-01 15:49:18 +01:00