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

Gracefully handle "Cannot read property .match of undefined" #1009

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ We often want to know if the bug we've fixed for the feature we've added has any
1. Make a pull-request against this repository
2. Add the following comment to the pull-request: "`test this please ✅`"

This will trigger the [benmark suite](https://github.com/npm/benchmarks) to run against your pull-request, and when it's finished running it will post a comment on your pull-request just like bellow. You'll be able to see the results from the suite inline in your pull-request.
This will trigger the [benchmark suite](https://github.com/npm/benchmarks) to run against your pull-request, and when it's finished running it will post a comment on your pull-request just like below. You'll be able to see the results from the suite inline in your pull-request.

> You'll notice that the bot-user will also add a 🚀 reaction to your comment to
let you know that it's sent the request to start the benchmark suite.
Expand Down Expand Up @@ -186,7 +186,6 @@ You'll need a few things installed in order to update and test the CLI project d

> Package vendoring is commonly referred to as the case where dependent packages are stored in the same place as your project. That usually means you dependencies are checked into your source management system, such as Git.

The CLI project vendors it's dependencies in the `node_modules/` folder. Meaning all the dependencies that the CLI project uses are contained withing the project itself. This is represented by the `bundledDependencies` section in the root level `package.json` file. The main reason for this is because the `npm` CLI project is distributed with the NodeJS runtime and needs to work out of the box, which means all dependencies need to be available after the runtime is installed.
The CLI project vendors its dependencies in the `node_modules/` folder. Meaning all the dependencies that the CLI project uses are contained within the project itself. This is represented by the `bundledDependencies` section in the root level `package.json` file. The main reason for this is because the `npm` CLI project is distributed with the NodeJS runtime and needs to work out of the box, which means all dependencies need to be available after the runtime is installed.

There are a couple scripts created to help manage this process in the `scripts/` folder.

8 changes: 8 additions & 0 deletions lib/install/inflate-shrinkwrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ function inflateShrinkwrap (topPath, tree, swdeps, opts) {
const sw = swdeps[name]
const dependencies = sw.dependencies || {}
const requested = realizeShrinkwrapSpecifier(name, sw, topPath)

if (Object.keys(sw).length === 0) {
let message = `Object for dependency "${name}" is empty.\n`
message += 'Something went wrong. Regenerate the package-lock.json with "npm install".\n'
message += 'If using a shrinkwrap, regenerate with "npm shrinkwrap".'
return Promise.reject(new Error(message))
}

return inflatableChild(
onDisk[name], name, topPath, tree, sw, requested, opts
).then((child) => {
Expand Down
68 changes: 68 additions & 0 deletions test/tap/lockfile-empty-dep-value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict'

const common = require('../common-tap.js')
const path = require('path')
const test = require('tap').test

const Tacks = require('tacks')
const File = Tacks.File
const Dir = Tacks.Dir

const basedir = common.pkg
const testdir = path.join(basedir, 'testdir')

const fixture = new Tacks(Dir({
cache: Dir(),
global: Dir(),
tmp: Dir(),
testdir: Dir({
'package-lock.json': File({
name: 'http-locks',
version: '1.0.0',
lockfileVersion: 1,
requires: true,
dependencies: {
minimist: {}
}
}),
'package.json': File({
name: 'http-locks',
version: '1.0.0',
dependencies: {
minimist: common.registry + '/minimist/-/minimist-0.0.5.tgz'
}
})
})
}))

function setup () {
cleanup()
fixture.create(basedir)
}

function cleanup () {
fixture.remove(basedir)
}

test('setup', function (t) {
setup()
t.done()
})

test('raises error to regenerate the lock file', function (t) {
common.npm(['install'], {cwd: testdir}, function (err, code, stdout, stderr) {
if (err) throw err
t.match(
stderr,
'npm ERR! Something went wrong. Regenerate the package-lock.json with "npm install".',
'returns message to regenerate package-lock'
)

t.done()
})
})

test('cleanup', function (t) {
cleanup()
t.done()
})
66 changes: 66 additions & 0 deletions test/tap/shrinkwrap-empty-dep-value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict'

const common = require('../common-tap.js')
const path = require('path')
const test = require('tap').test

const Tacks = require('tacks')
const File = Tacks.File
const Dir = Tacks.Dir

const basedir = common.pkg
const testdir = path.join(basedir, 'testdir')

const fixture = new Tacks(Dir({
cache: Dir(),
global: Dir(),
tmp: Dir(),
testdir: Dir({
'npm-shrinkwrap.json': File({
name: 'http-locks',
version: '0.0.0',
dependencies: {
minimist: {}
}
}),
'package.json': File({
name: 'http-locks',
version: '1.0.0',
dependencies: {
minimist: common.registry + '/minimist/-/minimist-0.0.5.tgz'
}
})
})
}))

function setup () {
cleanup()
fixture.create(basedir)
}

function cleanup () {
fixture.remove(basedir)
}

test('setup', function (t) {
setup()
t.done()
})

test('raises error to regenerate the shrinkwrap', function (t) {
common.npm(['install'], {cwd: testdir}, function (err, code, stdout, stderr) {
if (err) throw err
t.match(
stderr,
'npm ERR! If using a shrinkwrap, regenerate with "npm shrinkwrap".',
'returns message to regenerate shrinkwrap'
)

t.done()
})
})

test('cleanup', function (t) {
cleanup()
t.done()
})