From 02f6d1a9f4d51311c78d114dc64c2af1bdca116c Mon Sep 17 00:00:00 2001 From: Rowan Crawford Date: Mon, 17 Dec 2012 20:56:04 +1300 Subject: [PATCH 1/6] Implement npm install foo --save equivalent Update package.json's jam.dependencies or jam.devDependencies if --save or --save-dev passed --- lib/commands/install.js | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/commands/install.js b/lib/commands/install.js index 67cffe7..4a86bb1 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -69,7 +69,9 @@ exports.run = function (settings, args) { var a = argParse(args, { 'repository': {match: ['-r', '--repository'], value: true}, 'target_dir': {match: ['-d', '--package-dir'], value: true}, - 'baseurl': {match: ['-b', '--baseurl'], value: true} + 'baseurl': {match: ['-b', '--baseurl'], value: true}, + 'save': {match: ['-S', '--save'], value: false}, + 'save_dev': {match: ['-D', '--save-dev'], value: false} }); var opt = a.options; @@ -159,7 +161,6 @@ exports.reinstallPackages = function (cfg, opt, callback) { if (err) { return logger.error(err); } - // TODO: write package.json if --save option provided project.updateRequireConfig(opt.target_dir, opt.baseurl, function (err) { if (err) { @@ -187,7 +188,6 @@ exports.installPackages = function (cfg, names, opt, callback) { if (err) { return callback(err); } - // TODO: write package.json if --save option provided project.updateRequireConfig(opt.target_dir, opt.baseurl, callback); }); }; @@ -406,7 +406,34 @@ exports.installRepo = function (name, range, opt, callback) { if (err) { return callback(err); } - exports.cpDir(name, v, from_cache, cdir, opt, callback); + if (opt.save || opt.save_dev) { + exports.cpDir(name, v, from_cache, cdir, opt, function() { + fs.readFile('package.json', function(err, data) { + var deps = opt.save ? 'dependencies' : 'devDependencies'; + + try { + data = JSON.parse(data.toString('utf8')); + } catch(e) { + err = e; + } + if (err) { + return callback(); + } + if (!data.jam) { + data.jam = {}; + } + data.jam[deps] = data.jam[deps] || {}; + data.jam[deps][name] = v; + + data = JSON.stringify(data, null, 2) + '\n'; + fs.writeFile('package.json', data, function(err) { + callback(err); + }); + }); + }); + } else { + exports.cpDir(name, v, from_cache, cdir, opt, callback); + } } ); }; From 3d54c9414902147736ae565770659dee0dcc0d7d Mon Sep 17 00:00:00 2001 From: Rowan Crawford Date: Tue, 18 Dec 2012 12:02:02 +1300 Subject: [PATCH 2/6] Remove save-dev and all for running from any directory. --- lib/commands/install.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/commands/install.js b/lib/commands/install.js index 4a86bb1..37c195a 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -70,8 +70,7 @@ exports.run = function (settings, args) { 'repository': {match: ['-r', '--repository'], value: true}, 'target_dir': {match: ['-d', '--package-dir'], value: true}, 'baseurl': {match: ['-b', '--baseurl'], value: true}, - 'save': {match: ['-S', '--save'], value: false}, - 'save_dev': {match: ['-D', '--save-dev'], value: false} + 'save': {match: ['-S', '--save'], value: false} }); var opt = a.options; @@ -119,6 +118,8 @@ exports.run = function (settings, args) { exports.extendOptions = function (proj_dir, settings, cfg, opt) { + opt.proj_dir = proj_dir; + if (!opt.target_dir) { if (cfg.jam && cfg.jam.packageDir) { opt.target_dir = path.resolve(proj_dir, cfg.jam.packageDir); @@ -406,11 +407,11 @@ exports.installRepo = function (name, range, opt, callback) { if (err) { return callback(err); } - if (opt.save || opt.save_dev) { + if (opt.save) { exports.cpDir(name, v, from_cache, cdir, opt, function() { - fs.readFile('package.json', function(err, data) { - var deps = opt.save ? 'dependencies' : 'devDependencies'; + var package = path.resolve(opt.proj_dir, 'package.json'); + fs.readFile(path.resolve(package), function(err, data) { try { data = JSON.parse(data.toString('utf8')); } catch(e) { @@ -422,11 +423,11 @@ exports.installRepo = function (name, range, opt, callback) { if (!data.jam) { data.jam = {}; } - data.jam[deps] = data.jam[deps] || {}; - data.jam[deps][name] = v; + data.jam.dependencies = data.jam.dependencies || {}; + data.jam.dependencies[name] = v; data = JSON.stringify(data, null, 2) + '\n'; - fs.writeFile('package.json', data, function(err) { + fs.writeFile(package, data, function(err) { callback(err); }); }); From 3470920124256a194e7743332ea17724038aa0e4 Mon Sep 17 00:00:00 2001 From: Rowan Crawford Date: Tue, 18 Dec 2012 12:25:44 +1300 Subject: [PATCH 3/6] Add test to scripts property --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 4c553e7..40f7900 100644 --- a/package.json +++ b/package.json @@ -34,5 +34,8 @@ "bugs": {"url": "http://github.com/caolan/jam/issues"}, "bin": { "jam": "./bin/jam.js" + }, + "scripts": { + "test": "test/all.sh" } } From 9df9888ad21f955668e45c0f092a0b90fb85a679 Mon Sep 17 00:00:00 2001 From: Rowan Crawford Date: Tue, 18 Dec 2012 12:26:02 +1300 Subject: [PATCH 4/6] Add integration test for install --save --- test/integration/test-install-save.js | 116 ++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 test/integration/test-install-save.js diff --git a/test/integration/test-install-save.js b/test/integration/test-install-save.js new file mode 100644 index 0000000..b0e473c --- /dev/null +++ b/test/integration/test-install-save.js @@ -0,0 +1,116 @@ +/** + * Test description + * ================ + * + * Tests that jam install --save adds to package.json + * + * Starting with project with *ranged* deps in package.json + * - jam publish package-one @ 0.0.1 + * - jam publish package-two @ 0.0.1 + * - jam install package-one --save, test package.json updated + */ + + +var couchdb = require('../../lib/couchdb'), + logger = require('../../lib/logger'), + env = require('../../lib/env'), + utils = require('../utils'), + async = require('async'), + http = require('http'), + path = require('path'), + ncp = require('ncp').ncp, + fs = require('fs'), + _ = require('underscore'); + + +var pathExists = fs.exists || path.exists; + + +logger.clean_exit = true; + +// CouchDB database URL to use for testing +var TESTDB = process.env['JAM_TEST_DB'], + BIN = path.resolve(__dirname, '../../bin/jam.js'), + ENV = {JAM_TEST: 'true', JAM_TEST_DB: TESTDB}; + +if (!TESTDB) { + throw 'JAM_TEST_DB environment variable not set'; +} + +// remove trailing-slash from TESTDB URL +TESTDB = TESTDB.replace(/\/$/, ''); + + +exports.setUp = function (callback) { + // change to integration test directory before running test + this._cwd = process.cwd(); + process.chdir(__dirname); + + // recreate any existing test db + couchdb(TESTDB).deleteDB(function (err) { + if (err && err.error !== 'not_found') { + return callback(err); + } + // create test db + couchdb(TESTDB).createDB(callback); + }); +}; + +exports.tearDown = function (callback) { + // change back to original working directory after running test + process.chdir(this._cwd); + // delete test db + couchdb(TESTDB).deleteDB(callback); +}; + + +exports['project with ranged dependencies in package.json'] = { + + setUp: function (callback) { + this.project_dir = path.resolve(env.temp, 'jamtest-' + Math.random()); + // set current project to empty directory + ncp('./fixtures/project-rangedeps', this.project_dir, callback); + }, + + /* + tearDown: function (callback) { + var that = this; + // clear current project + //utils.myrimraf(that.project_dir, callback); + }, + */ + + 'publish, install, ls, remove': function (test) { + test.expect(1); + var that = this; + process.chdir(that.project_dir); + + async.series([ + async.apply( + utils.runJam, + ['publish', path.resolve(__dirname, 'fixtures', 'package-one')], + {env: ENV} + ), + async.apply( + utils.runJam, + ['publish', path.resolve(__dirname, 'fixtures', 'package-two')], + {env: ENV} + ), + async.apply(utils.runJam, ['install', 'package-one', '--save'], {env: ENV}), + function (cb) { + fs.readFile(path.resolve(that.project_dir, 'package.json'), function(err, data) { + data = JSON.parse(data); + + test.same(data.jam.dependencies, { + "package-one": "0.0.1", + "package-two": "<=0.0.2" + }); + cb(); + }); + } + ], + test.done); + } + +}; + From ff8288a1fc3a5e2e7421fc89dfd4d4be0caa1432 Mon Sep 17 00:00:00 2001 From: Rowan Crawford Date: Tue, 23 Apr 2013 12:59:13 +1200 Subject: [PATCH 5/6] Handle error for cpDir --- lib/commands/install.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/commands/install.js b/lib/commands/install.js index 37c195a..4de9cd0 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -408,8 +408,14 @@ exports.installRepo = function (name, range, opt, callback) { return callback(err); } if (opt.save) { - exports.cpDir(name, v, from_cache, cdir, opt, function() { - var package = path.resolve(opt.proj_dir, 'package.json'); + exports.cpDir(name, v, from_cache, cdir, opt, function(err) { + var package; + + if (err) { + return callback(err); + } + + package = path.resolve(opt.proj_dir, 'package.json'); fs.readFile(path.resolve(package), function(err, data) { try { From 2a60f0239e669fad05b0d8af1cf880533b3b7fed Mon Sep 17 00:00:00 2001 From: Rowan Crawford Date: Fri, 12 Jul 2013 15:38:58 +1200 Subject: [PATCH 6/6] Handle dependencies being at top level --- lib/commands/install.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/commands/install.js b/lib/commands/install.js index 4de9cd0..ff5938d 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -426,11 +426,16 @@ exports.installRepo = function (name, range, opt, callback) { if (err) { return callback(); } - if (!data.jam) { + if (!data.dependencies && !data.jam) { data.jam = {}; } - data.jam.dependencies = data.jam.dependencies || {}; - data.jam.dependencies[name] = v; + // if jam namespace exists + if (data.jam) { + data.jam.dependencies = data.jam.dependencies || {}; + data.jam.dependencies[name] = v; + } else { + data.dependencies[name] = v; + } data = JSON.stringify(data, null, 2) + '\n'; fs.writeFile(package, data, function(err) {