Commit Graph
6 Commits
Author SHA1 Message Date
Chengwen Zhang fb2759e2b8 fix(exec): set PWD to the directory the command runs in (#15487)
In a workspace reached through a symlinked directory, `pnpm -r exec pwd`
printed the resolved physical path instead of the logical path
(Closes pnpm/pnpm#1550).

The spawn cwd already is the logical project path. What leaks the physical
path is the inherited PWD environment variable: it still points at pnpm's own
cwd, disagrees with the child's actual cwd, and shells that trust PWD fall
back to the physical working directory. Set PWD to the directory the command
runs in (unix only). pacquet's command_in_dir gets the same override so both
implementations agree.

External binaries that print the physical directory by default (e.g.
coreutils pwd without -L) are unaffected by any package manager and out of
scope.
2026-09-25 02:09:06 +02:00
AltayandZoltan Kochan 30e3a83ed4 fix(exec): set package-manager environment variables (#15282)
Share lifecycle package-manager environment construction with exec and dlx
in both implementations. Child tools receive the invoking pnpm path, Node
path and initial working directory, matching npm exec.

Closes pnpm/pnpm#7037.

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-09-22 23:05:23 +02:00
Zoltan KochanandClaude Fable 5.1 00edab91b1 fix(exec): find the project's bins when run from a subdirectory (#15120)
* fix(exec): find the project's bins when run from a subdirectory

`pnpm exec` and the `pnpm <command>` fallback keep the caller's cwd since
pnpm/pnpm#10445, but the only PATH entry pointing at the project,
`./node_modules/.bin`, is relative and resolved against that subdirectory,
so executables installed in the project were no longer found. The
project's `node_modules/.bin` is now added as an absolute entry when the
run directory differs from the project directory, and `PNPM_PACKAGE_NAME`,
`.pnp.cjs`, and the package map are read from the project instead of the
cwd. This matches the Rust CLI, whose `ExecDirs` already separates the run
directory from the project directory.

Closes pnpm/pnpm#5068

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(exec): add the project's bin dir to PATH relative to the run dir

An absolute entry is rejected by makeEnv when the project path contains
the PATH delimiter, which the existing "directory with path delimiter"
test guards against for the relative `./node_modules/.bin` entry. The
subdirectory test now runs in such a project. The changeset states each
behavior in its own sentence.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(exec): cover the PnP lookup from a subdirectory

The subdirectory test now asserts that `.pnp.cjs` is found in the project,
not the cwd. The comment above the project-dir decision keeps only the
reasons the code cannot carry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-19 14:05:53 +00:00
Zoltan Kochan 7a1b7b14da feat(run): persist recursive task state (#14258)
Persist passed recursive tasks incrementally in a versioned journal under the workspace's node_modules directory. Hash the invocation's task graph, script commands, arguments, environment, and execution settings so only compatible state is reused.

Use unique per-run journals, cross-process serialization around the atomically published latest-run pointer, open file handles, and newline-committed records to reject stale, superseded, malformed, torn, or unsafe state. Remove each journal after its invocation succeeds and preserve the existing dependency-pruning fallback when no compatible state is available.

Implement the same state format and resume semantics in the TypeScript CLI and Rust pnpm port, with shared identity fixtures guarding cross-implementation compatibility.

Related to pnpm/pnpm#14211.
2026-08-28 05:06:43 +02:00
Zoltan Kochan e7f3bccfff feat: workspace task orchestration (#14209)
Replace the chunked topological scheduler of recursive run/exec with
per-task scheduling in both stacks: a task — a (project, script) pair —
becomes runnable when every task it depends on has completed
successfully, and runnable tasks are dispatched under the
workspace-concurrency limit with no barrier between
dependency-independent tasks.

A new "tasks" section in pnpm-workspace.yaml declares task dependencies
with the caret convention ("^build" = the task in each workspace
dependency, "build" = the task in the same project). A task with no
entry behaves as depending on its own name in the workspace
dependencies, which is exactly what chunking implied. A project without
the script becomes a pass-through node that is reported skipped and
keeps the chain intact.

Also per the RFC: task-graph cycles are ERR_PNPM_TASK_CYCLE naming the
participating tasks, scoped to the invocation's selected graph, with
ignoreWorkspaceCycles: true downgrading the error to a warning;
--resume-from excludes exactly the anchor's transitive dependencies;
--reverse runs the reverse graph; under --no-bail dependents of a
failed task are reported skipped and do not add to the exit code; with
--bail, the first failure ends the run at once and nothing new is
dispatched; output is inherited only when at most one script can ever
be in flight; and pnpm -r run --dry-run [--json] prints the resolved
task graph without running anything (the verify-deps check included).

Implementation: the projects sorter exposes the tunneled dependency-edge
map (filteredProjectsDependencies / filtered_projects_dependencies)
instead of only its flattened chunks; the recursive summary is
task-keyed (dependsOn-pulled tasks get "<dir>#<task>" keys); pacquet's
inert --sequential now means concurrency 1 and its --no-sort
resume/reverse handling is aligned with the TypeScript CLI; the dead
chunk helpers are removed.

Related to https://github.com/pnpm/rfcs/pull/23
2026-08-27 02:41:03 +02:00
Zoltan Kochan fc2f33912e refactor: move the TypeScript pnpm CLI into a pnpm11/ directory (#12537)
The TypeScript pnpm CLI freezes at v11; pnpm 12 will be the Rust pacquet
port. To make that split legible, all TypeScript source, test, and build
directories move under a new top-level pnpm11/ directory. The name states
the version boundary rather than implying a behavioral fork, since the two
stacks are meant to behave identically.

Scope is source-only: the shared workspace root stays at the repo root.
pnpm-workspace.yaml, package.json, pnpm-lock.yaml, .pnpmfile.cjs,
.meta-updater, __patches__, .changeset, .husky, and the lint/spell configs
remain in place, so one pnpm workspace and one Cargo workspace still span
all three products. pnpr/client and pacquet/tasks/registry-mock stay as
cross-product workspace members.

Rewiring the move required:
- pnpm-workspace.yaml globs prefixed with pnpm11/
- root package.json script paths, eslint.config.mjs, tsconfig.lint.json,
  .gitignore, and CODEOWNERS updated
- .meta-updater/src/index.ts literals repointed (pnpm11/pnpm/package.json,
  pnpm11/__utils__, pnpm11/__typings__, and the main package directory)
- regenerated every moved package's repository/homepage URL via meta-updater
- pnpm11/pnpm/bundle-deps.ts and __utils__/scripts/src/typecheck-only.ts
  climb one more level to reach the repo root

.meta-updater stays at the repo root because @pnpm/meta-updater resolves
its config at <cwd>/.meta-updater/main.mjs.

TS CI (.github/workflows/ci.yml) now only runs when pnpm11/-relevant paths
change, via a dorny/paths-filter changes job plus a TS CI / Success
aggregate gate; branch protection should require only that gate.
2026-06-20 14:36:25 +02:00