Skip to content

Commit fac90a2

Browse files
committed
install: add support for package aliases
1 parent 26b768d commit fac90a2

File tree

12 files changed

+76
-20
lines changed

12 files changed

+76
-20
lines changed

lib/install.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ Installer.prototype.normalizeCurrentTree = function (cb) {
401401
if (this.currentTree.error) {
402402
for (let child of this.currentTree.children) {
403403
if (!child.fakeChild && isExtraneous(child)) {
404-
this.currentTree.package.dependencies[child.package.name] = computeVersionSpec(this.currentTree, child)
404+
this.currentTree.package.dependencies[moduleName(child)] = computeVersionSpec(this.currentTree, child)
405405
}
406406
}
407407
}
@@ -825,7 +825,11 @@ Installer.prototype.printInstalledForHuman = function (diffs, auditResult) {
825825
var report = ''
826826
if (this.args.length && (added || updated)) {
827827
report += this.args.map((p) => {
828-
return `+ ${p.name}@${p.version}`
828+
return `+ ${p.name}@${p.version}${
829+
!p._requested.name || p._requested.name === p.name
830+
? ''
831+
: ` (as ${p._requested.name})`
832+
}`
829833
}).join('\n') + '\n'
830834
}
831835
var actions = []
@@ -922,10 +926,14 @@ Installer.prototype.printInstalledForJSON = function (diffs, auditResult) {
922926
function recordAction (action) {
923927
var mutation = action[0]
924928
var child = action[1]
929+
const isAlias = child.package && child.package._requested.type === 'alias'
930+
const name = isAlias
931+
? child.package._requested.name
932+
: child.package && child.package.name
925933
var result = {
926934
action: mutation,
927-
name: moduleName(child),
928-
version: child.package && child.package.version,
935+
name,
936+
version: child.package && `${isAlias ? `npm:${child.package.name}@` : ''}${child.package.version}`,
929937
path: child.path
930938
}
931939
if (mutation === 'move') {
@@ -947,10 +955,16 @@ Installer.prototype.printInstalledForParseable = function (diffs) {
947955
} else if (mutation === 'update') {
948956
var previousVersion = child.oldPkg.package && child.oldPkg.package.version
949957
}
958+
const isAlias = child.package._requested.type === 'alias'
959+
const version = child.package && isAlias
960+
? `npm:${child.package.name}@${child.package.version}`
961+
: child.package
962+
? child.package.version
963+
: ''
950964
output(
951965
mutation + '\t' +
952966
moduleName(child) + '\t' +
953-
(child.package ? child.package.version : '') + '\t' +
967+
version + '\t' +
954968
(child.path ? path.relative(self.where, child.path) : '') + '\t' +
955969
(previousVersion || '') + '\t' +
956970
(previousPath || ''))

lib/install/action/extract.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const figgyPudding = require('figgy-pudding')
66
const stat = BB.promisify(require('graceful-fs').stat)
77
const gentlyRm = BB.promisify(require('../../utils/gently-rm.js'))
88
const mkdirp = BB.promisify(require('mkdirp'))
9+
const moduleName = require('../../utils/module-name.js')
910
const moduleStagingPath = require('../module-staging-path.js')
1011
const move = require('../../utils/move.js')
1112
const npa = require('npm-package-arg')
@@ -113,7 +114,7 @@ function readBundled (pkg, staging, extractTo) {
113114
}
114115

115116
function stageBundledModule (bundler, child, staging, parentPath) {
116-
const stageFrom = path.join(parentPath, 'node_modules', child.package.name)
117+
const stageFrom = path.join(parentPath, 'node_modules', moduleName(child))
117118
const stageTo = moduleStagingPath(staging, child)
118119

119120
return BB.map(child.children, (child) => {

lib/install/action/global-install.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ var path = require('path')
33
var npm = require('../../npm.js')
44
var Installer = require('../../install.js').Installer
55
var packageId = require('../../utils/package-id.js')
6+
var moduleName = require('../../utils/module-name.js')
67

78
module.exports = function (staging, pkg, log, next) {
89
log.silly('global-install', packageId(pkg))
910
var globalRoot = path.resolve(npm.globalDir, '..')
1011
npm.config.set('global', true)
11-
var install = new Installer(globalRoot, false, [pkg.package.name + '@' + pkg.package._requested.fetchSpec])
12+
var install = new Installer(globalRoot, false, [moduleName(pkg) + '@' + pkg.package._requested.rawSpec])
1213
install.link = false
1314
install.run(function () {
1415
npm.config.set('global', false)

lib/install/action/global-link.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
'use strict'
2+
var moduleName = require('../../utils/module-name.js')
23
var npm = require('../../npm.js')
34
var packageId = require('../../utils/package-id.js')
45

56
module.exports = function (staging, pkg, log, next) {
67
log.silly('global-link', packageId(pkg))
7-
npm.link(pkg.package.name, next)
8+
npm.link(moduleName(pkg), next)
89
}

lib/install/and-add-parent-to-errors.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
'use strict'
2+
var moduleName = require('../utils/module-name.js')
23
var validate = require('aproba')
34

45
module.exports = function (parent, cb) {
56
validate('F', [cb])
67
return function (er) {
78
if (!er) return cb.apply(null, arguments)
89
if (er instanceof Error && parent && parent.package && parent.package.name) {
9-
er.parent = parent.package.name
10+
er.parent = moduleName(parent)
1011
}
1112
cb(er)
1213
}

lib/install/deps.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ function doesChildVersionMatch (child, requested, requestor) {
5757
if (fromSw.toString() === requested.toString()) return true
5858
}
5959

60+
if (requested.type === 'alias') {
61+
return doesChildVersionMatch(child, requested.subSpec, requestor)
62+
}
63+
6064
if (!registryTypes[requested.type]) {
6165
var childReq = child.package._requested
6266
if (childReq) {
@@ -72,7 +76,7 @@ function doesChildVersionMatch (child, requested, requestor) {
7276
// You'll see this scenario happen with at least tags and git dependencies.
7377
// Some buggy clients will write spaces into the module name part of a _from.
7478
if (child.package._from) {
75-
var fromReq = npa.resolve(moduleName(child), child.package._from.replace(new RegExp('^\\s*' + moduleName(child) + '\\s*@'), ''))
79+
var fromReq = npa(child.package._from)
7680
if (fromReq.rawSpec === requested.rawSpec) return true
7781
if (fromReq.type === requested.type && fromReq.saveSpec && fromReq.saveSpec === requested.saveSpec) return true
7882
}
@@ -289,13 +293,15 @@ function computeVersionSpec (tree, child) {
289293
var requested
290294
var childReq = child.package._requested
291295
if (child.isLink) {
292-
requested = npa.resolve(child.package.name, 'file:' + child.realpath, getTop(tree).path)
296+
requested = npa.resolve(moduleName(child), 'file:' + child.realpath, getTop(tree).path)
293297
} else if (childReq && (isNotEmpty(childReq.saveSpec) || (isNotEmpty(childReq.rawSpec) && isNotEmpty(childReq.fetchSpec)))) {
294298
requested = child.package._requested
295299
} else if (child.package._from) {
296300
requested = npa(child.package._from, tree.path)
301+
} else if (child.name && child.name !== child.package.name) {
302+
requested = npa.resolve(child.name, `npm:${child.package.name}@${child.package.version})`)
297303
} else {
298-
requested = npa.resolve(child.package.name, child.package.version)
304+
npa.resolve(child.package.name, child.package.version)
299305
}
300306
if (isRegistry(requested)) {
301307
var version = child.package.version
@@ -305,6 +311,9 @@ function computeVersionSpec (tree, child) {
305311
!npm.config.get('save-exact')) {
306312
rangeDescriptor = npm.config.get('save-prefix')
307313
}
314+
if (requested.type === 'alias') {
315+
rangeDescriptor = `npm:${requested.subSpec.name}@${rangeDescriptor}`
316+
}
308317
return rangeDescriptor + version
309318
} else if (requested.type === 'directory' || requested.type === 'file') {
310319
return 'file:' + unixFormatPath(path.relative(getTop(tree).path, requested.fetchSpec))
@@ -324,7 +333,7 @@ exports.removeDeps = function (args, tree, saveToDependencies, next) {
324333
for (let pkg of args) {
325334
var pkgName = moduleName(pkg)
326335
var toRemove = tree.children.filter(moduleNameMatches(pkgName))
327-
var pkgToRemove = toRemove[0] || createChild({package: {name: pkgName}})
336+
var pkgToRemove = toRemove[0] || createChild({name: pkgName})
328337
var saveType = getSaveType(tree, pkg) || 'dependencies'
329338
if (tree.isTop && saveToDependencies) {
330339
pkgToRemove.save = saveType
@@ -652,11 +661,13 @@ function resolveWithNewModule (pkg, tree, log, next) {
652661
addBundled(pkg, (bundleErr) => {
653662
var parent = earliestInstallable(tree, tree, pkg, log, null) || tree
654663
var isLink = pkg._requested.type === 'directory'
664+
var name = pkg._requested.name || pkg.name
655665
var child = createChild({
666+
name,
656667
package: pkg,
657668
parent: parent,
658-
path: path.join(parent.isLink ? parent.realpath : parent.path, 'node_modules', pkg.name),
659-
realpath: isLink ? pkg._requested.fetchSpec : path.join(parent.realpath, 'node_modules', pkg.name),
669+
path: path.join(parent.isLink ? parent.realpath : parent.path, 'node_modules', name),
670+
realpath: isLink ? pkg._requested.fetchSpec : path.join(parent.realpath, 'node_modules', name),
660671
children: pkg._bundled || [],
661672
isLink: isLink,
662673
isInLink: parent.isLink,

lib/install/is-only-optional.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
module.exports = isOptional
33

44
const isOptDep = require('./is-opt-dep.js')
5+
const moduleName = require('../utils/module-name.js')
56

67
function isOptional (node, seen) {
78
if (!seen) seen = new Set()
@@ -15,6 +16,6 @@ function isOptional (node, seen) {
1516
const swOptional = node.fromShrinkwrap && node.package._optional
1617
return node.requiredBy.every(function (req) {
1718
if (req.fakeChild && swOptional) return true
18-
return isOptDep(req, node.package.name) || isOptional(req, seen)
19+
return isOptDep(req, moduleName(node)) || isOptional(req, seen)
1920
})
2021
}

lib/install/validate-args.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
var validate = require('aproba')
33
var asyncMap = require('slide').asyncMap
44
var chain = require('slide').chain
5+
var moduleName = require('../utils/module-name.js')
56
var npmInstallChecks = require('npm-install-checks')
67
var iferr = require('iferr')
78
var checkEngine = npmInstallChecks.checkEngine
@@ -54,7 +55,7 @@ var isInstallable = module.exports.isInstallable = function (pkg, next) {
5455
}
5556

5657
function checkSelf (idealTree, pkg, force, next) {
57-
if (idealTree.package && idealTree.package.name !== pkg.name) return next()
58+
if (moduleName(idealTree) !== pkg.name) return next()
5859
if (force) {
5960
var warn = new Error("Wouldn't install " + pkg.name + ' as a dependency of itself, but being forced')
6061
warn.code = 'ENOSELF'

lib/ls.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var readPackageTree = require('read-package-tree')
1212
var archy = require('archy')
1313
var semver = require('semver')
1414
var color = require('ansicolors')
15+
var moduleName = require('./utils/module-name.js')
1516
var npa = require('npm-package-arg')
1617
var sortedObject = require('sorted-object')
1718
var npm = require('./npm.js')
@@ -59,7 +60,9 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
5960
args = []
6061
} else {
6162
args = args.map(function (a) {
62-
if (typeof a === 'object') {
63+
if (typeof a === 'object' && a.package._requested.type === 'alias') {
64+
return [moduleName(a), `npm:${a.package.name}@${a.package.version}`, a]
65+
} else if (typeof a === 'object') {
6366
return [a.package.name, a.package.version, a]
6467
} else {
6568
var p = npa(a)
@@ -278,6 +281,9 @@ function unloop (root) {
278281
var deps = current.dependencies = current.dependencies || {}
279282
Object.keys(deps).forEach(function (d) {
280283
var dep = deps[d]
284+
if (dep.name !== d) {
285+
dep.version = `${dep.name}@${dep.version}`
286+
}
281287
if (dep.missing && !dep.dependencies) return
282288
if (dep.path && seen.has(dep)) {
283289
dep = deps[d] = Object.assign({}, dep)
@@ -394,6 +400,9 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
394400
var out = {}
395401
// the top level is a bit special.
396402
out.label = data._id || ''
403+
if (data._requested && data._requested.type === 'alias') {
404+
out.label = `${d}@npm:${out.label}`
405+
}
397406
if (data._found === 'explicit' && data._id) {
398407
if (npm.color) {
399408
out.label = color.bgBlack(color.yellow(out.label.trim())) + ' '
@@ -546,3 +555,16 @@ function makeParseable_ (data, long, dir, depth, parent, d) {
546555
(data.peerInvalid ? ':PEERINVALID' : '') +
547556
(data.peerMissing ? ':PEERINVALID:MISSING' : '')
548557
}
558+
559+
function physicalName (data) {
560+
if (!data._location) {
561+
return data.name
562+
} else {
563+
const match = data._location.match(/(?:@[^/\\]+[/\\])?[^/\\]+$/i)
564+
if (match) {
565+
return match[0]
566+
} else {
567+
return data.name
568+
}
569+
}
570+
}

lib/outdated.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ function makeJSON (list, opts) {
215215

216216
function outdated_ (args, path, tree, parentHas, depth, opts, cb) {
217217
if (!tree.package) tree.package = {}
218-
if (path && tree.package.name) path += ' > ' + tree.package.name
219-
if (!path && tree.package.name) path = tree.package.name
218+
if (path && moduleName(tree)) path += ' > ' + tree.package.name
219+
if (!path && moduleName(tree)) path = tree.package.name
220220
if (depth > opts.depth) {
221221
return cb(null, [])
222222
}

0 commit comments

Comments
 (0)