From ec6df96a85cb0dfd2269fbec55db767e275f1a7d Mon Sep 17 00:00:00 2001 From: Mat Scales Date: Fri, 5 Apr 2013 16:56:20 +0100 Subject: [PATCH] Finished switching to bower.json --- bin/bower | 4 ++- lib/commands/install.js | 1 + lib/commands/link.js | 1 + lib/commands/list.js | 1 + lib/commands/uninstall.js | 1 + lib/commands/update.js | 2 ++ lib/core/manager.js | 60 +++++++++++++++++++++++---------------- lib/core/package.js | 38 +++++++++++-------------- lib/util/fallback.js | 32 +++++++++++++++++++++ lib/util/spawn.js | 2 +- test/manager.js | 38 +++++++++++++++++++++++++ test/package.js | 45 +++++++++++++++++++++++++++++ 12 files changed, 177 insertions(+), 48 deletions(-) create mode 100644 lib/util/fallback.js diff --git a/bin/bower b/bin/bower index 1f6ebe0b..58aa1794 100755 --- a/bin/bower +++ b/bin/bower @@ -12,7 +12,6 @@ var command; var options; var shorthand; var input = process.argv; -var cmdList = Object.keys(bower.commands); var nodeVer = process.version; var reqVer = pkg.engines.node; var errors = []; @@ -51,6 +50,9 @@ bower.commands[bower.command || 'help'].line(input) .on('end', function (data) { if (data) process.stdout.write(data); }) + .on('warn', function (warning) { + process.stdout.write(template('warn', { message: warning }, true)); + }) .on('error', function (err) { if (options.verbose) throw err; process.stdout.write(template('error', { message: err.message }, true)); diff --git a/lib/commands/install.js b/lib/commands/install.js index e84e4596..b285b6d1 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -32,6 +32,7 @@ module.exports = function (paths, options) { manager .on('data', emitter.emit.bind(emitter, 'data')) + .on('warn', emitter.emit.bind(emitter, 'warn')) .on('error', emitter.emit.bind(emitter, 'error')) .on('resolve', function (resolved) { // Handle save/save-dev diff --git a/lib/commands/link.js b/lib/commands/link.js index ac705063..d972e91a 100644 --- a/lib/commands/link.js +++ b/lib/commands/link.js @@ -27,6 +27,7 @@ function linkSelf(emitter) { manager .on('error', emitter.emit.bind('error')) + .on('warn', emitter.emit.bind('warn')) .once('loadJSON', function () { var destPath = path.join(config.links, manager.name); var srcPath = process.cwd(); diff --git a/lib/commands/list.js b/lib/commands/list.js index dd61afc1..7d845a31 100644 --- a/lib/commands/list.js +++ b/lib/commands/list.js @@ -187,6 +187,7 @@ module.exports = function (options) { }; manager .on('data', emitter.emit.bind(emitter, 'data')) + .on('warn', emitter.emit.bind(emitter, 'warn')) .on('error', emitter.emit.bind(emitter, 'error')) .on('list', function (packages) { // console.log(packages); diff --git a/lib/commands/uninstall.js b/lib/commands/uninstall.js index 912f5423..a412a41a 100644 --- a/lib/commands/uninstall.js +++ b/lib/commands/uninstall.js @@ -31,6 +31,7 @@ module.exports = function (names, options) { options = options || {}; manager.on('data', emitter.emit.bind(emitter, 'data')); + manager.on('warn', emitter.emit.bind(emitter, 'warn')); manager.on('error', emitter.emit.bind(emitter, 'error')); var resolveLocal = function () { diff --git a/lib/commands/update.js b/lib/commands/update.js index c6757c29..ea7a1351 100644 --- a/lib/commands/update.js +++ b/lib/commands/update.js @@ -29,6 +29,7 @@ module.exports = function (names, options) { }); manager.on('data', emitter.emit.bind(emitter, 'data')); + manager.on('warn', emitter.emit.bind(emitter, 'warn')); manager.on('error', emitter.emit.bind(emitter, 'error')); var installURLS = function (err, arr) { @@ -50,6 +51,7 @@ module.exports = function (names, options) { manager .on('data', emitter.emit.bind(emitter, 'data')) + .on('warn', emitter.emit.bind(emitter, 'warn')) .on('error', emitter.emit.bind(emitter, 'error')) .on('resolve', function (resolved) { // Handle save diff --git a/lib/core/manager.js b/lib/core/manager.js index 03818beb..47cf29b6 100644 --- a/lib/core/manager.js +++ b/lib/core/manager.js @@ -11,6 +11,7 @@ // - resolve: fired when deps resolved (with a true/false indicating success or error) // - error: fired on all errors // - data: fired when trying to output data +// - warn: fired when a discouraged but not fatal situation arises // - end: fired when finished installing // ========================================== @@ -25,7 +26,7 @@ var _ = require('lodash'); var Package = require('./package'); var UnitWork = require('./unit_work'); var config = require('./config'); -var fileExists = require('../util/file-exists'); +var fallback = require('../util/fallback'); var template = require('../util/template'); var prune = require('../util/prune'); @@ -47,30 +48,17 @@ Manager.prototype = Object.create(events.EventEmitter.prototype); Manager.prototype.constructor = Manager; Manager.prototype.loadJSON = function () { - var json = path.join(this.cwd, config.json); - fileExists(json, function (exists) { - if (!exists) { - // If the json does not exist, assume one - this.json = { - name: path.basename(this.cwd), - version: '0.0.0' - }, - this.name = this.json.name; - this.version = this.json.version; - return this.emit('loadJSON'); + fallback(this.cwd, [config.json, 'component.json'], function (file) { + if (file !== null) { + if (file !== config.json) { + this.emit('warn', 'Using deprecated "component.json". Please use "bower.json" instead'); + } + + return this.readJSON(path.join(this.cwd, file)); } - fs.readFile(json, 'utf8', function (err, json) { - if (err) return this.emit('error', err); - try { - this.json = JSON.parse(json); - } catch (e) { - return this.emit('error', new Error('There was an error while reading the ' + config.json + ': ' + e.message)); - } - this.name = this.json.name; - this.version = this.json.version; - this.emit('loadJSON', json.slice(-1) === '\n'); - }.bind(this)); + this.createJSON(); + return this.emit('loadJSON'); }.bind(this)); return this; @@ -178,6 +166,30 @@ Manager.prototype.resolveFromJson = function () { }; // Private +Manager.prototype.createJSON = function () { + // If the json does not exist, assume one + this.json = { + name: path.basename(this.cwd), + version: '0.0.0' + }, + this.name = this.json.name; + this.version = this.json.version; +}; + +Manager.prototype.readJSON = function (filename) { + fs.readFile(filename, 'utf8', function (err, json) { + if (err) return this.emit('error', err); + try { + this.json = JSON.parse(json); + } catch (e) { + return this.emit('error', new Error('There was an error while reading the ' + config.json + ': ' + e.message)); + } + this.name = this.json.name; + this.version = this.json.version; + this.emit('loadJSON', json.slice(-1) === '\n'); + }.bind(this)); +}; + Manager.prototype.getDeepDependencies = function () { var result = {}; @@ -361,4 +373,4 @@ Manager.prototype.getDependencyList = function () { }.bind(this), this.emit.bind(this, 'list', packages)); }; -module.exports = Manager; \ No newline at end of file +module.exports = Manager; diff --git a/lib/core/package.js b/lib/core/package.js index 752c6f85..c161cdcb 100644 --- a/lib/core/package.js +++ b/lib/core/package.js @@ -36,6 +36,7 @@ var source = require('./source'); var template = require('../util/template'); var readJSON = require('../util/read-json'); var fileExists = require('../util/file-exists'); +var fallback = require('../util/fallback'); var isRepo = require('../util/is-repo'); var git = require('../util/git-cmd'); var UnitWork = require('./unit_work'); @@ -117,6 +118,7 @@ var Package = function (name, endpoint, manager) { if (this.manager) { this.on('data', this.manager.emit.bind(this.manager, 'data')); + this.on('warn', this.manager.emit.bind(this.manager, 'warn')); this.on('error', function (err, origin) { // Unlock the unit of work automatically on error (only if the error is from this package) if (!origin && this.unitWork.isLocked(this.cacheName)) this.unitWork.unlock(this.cacheName, this); @@ -318,35 +320,27 @@ Package.prototype.uninstall = function () { }; // Private +Package.prototype.findJSON = function () { + fallback(this.path, [config.json, 'bower.json', 'component.json'], function (name) { + if (name) { + if (name === 'component.json') { + this.emit('warn', 'Package ' + this.name + ' is still using the deprecated "component.json" file'); + } + this.localConfig.json = name; + } + this.emit('readLocalConfig'); + }.bind(this)); +}; + Package.prototype.readLocalConfig = function () { if (this.localConfig) return this.emit('readLocalConfig'); - var checkExistence = function () { - fileExists(path.join(this.path, this.localConfig.json), function (exists) { - if (!exists) { - this.localConfig.json = 'bower.json'; - - // For backwards compatibility with old packages we will fallback to component.json if bower.json does not exist - fileExists(path.join(this.path, this.localConfig.json), function (exists) { - if (!exists) { - this.localConfig.json = 'component.json'; - this.emit('data', template('warn', { message: 'Package ' + this.name + ' is still using the deprecated "component.json" file' }, true)); - } - - this.emit('readLocalConfig'); - }.bind(this)); - } else { - this.emit('readLocalConfig'); - } - }.bind(this)); - }.bind(this); - fs.readFile(path.join(this.path, '.bowerrc'), function (err, file) { // If the local .bowerrc file do not exists then we check if the // json specific in the config exists (if not, we fallback to bower.json) if (err) { this.localConfig = { json: config.json }; - checkExistence(); + this.findJSON(); } else { // If the local .bowerrc file exists, we read it and check if a custom json file // is defined. If not, we check if the global config json file exists (if not, we fallback to bower.json) @@ -358,7 +352,7 @@ Package.prototype.readLocalConfig = function () { if (!this.localConfig.json) { this.localConfig.json = config.json; - return checkExistence(); + return this.findJSON(); } this.emit('readLocalConfig'); diff --git a/lib/util/fallback.js b/lib/util/fallback.js new file mode 100644 index 00000000..e8ba0b92 --- /dev/null +++ b/lib/util/fallback.js @@ -0,0 +1,32 @@ +// ========================================== +// BOWER: fallback +// ========================================== +// Copyright 2012 Twitter, Inc +// Licensed under The MIT License +// http://opensource.org/licenses/MIT +// ========================================== +// A function that takes a list of files and returns the first one that exists +// If none exists, return null + +var fileExists = require('./file-exists'); +var path = require('path'); + +var fallback = function (baseDir, files, callback) { + if (!Array.isArray(files) || files.length === 0) { + return callback(null); + } + + var file = files.shift(); + + fileExists(path.join(baseDir, file), function (exists) { + if (!exists) { + return fallback(baseDir, files, callback); + } else { + return callback(file); + } + }); +}; + +module.exports = fallback; + + diff --git a/lib/util/spawn.js b/lib/util/spawn.js index 28571e2b..d338f2a3 100644 --- a/lib/util/spawn.js +++ b/lib/util/spawn.js @@ -33,4 +33,4 @@ module.exports = function (command, args, options, emitter) { }); return cp; -}; \ No newline at end of file +}; diff --git a/test/manager.js b/test/manager.js index 01c6e35b..c6ce884b 100644 --- a/test/manager.js +++ b/test/manager.js @@ -86,6 +86,44 @@ describe('manager', function () { manager.resolve(); }); + it('Should fallback to component.json if not overriden and bower.json does not exist', function (next) { + var manager = new Manager([]); + manager.cwd = __dirname + '/assets/project-old'; + + manager.on('resolve', function () { + assert.deepEqual(manager.dependencies['jquery-pjax'][0].version, '1.0.0'); + assert.notEqual(manager.dependencies.jquery[0].version, null); + next(); + }); + + manager.on('error', function (err) { + throw err; + }); + + manager.resolve(); + }); + + it('Should emit a warning when falling back to component.json', function (next) { + var manager = new Manager([]); + var warning = ''; + manager.cwd = __dirname + '/assets/project-old'; + + manager.on('resolve', function () { + assert(/deprecated "component.json"/.test(warning)); + next(); + }); + + manager.on('warn', function (message) { + warning = message; + }); + + manager.on('error', function (err) { + throw err; + }); + + manager.resolve(); + }); + it('Should override packages at the project level', function (next) { var manager = new Manager([]); manager.cwd = __dirname + '/assets/project-static'; diff --git a/test/package.js b/test/package.js index 0c08b082..c4dc855b 100644 --- a/test/package.js +++ b/test/package.js @@ -630,4 +630,49 @@ describe('package', function () { pkg.resolve(); }); + + it('Should display a warning if a dependency is using the old component.json file', function (next) { + var pkg = new Package('project', __dirname + '/assets/project'); + var warn = []; + + pkg.on('resolve', function () { + // jQuery will get resolved twice as it is a dependency of both explicit dependencies. + assert.equal(warn.length, 4); + next(); + }); + + pkg.on('warn', function (message) { + if (/deprecated "component.json"/.test(message)) { + warn.push(message); + } + }); + + pkg.on('error', function (err) { + throw err; + }); + + pkg.resolve(); + }); + + it('Should not display a warning for dependencies using the new bower.json file', function (next) { + var pkg = new Package('project-new-deps', __dirname + '/assets/project-new-deps'); + var warn = []; + + pkg.on('resolve', function () { + assert.equal(warn.length, 0); + next(); + }); + + pkg.on('warn', function (message) { + if (/deprecated "component.json"/.test(message)) { + warn.push(message); + } + }); + + pkg.on('error', function (err) { + throw err; + }); + + pkg.resolve(); + }); });