Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/v7.0.0 beta.11 #1810

Merged
merged 13 commits into from
Sep 16, 2020
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -701,3 +701,4 @@ Edward Thomson <ethomson@edwardthomson.com>
Masafumi Koba <ybiquitous@gmail.com>
jamesgeorge007 <jamesgeorge998001@gmail.com>
Mickael Jeanroy <mickael.jeanroy@gmail.com>
Myles Borins <mylesborins@github.com>
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
## v7.0.0-beta.11 (2020-09-16)

* [`63005f4a9`](https://github.com/npm/cli/commit/63005f4a98d55786fda46f3bbb3feab044d078df)
[#1639](https://github.com/npm/cli/issues/1639)
npm view should not output extra newline ([@MylesBorins](https://github.com/MylesBorins))
* [`3743a42c8`](https://github.com/npm/cli/commit/3743a42c854d9ea7e333d7ff86d206a4b079a352)
[#1750](https://github.com/npm/cli/pull/1750)
add outdated tests ([@claudiahdz](https://github.com/claudiahdz))
* [`2019abdf1`](https://github.com/npm/cli/commit/2019abdf159eb13c9fb3a2bd2f35897a8f52b0d9)
[#1786](https://github.com/npm/cli/pull/1786)
add lib/link.js tests ([@ruyadorno](https://github.com/ruyadorno))
* [`2f8d11968`](https://github.com/npm/cli/commit/2f8d11968607a74c8def3c05266049bee5e313eb)
@`npmcli/arborist@0.0.25`
* add meta vulnerability calculator for faster audits
* changed parsing specs to be relative to cwd
* fix logging script execution
* fix properly following resolved symlinks
* fix package.json dependencies order
* [`49b2bf5a7`](https://github.com/npm/cli/commit/49b2bf5a798b49d52166744088a80b8a39ccaeb6)
@`npmcli/config@1.1.8`
* fix unkown envs to be passed through
* fix setting correct globalPrefix on load
* [`f9aac351d`](https://github.com/npm/cli/commit/f9aac351dd36a19d14e1f951a2e8e20b41545822)
`libnpmversion@1.0.5`
* fix git ignored lockfiles

## v7.0.0-beta.10 (2020-09-08)

* [`7418970f0`](https://github.com/npm/cli/commit/7418970f03229dd2bce7973b99b981779aee6916)
Expand Down
104 changes: 87 additions & 17 deletions lib/link.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
// link with no args: symlink the folder to the global location
// link with package arg: symlink the global to the local
'use strict'

const { readdir } = require('fs')
const { resolve } = require('path')

const Arborist = require('@npmcli/arborist')
const npa = require('npm-package-arg')
const rpj = require('read-package-json-fast')
const semver = require('semver')

const npm = require('./npm.js')
const usageUtil = require('./utils/usage.js')
const reifyOutput = require('./utils/reify-output.js')
const { resolve } = require('path')
const Arborist = require('@npmcli/arborist')

const completion = (opts, cb) => {
const { readdir } = require('fs')
const dir = npm.globalDir
readdir(dir, (er, files) => cb(er, files.filter(f => !/^[._-]/.test(f))))
}
Expand All @@ -23,44 +27,110 @@ const cmd = (args, cb) => link(args).then(() => cb()).catch(cb)

const link = async args => {
if (npm.config.get('global')) {
throw new Error(
'link should never be --global.\n' +
'Please re-run this command with --local'
throw Object.assign(
new Error(
'link should never be --global.\n' +
'Please re-run this command with --local'
),
{ code: 'ELINKGLOBAL' }
)
}

// link with no args: symlink the folder to the global location
// link with package arg: symlink the global to the local
args = args.filter(a => resolve(a) !== npm.prefix)
return args.length ? linkInstall(args) : linkPkg()
return args.length
? linkInstall(args)
: linkPkg()
}

// Returns a list of items that can't be fulfilled by
// things found in the current arborist inventory
const missingArgsFromTree = (tree, args) => {
const foundNodes = []
const missing = args.filter(a => {
const arg = npa(a)
const nodes = tree.children.values()
const argFound = [...nodes].every(node => {
// TODO: write tests for unmatching version specs, this is hard to test
// atm but should be simple once we have a mocked registry again
if (arg.name !== node.name /* istanbul ignore next */ || (
arg.version &&
!semver.satisfies(node.version, arg.version)
)) {
foundNodes.push(node)
return true
}
})
return argFound
})

// remote nodes from the loaded tree in order
// to avoid dropping them later when reifying
for (const node of foundNodes) {
node.parent = null
}

return missing
}

const linkInstall = async args => {
// add all the args as global installs, and then add symlink installs locally
// to the packages in the global space.
// load current packages from the global space,
// and then add symlinks installs locally
const globalTop = resolve(npm.globalDir, '..')
const globalArb = new Arborist({
const globalOpts = {
...npm.flatOptions,
path: globalTop,
global: true
global: true,
prune: false
}
const globalArb = new Arborist(globalOpts)

// get only current top-level packages from the global space
const globals = await globalArb.loadActual({
filter: (node, kid) =>
!node.isRoot || args.some(a => npa(a).name === kid)
})

const globals = await globalArb.reify({ add: args })
// any extra arg that is missing from the current
// global space should be reified there first
const missing = missingArgsFromTree(globals, args)
if (missing.length) {
await globalArb.reify({
...globalOpts,
add: missing
})
}

// get a list of module names that should be linked in the local prefix
const names = []
for (const a of args) {
const arg = npa(a)
names.push(
arg.type === 'directory'
? (await rpj(resolve(arg.fetchSpec, 'package.json'))).name
: arg.name
)
}

const links = globals.edgesOut.keys()
// create a new arborist instance for the local prefix and
// reify all the pending names as symlinks there
const localArb = new Arborist({
...npm.flatOptions,
path: npm.prefix
})
await localArb.reify({
add: links.map(l => `file:${resolve(globalTop, 'node_modules', l)}`)
add: names.map(l => `file:${resolve(globalTop, 'node_modules', l)}`)
})

reifyOutput(localArb)
}

const linkPkg = async () => {
const globalTop = resolve(npm.globalDir, '..')
const arb = new Arborist({
...npm.flatOptions,
path: resolve(npm.globalDir, '..'),
path: globalTop,
global: true
})
await arb.reify({ add: [`file:${npm.prefix}`] })
Expand Down
36 changes: 15 additions & 21 deletions lib/outdated.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const usage = usageUtil('outdated',
const completion = require('./utils/completion/none.js')

function cmd (args, cb) {
outdated(args, cb)
outdated(args)
.then(() => cb())
.catch(cb)
}
Expand Down Expand Up @@ -78,14 +78,12 @@ async function outdated (args) {
}
output(table(outTable, tableOpts))
}

process.exitCode = outdated.length ? 1 : 0
}

async function outdated_ (tree, deps, opts) {
const list = []
const edges = new Set()

const edges = new Set()
function getEdges (nodes, type) {
const getEdgesIn = (node) => {
for (const edge of node.edgesIn) {
Expand All @@ -94,8 +92,14 @@ async function outdated_ (tree, deps, opts) {
}

const getEdgesOut = (node) => {
for (const edge of node.edgesOut.values()) {
edges.add(edge)
if (opts.global) {
for (const child of node.children.values()) {
edges.add(child)
}
} else {
for (const edge of node.edgesOut.values()) {
edges.add(edge)
}
}
}

Expand All @@ -107,30 +111,19 @@ async function outdated_ (tree, deps, opts) {
}
}

// packument fetching memoizing
const packuments = new Map()
async function getPackument (spec) {
if (packuments.has(spec)) {
return packuments.get(spec)
}
const packument = await pacote.packument(spec, {
fullMetadata: npm.flatOptions.long,
preferOnline: true
})
packuments.set(spec, packument)
return packument
}

async function getOutdatedInfo (edge) {
const spec = npa(edge.name)
const node = edge.to
const {
path,
location,
package: {
version: current
}
} = node || { package: {} }
const node = edge.to || edge
const { path, location } = node
const { version: current } = node.package || {}

const type = edge.optional ? 'optionalDependencies'
: edge.peer ? 'peerDependencies'
Expand All @@ -145,6 +138,7 @@ async function outdated_ (tree, deps, opts) {
const packument = await getPackument(spec)
const expected = edge.spec
// if it's not a range, version, or tag, skip it
/* istanbul ignore next */
if (!npa(`${edge.name}@${edge.spec}`).registry) {
return null
}
Expand All @@ -164,7 +158,7 @@ async function outdated_ (tree, deps, opts) {
location,
wanted: wanted.version,
latest: latest.version,
dependent: edge.from.name,
dependent: edge.from ? edge.from.name : 'global',
homepage: packument.homepage
})
}
Expand Down
4 changes: 2 additions & 2 deletions lib/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ async function printData (data, name, opts) {
// we may have partial lines printed.
log.disableProgress()

// print directly to stdout to not unnecessarily add blank lines
console.log(msg.trim())
// only log if there is something to log
if (msg !== '') console.log(msg.trim())
}

function cleanup (data) {
Expand Down
12 changes: 4 additions & 8 deletions node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading