-
Notifications
You must be signed in to change notification settings - Fork 62
fix: follow symlinks on build-ideal-tree add #129
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ const pickManifest = require('npm-pick-manifest') | |
| const mapWorkspaces = require('@npmcli/map-workspaces') | ||
| const promiseCallLimit = require('promise-call-limit') | ||
| const getPeerSet = require('../peer-set.js') | ||
| const realpath = require('../../lib/realpath.js') | ||
|
|
||
| const fromPath = require('../from-path.js') | ||
| const calcDepFlags = require('../calc-dep-flags.js') | ||
|
|
@@ -79,6 +80,10 @@ const _globalStyle = Symbol('globalStyle') | |
| const _globalRootNode = Symbol('globalRootNode') | ||
| const _isVulnerable = Symbol.for('isVulnerable') | ||
| const _usePackageLock = Symbol.for('usePackageLock') | ||
| const _rpcache = Symbol.for('realpathCache') | ||
| const _stcache = Symbol.for('statCache') | ||
| const _followSymlinkPath = Symbol('followSymlinkPath') | ||
| const _retrieveSpecName = Symbol('retrieveSpecName') | ||
|
|
||
| // used for the ERESOLVE error to show the last peer conflict encountered | ||
| const _peerConflict = Symbol('peerConflict') | ||
|
|
@@ -130,6 +135,12 @@ module.exports = cls => class IdealTreeBuilder extends cls { | |
| this[_linkNodes] = new Set() | ||
| this[_manifests] = new Map() | ||
| this[_peerConflict] = null | ||
|
|
||
| // caches for cached realpath calls | ||
| const cwd = process.cwd() | ||
| // assume that the cwd is real enough for our purposes | ||
| this[_rpcache] = this[_rpcache] | ||
| this[_stcache] = this[_stcache] | ||
| } | ||
|
|
||
| get explicitRequests () { | ||
|
|
@@ -326,18 +337,11 @@ module.exports = cls => class IdealTreeBuilder extends cls { | |
| return Promise.all(add.map(s => { | ||
ruyadorno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // in global mode, `npm i foo.tgz` needs to be resolved from | ||
| // the current working dir, NOT /usr/local/lib! | ||
| const spec = npa(s, this[_global] ? process.cwd() : this.path) | ||
| // if it's just @'' then we reload whatever's there, or get latest | ||
| // if it's an explicit tag, we need to install that specific tag version | ||
| const isTag = spec.rawSpec && spec.type === 'tag' | ||
| return spec.name && !isTag ? spec : pacote.manifest(spec).then(mani => { | ||
| // if it's a tag type, then we need to run it down to an actual version | ||
| if (isTag) | ||
| return npa(`${mani.name}@${mani.version}`) | ||
|
|
||
| spec.name = mani.name | ||
| return spec | ||
| }) | ||
| const currpath = this[_global] ? process.cwd() : this.path | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @isaacs I decided to leave this here for now, we can revisit it later
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can land on a separate commit, but ought to get it fixed, may as well pull in with this changeset.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. eh, let's land it in a sep commit, maybe even better sep PR, let's thing about future us trying to bisect something 😂 |
||
| const spec = npa(s, currpath) | ||
|
|
||
| return this[_retrieveSpecName](spec) | ||
| .then(add => this[_followSymlinkPath](add, currpath)) | ||
| })).then(add => { | ||
| this[_resolvedAdd] = add | ||
| // now add is a list of spec objects with names. | ||
|
|
@@ -355,6 +359,41 @@ module.exports = cls => class IdealTreeBuilder extends cls { | |
| }) | ||
| } | ||
|
|
||
| async [_retrieveSpecName] (spec) { | ||
| // if it's just @'' then we reload whatever's there, or get latest | ||
| // if it's an explicit tag, we need to install that specific tag version | ||
| const isTag = spec.rawSpec && spec.type === 'tag' | ||
|
|
||
| if (spec.name && !isTag) | ||
| return spec | ||
|
|
||
| const mani = await pacote.manifest(spec) | ||
| // if it's a tag type, then we need to run it down to an actual version | ||
| if (isTag) | ||
| return npa(`${mani.name}@${mani.version}`) | ||
|
|
||
| spec.name = mani.name | ||
| return spec | ||
| } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was just a small refactor for readability since when adding the |
||
|
|
||
| async [_followSymlinkPath] (spec, currpath) { | ||
| if (spec.type === 'directory') { | ||
| const real = await ( | ||
| realpath(spec.fetchSpec, this[_rpcache], this[_stcache]) | ||
| // TODO: create synthetic test case to simulate realpath failure | ||
| .catch(/* istanbul ignore next */() => null) | ||
ruyadorno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) | ||
|
|
||
| /* istanbul ignore else - same as the ignored catch above */ | ||
| if (real) { | ||
| const { name } = spec | ||
| spec = npa(`file:${relpath(this.path, real)}`, this.path) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the new spec gets npa parsed relative to |
||
| spec.name = name | ||
| } | ||
| } | ||
| return spec | ||
| } | ||
|
|
||
| // TODO: provide a way to fix bundled deps by exposing metadata about | ||
| // what's in the bundle at each published manifest. Without that, we | ||
| // can't possibly fix bundled deps without breaking a ton of other stuff, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was introduced in #125 as a way to compensate for the wrong parsed links and should not be necessary anymore