Skip to content
This repository has been archived by the owner on Aug 11, 2022. It is now read-only.

Commit

Permalink
install/actions: Check installability of modules from shrinkwrap
Browse files Browse the repository at this point in the history
Modules that came into the tree via shrinkwrap won't have had this
determined in advance so we check here and take advantage of the
optional rollback semantics to skip them.

Plus if it was a regular dependency we can just fail out now instead of
trying and failing to install the dep.

Fixes: #13394
PR-URL: #13692
Credit: @iarna
Reviewed-By: @zkat
  • Loading branch information
iarna authored and zkat committed Sep 8, 2016
1 parent 146ee39 commit c00ca3a
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 1 deletion.
19 changes: 18 additions & 1 deletion lib/install/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var failedDependency = require('./deps.js').failedDependency
var moduleName = require('../utils/module-name.js')
var buildPath = require('./build-path.js')
var reportOptionalFailure = require('./report-optional-failure.js')
var isInstallable = require('./validate-args.js').isInstallable

var actions = {}

Expand Down Expand Up @@ -45,7 +46,23 @@ Object.keys(actions).forEach(function (actionName) {
if (!pkg.commit) pkg.commit = []
pkg.commit.push(action.commit)
}
return action(top, buildpath, pkg, log, andFinishTracker(log, andAddParentToErrors(pkg.parent, andHandleOptionalDepErrors(pkg, next))))
if (pkg.knownInstallable) {
return thenRunAction()
} else {
return isInstallable(pkg.package, iferr(andDone(next), andMarkInstallable(thenRunAction)))
}
function andMarkInstallable (cb) {
return function () {
pkg.knownInstallable = true
cb()
}
}
function thenRunAction () {
action(top, buildpath, pkg, log, andDone(next))
}
function andDone (cb) {
return andFinishTracker(log, andAddParentToErrors(pkg.parent, andHandleOptionalDepErrors(pkg, cb)))
}
}
})

Expand Down
96 changes: 96 additions & 0 deletions test/tap/shrinkwrap-optional-platform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict'
var path = require('path')
var test = require('tap').test
var Tacks = require('tacks')
var File = Tacks.File
var Dir = Tacks.Dir
var extend = Object.assign || require('util')._extend
var common = require('../common-tap.js')

var basedir = path.join(__dirname, path.basename(__filename, '.js'))
var testdir = path.join(basedir, 'testdir')
var cachedir = path.join(basedir, 'cache')
var globaldir = path.join(basedir, 'global')
var tmpdir = path.join(basedir, 'tmp')

var conf = {
cwd: testdir,
env: extend(extend({}, process.env), {
npm_config_cache: cachedir,
npm_config_tmp: tmpdir,
npm_config_prefix: globaldir,
npm_config_registry: common.registry,
npm_config_loglevel: 'warn'
})
}

var fixture = new Tacks(Dir({
cache: Dir(),
global: Dir(),
tmp: Dir(),
testdir: Dir({
mod1: Dir({
'package.json': File({
name: 'mod1',
version: '1.0.0',
scripts: {

},
os: ['nosuchos']
})
}),
'npm-shrinkwrap.json': File({
name: 'shrinkwrap-optional-platform',
version: '1.0.0',
dependencies: {
mod1: {
version: '1.0.0',
from: 'mod1',
resolved: 'file:mod1',
optional: true
}
}
}),
'package.json': File({
name: 'shrinkwrap-optional-platform',
version: '1.0.0',
optionalDependencies: {
mod1: 'file:mod1'
},
description: 'x',
repository: 'x',
license: 'Artistic-2.0'
})
})
}))

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

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

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

test('example', function (t) {
common.npm(['install'], conf, function (err, code, stdout, stderr) {
if (err) throw err
t.is(code, 0, 'install ran ok')
t.comment(stdout.trim())
t.comment(stderr.trim())
t.notMatch(stderr, /Exit status 1/, 'did not try to install opt dep')
t.done()
})
})

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

0 comments on commit c00ca3a

Please sign in to comment.