pnpm 11.28.3 → 11.28.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,155 @@
1
1
  # pnpm
2
2
 
3
+ ## 11.28.5
4
+
5
+ This release reads cached registry metadata faster and makes `pnpm config get --global` ignore project settings. It also carries several security fixes for package archives, git dependencies, and config dependencies.
6
+
7
+ ### Patch Changes
8
+
9
+ #### Security
10
+
11
+ - pnpm now verifies locked config dependencies against their registry before installing them. Config dependencies must come from an npm registry. The lockfile can no longer replace the integrity of a config dependency pinned with `version+integrity`.
12
+
13
+ - Lockfile verification now checks the tarballs inside a `variations` resolution against the registry. A `name@version` lockfile entry with an empty `variations` resolution is now rejected.
14
+
15
+ - `pnpm audit signatures` now verifies signatures against the integrity recorded in the lockfile. Packages without a recorded integrity cannot pass signature verification.
16
+
17
+ - pnpm now rejects a git dependency whose lockfile repository is empty, begins with `-`, or contains a null byte. Git can no longer read such a value as a command-line option [pnpm/tasks#84](https://github.com/pnpm/tasks/issues/84).
18
+
19
+ - A git dependency with a `#path:` subpath can no longer reach files outside the repository through a symlink in the subpath.
20
+
21
+ - `pnpm pack`, `pnpm publish`, and installs of git and local directory dependencies now leave out files that a directory symlink or a `bundleDependencies` entry points to outside the package directory [pnpm/tasks#83](https://github.com/pnpm/tasks/issues/83) [pnpm/tasks#93](https://github.com/pnpm/tasks/issues/93).
22
+
23
+ - `pnpm deploy` with `deployAllFiles` now rejects symlinks that point outside the package directory. Local package installs with this setting apply the same check.
24
+
25
+ - pnpm no longer hangs on a package archive with a negative PAX record length or an entry of 4 GiB or more [pnpm/tasks#78](https://github.com/pnpm/tasks/issues/78) [pnpm/tasks#79](https://github.com/pnpm/tasks/issues/79).
26
+
27
+ - Large package downloads and large files inside gzip and bzip2 package archives now use bounded memory during installation. Package manifests and archive metadata larger than 64 MiB are rejected. `pnpm publish` also rejects manifests and README files larger than 64 MiB in pre-built tarballs before reading them into memory.
28
+
29
+ - Two URL or local path dependencies no longer share a virtual store directory when one URL has `+`, `#`, `:`, or `?` where the other has `/`. Such dependencies, including git dependencies pinned with `#`, now get a hash suffix on their directory name.
30
+
31
+ - `pnpm licenses` now removes terminal control characters from package metadata in table output.
32
+
33
+ - The warnings about ignored project `.npmrc` registry and auth settings no longer print the username and password of a URL-scoped key such as `//user:password@registry.example.com/:_authToken`.
34
+
35
+ #### Installing and resolving dependencies
36
+
37
+ - Dependency resolution reads cached registry metadata faster. The metadata cache moved to `<cache-dir>/v12/`, so the first install after upgrading downloads registry metadata again. A damaged cache entry is downloaded again, or reported as an error when `--offline` is set [#13512](https://github.com/pnpm/pnpm/pull/13512).
38
+
39
+ - `pnpm install` now fails with `ERR_PNPM_UNSUPPORTED_PROTOCOL` when a dependency uses a specifier with a protocol pnpm does not support, such as Yarn's `patch:`. pnpm linked such a dependency to a directory that does not exist [#16590](https://github.com/pnpm/pnpm/issues/16590).
40
+
41
+ - When a dependency moves an exact dependency of its own to an older version, a peer dependency that pnpm installed automatically now moves with it. Before, `pnpm install` and `pnpm dedupe` kept the newer locked version of the peer, so the lockfile held two copies of it, for example two copies of `vue` [pnpm/tasks#61](https://github.com/pnpm/tasks/issues/61).
42
+
43
+ - `pnpm add` and `pnpm install` now keep the peer dependencies that `pnpm-lock.yaml` records for a package they did not update. A registry whose metadata disagrees with the package's `package.json`, for example by omitting `peerDependenciesMeta`, made `pnpm add` and `pnpm dedupe` write different lockfiles, so `pnpm dedupe --check` failed after `pnpm add` [#16615](https://github.com/pnpm/pnpm/issues/16615).
44
+
45
+ #### Configuration
46
+
47
+ - `pnpm config get` and `pnpm config list` with `--global` or `--location=global` now show only the global configuration. Both flags included the project's `.npmrc` before. `--location=global` also included the project's `pnpm-workspace.yaml`. `pnpm config get --global` failed when the global bin directory was not in PATH [#16598](https://github.com/pnpm/pnpm/issues/16598).
48
+
49
+ - pnpm now prints config warnings, such as an unset environment variable in `.npmrc`, when loading the config fails.
50
+
51
+ - pnpm now fails when `httpProxy` or `httpsProxy` in `pnpm-workspace.yaml` or the global configuration is not a string.
52
+
53
+ - `pnpm dlx` now uses the `release` entry of `nodeDownloadMirrors` from the workspace configuration when downloading Node.js runtimes [#11281](https://github.com/pnpm/pnpm/issues/11281). Mirrors for other channels, such as `rc` and `nightly`, still apply only from the global configuration.
54
+
55
+ #### Commands
56
+
57
+ - `pnpm run` and `pnpm exec` now forward `--config.*` command-line flags to the install started by `verifyDepsBeforeRun` [pnpm/tasks#60](https://github.com/pnpm/tasks/issues/60).
58
+
59
+ - `pnpm dlx` with `--package` but no command now fails with `'pnpm dlx' requires a command to run`. Before, it installed the package and then crashed trying to run an empty command.
60
+
61
+ - `pnpm unpublish <pkg>@<version>` now deletes the tarball under the registry's path when the registry is served under one, such as Gitea's npm registry. It used to send the delete to the host root and report success without removing the version [#16568](https://github.com/pnpm/pnpm/issues/16568). It also no longer mistakes a sibling path such as `/npm-mirror/` for the registry path `/npm/` [pnpm/tasks#94](https://github.com/pnpm/tasks/issues/94).
62
+
63
+ - The interactive `pnpm audit --fix` picker now shows each patched version with the `saveExact` and `savePrefix` style that the override is written with [#13209](https://github.com/pnpm/pnpm/issues/13209).
64
+
65
+ - `pnpm list` now reports the correct package paths when `nodeLinker` is `hoisted` [#9593](https://github.com/pnpm/pnpm/issues/9593).
66
+
67
+ - `pnpm setup` now puts `$PNPM_HOME/bin` first on `PATH` in login shells that inherited it further down, such as the VS Code terminal on macOS. Before, another `node` took precedence over the one installed by `pnpm runtime set node -g`. Run `pnpm setup` again to update the block in your shell config [#16635](https://github.com/pnpm/pnpm/issues/16635).
68
+
69
+ - `pnpm setup` now names the shell config file even if it is already up to date [#16608](https://github.com/pnpm/pnpm/issues/16608).
70
+
71
+ #### Output and messages
72
+
73
+ - A warning about a project's `devEngines` or `packageManager` pin is now printed to stderr. A command such as `pnpm cache path` or `pnpm list --json` keeps only its own output on stdout [#16584](https://github.com/pnpm/pnpm/issues/16584).
74
+
75
+ - The warning for a non-root `resolutions` field now points at the `overrides` field in `pnpm-workspace.yaml` [#11757](https://github.com/pnpm/pnpm/issues/11757).
76
+
77
+ ## 11.28.4
78
+
79
+ pnpm 11.28.4 fixes two ways credentials could leak, makes `pnpm install --frozen-lockfile` accept several lockfiles it rejected, warns when an optional dependency cannot be fetched, and stops `pnpm self-update` from installing a second pnpm next to a Homebrew one.
80
+
81
+ ### Patch Changes
82
+
83
+ - `pnpm login` no longer forwards credentials in its request body to another origin during redirects.
84
+
85
+ - The error for a tarball that fails its integrity check no longer prints credentials, query strings, or fragments from the tarball URL.
86
+
87
+ #### Installing packages
88
+
89
+ - `pnpm install --frozen-lockfile` now succeeds in a project with no dependencies when `pnpm-lock.yaml` records only the pinned pnpm version. Other commands write such a lockfile when they run before the first install. A lockfile missing the `---` line after that section is accepted too [#16477](https://github.com/pnpm/pnpm/issues/16477).
90
+
91
+ - `pnpm install --frozen-lockfile` again succeeds when a workspace project recorded in `pnpm-lock.yaml` has no directory, such as a project left out of a Docker build context. It still fails if the project's directory exists without a `package.json` [#16453](https://github.com/pnpm/pnpm/issues/16453).
92
+
93
+ - `pnpm install --frozen-lockfile` no longer fails with `ERR_PNPM_OUTDATED_LOCKFILE` for a workspace project that declares `dependenciesMeta` and whose dependencies are all workspace links. pnpm now records that project's `dependenciesMeta` in `pnpm-lock.yaml` [#16457](https://github.com/pnpm/pnpm/issues/16457).
94
+
95
+ - Fixed frozen installs replacing a hoisted dependency with a workspace package of the same name. A later `pnpm dedupe` then removed the hoisted link [#16485](https://github.com/pnpm/pnpm/issues/16485).
96
+
97
+ - With `enableGlobalVirtualStore` on, scripts can run entry points that a CommonJS require hook loads again, such as `ts-node index.ts`. They failed with `ERR_UNKNOWN_FILE_EXTENSION` on Node.js versions without built-in TypeScript support [#16436](https://github.com/pnpm/pnpm/issues/16436).
98
+
99
+ #### Optional dependencies
100
+
101
+ - `pnpm install` now prints a warning with the error when an optional dependency cannot be fetched and is skipped. The skipped package is no longer linked into `node_modules` as a broken symlink or listed among the added dependencies. The `pnpm:skipped-optional-dependency` log reports the skip with the `fetch_failure` reason [#16514](https://github.com/pnpm/pnpm/issues/16514).
102
+
103
+ - When an optional dependency fails to build, pnpm now removes its link from `node_modules`. A repeat `pnpm install` then reports "Already up to date" and no longer reruns the failing build [#16468](https://github.com/pnpm/pnpm/issues/16468).
104
+
105
+ - Fixed frozen installs creating symlinks to the working directory for skipped optional dependencies and unresolved peer dependencies [#16454](https://github.com/pnpm/pnpm/issues/16454).
106
+
107
+ #### Hoisted node_modules
108
+
109
+ - With `nodeLinker: hoisted`, a filtered install now keeps the packages of the workspace projects an earlier install put in `node_modules`. This also covers the install that `pnpm --filter <selector> run` and `pnpm --filter <selector> exec` start before the command. Before, these installs removed every package that only the unselected projects needed [#16483](https://github.com/pnpm/pnpm/issues/16483).
110
+
111
+ A filtered install of a workspace project also no longer fails with `ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY` after a filtered install of another project.
112
+
113
+ - `pnpm install` with `nodeLinker: hoisted` now refreshes directories supplied by custom fetchers when reinstalling.
114
+
115
+ #### Speed and network
116
+
117
+ - pnpm now revalidates cached registry metadata with a conditional request, so the registry can answer `304 Not Modified`. Before, pnpm downloaded the whole document again for registries whose responses forbid caching, such as `Cache-Control: no-store` [#16528](https://github.com/pnpm/pnpm/issues/16528), and for packages published within `minimumReleaseAge` [#16506](https://github.com/pnpm/pnpm/issues/16506).
118
+
119
+ - A fetch timeout while other downloads from the same host are still running now lowers concurrency for that host to one connection. Retries of that request, and later downloads from that host, use the lower concurrency. Other hosts keep the configured concurrency [#12791](https://github.com/pnpm/pnpm/issues/12791).
120
+
121
+ #### Running scripts
122
+
123
+ - Scripts run without a terminal no longer start a second `sh` each. One watchdog per pnpm command now ends every script's process group if pnpm is killed, so `pnpm -r run` across many projects starts half as many processes [#16489](https://github.com/pnpm/pnpm/issues/16489).
124
+
125
+ - `pnpm run` and `pnpm exec` now warn and run the command when the install that `verifyDepsBeforeRun` starts fails. This lets scripts run in sandboxes where pnpm cannot install, such as containers with a read-only store or no network [#15173](https://github.com/pnpm/pnpm/issues/15173).
126
+
127
+ - A filtered `pnpm run` or `pnpm exec` now finds dependencies out of date when a workspace dependency of a selected project has no `node_modules` directory, as after a filtered install. With `verifyDepsBeforeRun: install`, pnpm installs that dependency before running the command [pnpm/tasks#45](https://github.com/pnpm/tasks/issues/45).
128
+
129
+ - `pnpm rebuild` and `pnpm approve-builds` refresh command launchers when a build changes a command's interpreter or replaces it with a native executable. Dependent packages' build scripts use the refreshed launchers.
130
+
131
+ #### Updating pnpm
132
+
133
+ - `pnpm self-update` now fails for Homebrew-installed pnpm and prints the `brew upgrade` command for the installed formula, such as `brew upgrade pnpm` or `brew upgrade pnpm@11`. It used to install a second copy of pnpm that the Homebrew one kept shadowing [#16547](https://github.com/pnpm/pnpm/issues/16547).
134
+
135
+ - On Windows, `pnpm self-update` now replaces a `pnpm.exe` left in `PNPM_HOME` or in `PNPM_HOME\bin`. In `PNPM_HOME`, that executable kept running the old version after a successful update. In `PNPM_HOME\bin`, the update failed with `EPERM`. If the executable was in `PNPM_HOME`, `self-update` now asks you to run `pnpm setup` [#9094](https://github.com/pnpm/pnpm/issues/9094).
136
+
137
+ - pnpm can now switch to a `packageManager` version below 11 on x64 musl Linux, such as Alpine [#16467](https://github.com/pnpm/pnpm/issues/16467).
138
+
139
+ - A `devEngines.packageManager` range now records the running pnpm in `pnpm-lock.yaml` only if it meets `minimumReleaseAge`. Otherwise pnpm records the newest version in the range that meets it. If no version in the range does, pnpm still records the running pnpm [#16431](https://github.com/pnpm/pnpm/issues/16431).
140
+
141
+ #### Filtering, settings, and other commands
142
+
143
+ - The `[<since>]` filter selector works again with Git 2.24 through 2.27 [#16561](https://github.com/pnpm/pnpm/issues/16561). With Git older than 2.24, the selector now fails with an error that names the required Git version.
144
+
145
+ - Package-name filters now support `?` to match one character [#2817](https://github.com/pnpm/pnpm/issues/2817).
146
+
147
+ - `pnpm -r pkg get` now reports every selected project when several share a package name. Projects with the same name are keyed by their directory relative to the workspace root. Before, only one of them appeared in the output.
148
+
149
+ - pnpm now reports an `INVALID_SETTING` error when `allowUnusedPatches` in `pnpm-workspace.yaml` is not a boolean, or when `ignoredOptionalDependencies` or `requiredScripts` is not an array of strings. A quoted `allowUnusedPatches` value such as `"false"` was treated as `true`.
150
+
151
+ - `pnpm store path`, `pnpm store status`, and other commands that look up the default store no longer fail when the current directory is not writable. pnpm now uses the store in the pnpm home directory in that case [#16554](https://github.com/pnpm/pnpm/issues/16554).
152
+
3
153
  ## 11.28.3
4
154
 
5
155
  pnpm 11.28.3 updates `undici` to clear a security advisory, fixes "database disk image is malformed" errors when several pnpm processes share a store, and makes packages, catalogs, projects, and commands named like `constructor` work.
@@ -8,9 +8,8 @@
8
8
  # the shim before it reaches its target. Directories come from `${link%/*}`,
9
9
  # which needs no helper at all.
10
10
  #
11
- # Where no default path is compiled in, as on Nix, `command -p` searches PATH
12
- # instead, so the helpers run with node_modules and relative entries dropped from
13
- # PATH.
11
+ # A helper the default path lacks, as in a Nix build sandbox, comes from PATH
12
+ # instead, with node_modules and relative entries dropped from it.
14
13
  caller_path_set=${PATH+set}
15
14
  caller_path=${PATH-}
16
15
  helper_path=
@@ -25,6 +24,11 @@ while [ -n "$rest" ]; do
25
24
  done
26
25
  # An empty PATH searches the current directory.
27
26
  PATH=${helper_path:-/}
27
+ # A helper comes from PATH only when the default path lacks it and PATH has it.
28
+ # The bash 3.2 that macOS ships as sh answers `command -p -v` from PATH.
29
+ run_helper() {
30
+ if command -p -v "$1" >/dev/null 2>&1 || ! command -v "$1" >/dev/null 2>&1; then command -p "$@"; else command "$@"; fi
31
+ }
28
32
  link="$0"
29
33
  # `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
30
34
  # and stands for a file in the current directory.
@@ -35,13 +39,13 @@ esac
35
39
  hops=0
36
40
  while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
37
41
  hops=$((hops+1))
38
- target=$(command -p readlink "$link")
42
+ target=$(run_helper readlink "$link")
39
43
  case "$target" in
40
44
  /*) link="$target" ;;
41
45
  *) link="${link%/*}/$target" ;;
42
46
  esac
43
47
  done
44
- basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
48
+ basedir=$(run_helper printf '%s\n' "$link" | run_helper sed -e 's,\\,/,g')
45
49
  basedir="${basedir%/*}"
46
50
  basedir_abs=$(CDPATH= cd -P -- "$basedir" && pwd -P) || exit $?
47
51
  basedir="$basedir_abs"
@@ -49,7 +53,7 @@ basedir_win="$basedir"
49
53
  exe=""
50
54
  msys=""
51
55
 
52
- case `command -p uname -a` in
56
+ case `run_helper uname -a` in
53
57
  *CYGWIN*|*MINGW*|*MSYS*)
54
58
  if converted=$(command -p cygpath -w "$basedir" 2>/dev/null) && [ -n "$converted" ]; then
55
59
  basedir_win="$converted"
@@ -8,9 +8,8 @@
8
8
  # the shim before it reaches its target. Directories come from `${link%/*}`,
9
9
  # which needs no helper at all.
10
10
  #
11
- # Where no default path is compiled in, as on Nix, `command -p` searches PATH
12
- # instead, so the helpers run with node_modules and relative entries dropped from
13
- # PATH.
11
+ # A helper the default path lacks, as in a Nix build sandbox, comes from PATH
12
+ # instead, with node_modules and relative entries dropped from it.
14
13
  caller_path_set=${PATH+set}
15
14
  caller_path=${PATH-}
16
15
  helper_path=
@@ -25,6 +24,11 @@ while [ -n "$rest" ]; do
25
24
  done
26
25
  # An empty PATH searches the current directory.
27
26
  PATH=${helper_path:-/}
27
+ # A helper comes from PATH only when the default path lacks it and PATH has it.
28
+ # The bash 3.2 that macOS ships as sh answers `command -p -v` from PATH.
29
+ run_helper() {
30
+ if command -p -v "$1" >/dev/null 2>&1 || ! command -v "$1" >/dev/null 2>&1; then command -p "$@"; else command "$@"; fi
31
+ }
28
32
  link="$0"
29
33
  # `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
30
34
  # and stands for a file in the current directory.
@@ -35,13 +39,13 @@ esac
35
39
  hops=0
36
40
  while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
37
41
  hops=$((hops+1))
38
- target=$(command -p readlink "$link")
42
+ target=$(run_helper readlink "$link")
39
43
  case "$target" in
40
44
  /*) link="$target" ;;
41
45
  *) link="${link%/*}/$target" ;;
42
46
  esac
43
47
  done
44
- basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
48
+ basedir=$(run_helper printf '%s\n' "$link" | run_helper sed -e 's,\\,/,g')
45
49
  basedir="${basedir%/*}"
46
50
  basedir_abs=$(CDPATH= cd -P -- "$basedir" && pwd -P) || exit $?
47
51
  basedir="$basedir_abs"
@@ -49,7 +53,7 @@ basedir_win="$basedir"
49
53
  exe=""
50
54
  msys=""
51
55
 
52
- case `command -p uname -a` in
56
+ case `run_helper uname -a` in
53
57
  *CYGWIN*|*MINGW*|*MSYS*)
54
58
  if converted=$(command -p cygpath -w "$basedir" 2>/dev/null) && [ -n "$converted" ]; then
55
59
  basedir_win="$converted"
@@ -8,9 +8,8 @@
8
8
  # the shim before it reaches its target. Directories come from `${link%/*}`,
9
9
  # which needs no helper at all.
10
10
  #
11
- # Where no default path is compiled in, as on Nix, `command -p` searches PATH
12
- # instead, so the helpers run with node_modules and relative entries dropped from
13
- # PATH.
11
+ # A helper the default path lacks, as in a Nix build sandbox, comes from PATH
12
+ # instead, with node_modules and relative entries dropped from it.
14
13
  caller_path_set=${PATH+set}
15
14
  caller_path=${PATH-}
16
15
  helper_path=
@@ -25,6 +24,11 @@ while [ -n "$rest" ]; do
25
24
  done
26
25
  # An empty PATH searches the current directory.
27
26
  PATH=${helper_path:-/}
27
+ # A helper comes from PATH only when the default path lacks it and PATH has it.
28
+ # The bash 3.2 that macOS ships as sh answers `command -p -v` from PATH.
29
+ run_helper() {
30
+ if command -p -v "$1" >/dev/null 2>&1 || ! command -v "$1" >/dev/null 2>&1; then command -p "$@"; else command "$@"; fi
31
+ }
28
32
  link="$0"
29
33
  # `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
30
34
  # and stands for a file in the current directory.
@@ -35,13 +39,13 @@ esac
35
39
  hops=0
36
40
  while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
37
41
  hops=$((hops+1))
38
- target=$(command -p readlink "$link")
42
+ target=$(run_helper readlink "$link")
39
43
  case "$target" in
40
44
  /*) link="$target" ;;
41
45
  *) link="${link%/*}/$target" ;;
42
46
  esac
43
47
  done
44
- basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
48
+ basedir=$(run_helper printf '%s\n' "$link" | run_helper sed -e 's,\\,/,g')
45
49
  basedir="${basedir%/*}"
46
50
  basedir_abs=$(CDPATH= cd -P -- "$basedir" && pwd -P) || exit $?
47
51
  basedir="$basedir_abs"
@@ -49,7 +53,7 @@ basedir_win="$basedir"
49
53
  exe=""
50
54
  msys=""
51
55
 
52
- case `command -p uname -a` in
56
+ case `run_helper uname -a` in
53
57
  *CYGWIN*|*MINGW*|*MSYS*)
54
58
  if converted=$(command -p cygpath -w "$basedir" 2>/dev/null) && [ -n "$converted" ]; then
55
59
  basedir_win="$converted"
@@ -8,9 +8,8 @@
8
8
  # the shim before it reaches its target. Directories come from `${link%/*}`,
9
9
  # which needs no helper at all.
10
10
  #
11
- # Where no default path is compiled in, as on Nix, `command -p` searches PATH
12
- # instead, so the helpers run with node_modules and relative entries dropped from
13
- # PATH.
11
+ # A helper the default path lacks, as in a Nix build sandbox, comes from PATH
12
+ # instead, with node_modules and relative entries dropped from it.
14
13
  caller_path_set=${PATH+set}
15
14
  caller_path=${PATH-}
16
15
  helper_path=
@@ -25,6 +24,11 @@ while [ -n "$rest" ]; do
25
24
  done
26
25
  # An empty PATH searches the current directory.
27
26
  PATH=${helper_path:-/}
27
+ # A helper comes from PATH only when the default path lacks it and PATH has it.
28
+ # The bash 3.2 that macOS ships as sh answers `command -p -v` from PATH.
29
+ run_helper() {
30
+ if command -p -v "$1" >/dev/null 2>&1 || ! command -v "$1" >/dev/null 2>&1; then command -p "$@"; else command "$@"; fi
31
+ }
28
32
  link="$0"
29
33
  # `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup
30
34
  # and stands for a file in the current directory.
@@ -35,13 +39,13 @@ esac
35
39
  hops=0
36
40
  while [ -L "$link" ] && [ "$hops" -lt 40 ]; do
37
41
  hops=$((hops+1))
38
- target=$(command -p readlink "$link")
42
+ target=$(run_helper readlink "$link")
39
43
  case "$target" in
40
44
  /*) link="$target" ;;
41
45
  *) link="${link%/*}/$target" ;;
42
46
  esac
43
47
  done
44
- basedir=$(command -p printf '%s\n' "$link" | command -p sed -e 's,\\,/,g')
48
+ basedir=$(run_helper printf '%s\n' "$link" | run_helper sed -e 's,\\,/,g')
45
49
  basedir="${basedir%/*}"
46
50
  basedir_abs=$(CDPATH= cd -P -- "$basedir" && pwd -P) || exit $?
47
51
  basedir="$basedir_abs"
@@ -49,7 +53,7 @@ basedir_win="$basedir"
49
53
  exe=""
50
54
  msys=""
51
55
 
52
- case `command -p uname -a` in
56
+ case `run_helper uname -a` in
53
57
  *CYGWIN*|*MINGW*|*MSYS*)
54
58
  if converted=$(command -p cygpath -w "$basedir" 2>/dev/null) && [ -n "$converted" ]; then
55
59
  basedir_win="$converted"