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

[WIP] Support for the --save and --save-dev flags #41

Merged
merged 3 commits into from
Jan 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 20 additions & 6 deletions bin/pnpm-install
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ var dirname = require('path').dirname
var join = require('path').join
var readPkgUp = require('read-pkg-up')
var assign = require('object-assign')
var npa = require('npm-package-arg')

var logger = require('../lib/logger')
var installMultiple = require('../lib/install_multiple')
var config = require('../lib/config')
var save = require('../lib/save')

const cli = require('meow')([
'Usage:',
Expand Down Expand Up @@ -45,7 +47,7 @@ if (cli.flags.debug) {
cli.flags.quiet = true
}

['saveDev', 'save', 'saveExact', 'dryRun', 'global'].forEach((flag) => {
['dryRun', 'global'].forEach(flag => {
if (cli.flags[flag]) {
console.error("Error: '" + flag + "' is not supported yet, sorry!")
process.exit(1)
Expand All @@ -59,27 +61,30 @@ if (cli.flags.debug) {
function run (cli) {
var ctx = {}
var pkg
var packagesToInstall
var installType

return readPkgUp()
.then(pkg_ => { pkg = pkg_ })
.then(_ => updateContext(pkg.path))
.then(_ => install())

function install () {
var packages
installType = cli.input && cli.input.length ? 'named' : 'general'

if (cli.input && cli.input.length) {
packages = cli.input
if (installType === 'named') {
packagesToInstall = cli.input
} else {
packages = assign({},
packagesToInstall = assign({},
pkg.pkg.dependencies || {},
pkg.pkg.devDependencies || {})
}

return installMultiple(ctx,
packages,
packagesToInstall,
join(ctx.root, 'node_modules'),
cli.flags)
.then(savePkgs)
}

function updateContext (packageJson) {
Expand All @@ -89,6 +94,15 @@ function run (cli) {
if (!cli.flags.quiet) ctx.log = logger()
else ctx.log = function () { return function () {} }
}

function savePkgs (packages) {
var saveType = cli.flags.save ? 'dependencies' : cli.flags.saveDev ? 'devDependencies' : null
if (saveType && installType === 'named') {
var inputNames = cli.input.map(pkgName => npa(pkgName).name)
var savedPackages = packages.filter(pkg => inputNames.indexOf(pkg.name) > -1)
return save(pkg, savedPackages, saveType, cli.flags.saveExact)
}
}
}

module.exports = run
Expand Down
6 changes: 5 additions & 1 deletion lib/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,18 @@ module.exports = function install (ctx, pkgSpec, modules, options) {
.then(_ => log('package.json', requireJson(join(paths.target, '_', 'package.json'))))
})
// done
.then(_ => log('done'))
.then(_ => {
log('done')
return pkg
})
.catch(err => {
log('error', err)
throw err
})

// set metadata as fetched from resolve()
function saveResolution (res) {
pkg.name = res.name
pkg.fullname = res.fullname
pkg.version = res.version
pkg.dist = res.dist
Expand Down
1 change: 1 addition & 0 deletions lib/resolve/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = function resolveNpm (pkg) {
.then(res => JSON.parse(res.body))
.then(res => {
return {
name: res.name,
fullname: '' + res.name.replace('/', '!') + '@' + res.version,
version: res.version, // used for displaying
dist: res.dist
Expand Down
14 changes: 14 additions & 0 deletions lib/save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
var thenify = require('thenify')
var fs = require('fs')
var writeFile = thenify(fs.writeFile)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or:

require('mz/fs').writeFile


module.exports = function save (pkg, installedPackages, saveType, useExactVersion) {
var packageJson = pkg.pkg
packageJson[saveType] = packageJson[saveType] || {}
installedPackages.forEach(function (dependency) {
var semverCharacter = useExactVersion ? '' : '^'
packageJson[saveType][dependency.spec.name] = semverCharacter + dependency.version
})

return writeFile(pkg.path, JSON.stringify(packageJson, null, 2), 'utf8')
}
56 changes: 37 additions & 19 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,36 +130,54 @@ test('compiled modules (ursa@0.9.1)', function (t) {
}, t.end)
})

test('tarballs (is-array-1.0.1.tgz)', function (t) {
test('save to package.json (rimraf@2.5.1)', function (t) {
prepare()
install({ input: ['http://registry.npmjs.org/is-array/-/is-array-1.0.1.tgz'], flags: { quiet: true } })
install({ input: ['rimraf@2.5.1'], flags: { quiet: true, save: true } })
.then(function () {
var isArray = require(
join(process.cwd(), 'node_modules', 'is-array'))
var rimraf = require(join(process.cwd(), 'node_modules', 'rimraf'))
t.ok(typeof rimraf === 'function', 'rimraf() is available')

t.ok(isArray, 'isArray() is available')
var pkgJson = fs.readFileSync(join(process.cwd(), 'package.json'), 'utf8')
var dependencies = JSON.parse(pkgJson).dependencies
t.deepEqual(dependencies, {rimraf: '^2.5.1'}, 'rimraf has been added to dependencies')

stat = fs.statSync(
join(process.cwd(), 'node_modules', '.store',
'is-array-1.0.1@a83102a9c117983e6ff4d85311fb322231abe3d6'))
t.ok(stat.isDirectory(), 'stored in the proper location')
t.end()
}, t.end)
})

test('shrinkwrap compatibility', function (t) {
test('saveDev scoped module to package.json (@rstacruz/tap-spec)', function (t) {
prepare()
fs.writeFileSync('package.json',
JSON.stringify({ dependencies: { rimraf: '*' } }),
'utf-8')
install({ input: ['@rstacruz/tap-spec'], flags: { quiet: true, saveDev: true } })
.then(function () {
var tapSpec = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
t.ok(typeof tapSpec === 'function', 'tapSpec() is available')

install({ input: ['rimraf@2.5.1'], flags: { quiet: true } })
var pkgJson = fs.readFileSync(join(process.cwd(), 'package.json'), 'utf8')
var devDependencies = JSON.parse(pkgJson).devDependencies
t.deepEqual(devDependencies, { '@rstacruz/tap-spec': '^4.1.1' }, 'tap-spec has been added to devDependencies')

t.end()
}, t.end)
})

test('multiple save to package.json with `exact` versions (@rstacruz/tap-spec & rimraf@2.5.1)', function (t) {
prepare()
install({ input: ['@rstacruz/tap-spec@latest', 'rimraf@2.5.1'], flags: { quiet: true, save: true, saveExact: true } })
.then(function () {
var npm = JSON.stringify(require.resolve('npm/bin/npm-cli.js'))
require('child_process').execSync('node ' + npm + ' shrinkwrap')
var wrap = JSON.parse(fs.readFileSync('npm-shrinkwrap.json', 'utf-8'))
t.ok(wrap.dependencies.rimraf.version === '2.5.1',
'npm shrinkwrap is successful')
var tapSpec = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
t.ok(typeof tapSpec === 'function', 'tapSpec() is available')

var rimraf = require(join(process.cwd(), 'node_modules', 'rimraf'))
t.ok(typeof rimraf === 'function', 'rimraf() is available')

var pkgJson = fs.readFileSync(join(process.cwd(), 'package.json'), 'utf8')
var dependencies = JSON.parse(pkgJson).dependencies
var expectedDeps = {
rimraf: '2.5.1',
'@rstacruz/tap-spec': '4.1.1'
}
t.deepEqual(dependencies, expectedDeps, 'tap-spec and rimraf have been added to dependencies')

t.end()
}, t.end)
})