mirror of
https://github.com/bower/bower.git
synced 2026-04-24 03:00:19 -04:00
Uninstall now removes also nested deps if not shared.
The uninstall now warns and halts uninstalling shared packages. Though it can be forced with the --force flag. Also fix CS, and fix small bug.
This commit is contained in:
@@ -27,7 +27,7 @@ module.exports = function (paths, options) {
|
||||
var emitter = new Emitter;
|
||||
var manager = new Manager(paths, { force: options && options.force });
|
||||
|
||||
if (options && options.save) save(emitter, manager, paths);
|
||||
if (options && options.save) save(manager, paths);
|
||||
|
||||
manager
|
||||
.on('data' , emitter.emit.bind(emitter, 'data'))
|
||||
|
||||
@@ -47,11 +47,11 @@ var getTree = function (packages, subPackages, result) {
|
||||
};
|
||||
|
||||
var generatePath = function (name, main) {
|
||||
if (typeof main == 'string') {
|
||||
if (typeof main === 'string') {
|
||||
return path.join(config.directory, name, main);
|
||||
} else if (_.isArray(main)) {
|
||||
main = main.map(function (main) { return generatePath(name, main); });
|
||||
return main.length == 1 ? main[0] : main;
|
||||
return main.length === 1 ? main[0] : main;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,7 +149,7 @@ module.exports = function (options) {
|
||||
|
||||
async.forEach(_.values(packages), function (pkg, next) {
|
||||
pkg.once('loadJSON', function () {
|
||||
if (this.json.repository && (this.json.repository.type == 'git' || this.json.repository.type == 'local-repo')) {
|
||||
if (this.json.repository && (this.json.repository.type === 'git' || this.json.repository.type === 'local-repo')) {
|
||||
pkg.once('versions', function (versions) {
|
||||
pkg.tags = versions.map(function (ver) {
|
||||
return semver.valid(ver) ? semver.clean(ver) : ver;
|
||||
|
||||
@@ -9,67 +9,131 @@
|
||||
var Emitter = require('events').EventEmitter;
|
||||
var async = require('async');
|
||||
var nopt = require('nopt');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var _ = require('lodash');
|
||||
|
||||
var template = require('../util/template');
|
||||
var Manager = require('../core/manager');
|
||||
var save = require('../util/save');
|
||||
var config = require('../core/config');
|
||||
var help = require('./help');
|
||||
|
||||
var shorthand = { 'h': ['--help'], 'S': ['--save'] };
|
||||
var optionTypes = { help: Boolean };
|
||||
var optionTypes = { help: Boolean, force: Boolean };
|
||||
var shorthand = { 'h': ['--help'], 'S': ['--save'], 'f': ['--force'] };
|
||||
|
||||
module.exports = function (names, options) {
|
||||
|
||||
var packages, uninstallables;
|
||||
var packages, uninstallables, packagesCount = {};
|
||||
var emitter = new Emitter;
|
||||
var manager = new Manager;
|
||||
|
||||
// TODO: only deletect on conflict if force is true
|
||||
// TODO: delete nested deps
|
||||
if (options.save) save.discard(emitter, manager, names);
|
||||
var force = !!options.force;
|
||||
|
||||
manager.on('data', emitter.emit.bind(emitter, 'data'));
|
||||
manager.on('error', emitter.emit.bind(emitter, 'error'));
|
||||
|
||||
var resolveLocal = function () {
|
||||
packages = _.flatten(_.values(manager.dependencies));
|
||||
|
||||
uninstallables = packages.filter(function (pkg) {
|
||||
return _.include(names, pkg.name);
|
||||
});
|
||||
|
||||
async.forEach(packages, function (pkg, next) {
|
||||
pkg.once('loadJSON', next).loadJSON();
|
||||
}, function () {
|
||||
showWarnings();
|
||||
if (showWarnings(force) && !force) return;
|
||||
includeShared();
|
||||
uninstall();
|
||||
});
|
||||
};
|
||||
|
||||
var showWarnings = function () {
|
||||
var showWarnings = function (force) {
|
||||
var foundConflicts = false;
|
||||
|
||||
packages.forEach(function (pkg) {
|
||||
if (!pkg.json.dependencies) return;
|
||||
if (uninstallables.indexOf(pkg) !== -1) return;
|
||||
|
||||
var conflicts = _.intersection(
|
||||
Object.keys(pkg.json.dependencies),
|
||||
_.pluck(uninstallables, 'name')
|
||||
);
|
||||
|
||||
conflicts.forEach(function (conflictName) {
|
||||
template('warning-uninstall', {packageName: pkg.name, conflictName: conflictName})
|
||||
.on('data', emitter.emit.bind(emitter, 'data'));
|
||||
});
|
||||
if (conflicts.length) {
|
||||
foundConflicts = true;
|
||||
if (!force) {
|
||||
conflicts.forEach(function (conflictName) {
|
||||
emitter.emit('data', template('warning-uninstall', { packageName: pkg.name, conflictName: conflictName }, true));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (foundConflicts && !force) {
|
||||
emitter.emit('data', template('warn', { message: 'To proceed, run uninstall with the --force flag'}, true));
|
||||
}
|
||||
|
||||
return foundConflicts;
|
||||
};
|
||||
|
||||
var includeShared = function () {
|
||||
count(packages, packagesCount);
|
||||
|
||||
uninstallables.forEach(function (pkg) {
|
||||
parseUninstallableDeps(pkg);
|
||||
});
|
||||
|
||||
for (var name in packagesCount) {
|
||||
var pkg = manager.dependencies[name][0];
|
||||
if ((!packagesCount[name] || (packagesCount[name] === 1 && !manager.json.dependencies[name]))
|
||||
&& uninstallables.indexOf(pkg) === -1) {
|
||||
if (packagesCount[name] > 0) packagesCount[name] -= 1;
|
||||
uninstallables.push(pkg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var count = function (packages, counts) {
|
||||
packages.forEach(function (pkg) {
|
||||
counts[pkg.name] = (counts[pkg.name] || 0) + 1;
|
||||
|
||||
if (pkg.json.dependencies) {
|
||||
for (var key in pkg.json.dependencies) {
|
||||
count(manager.dependencies[key], counts);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var parseUninstallableDeps = function (pkg) {
|
||||
if (packagesCount[pkg.name] > 0) packagesCount[pkg.name] -= 1;
|
||||
|
||||
if (pkg.json.dependencies) {
|
||||
for (var key in pkg.json.dependencies) {
|
||||
parseUninstallableDeps(manager.dependencies[key][0]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var uninstall = function () {
|
||||
async.forEach(uninstallables, function (pkg, next) {
|
||||
pkg.on('uninstall', next).uninstall();
|
||||
}, emitter.emit.bind(emitter, 'end'));
|
||||
}, function () {
|
||||
// Finally save
|
||||
if (options.save) save();
|
||||
emitter.emit.bind(emitter, 'end');
|
||||
});
|
||||
};
|
||||
|
||||
manager.on('resolveLocal', resolveLocal).resolveLocal();
|
||||
var save = function () {
|
||||
names.forEach(function (name) {
|
||||
delete manager.json.dependencies[name];
|
||||
});
|
||||
|
||||
fs.writeFileSync(path.join(manager.cwd, config.json), JSON.stringify(manager.json, null, 2));
|
||||
};
|
||||
|
||||
manager.on('loadJSON', function () {
|
||||
manager.on('resolveLocal', resolveLocal).resolveLocal();
|
||||
}).loadJSON();
|
||||
|
||||
return emitter;
|
||||
};
|
||||
@@ -78,7 +142,7 @@ module.exports.line = function (argv) {
|
||||
var options = nopt(optionTypes, shorthand, argv);
|
||||
|
||||
if (options.help) return help('uninstall');
|
||||
var names = options.argv.remain.slice(1);
|
||||
var names = options.argv.remain.slice(1);
|
||||
|
||||
return module.exports(names, options);
|
||||
};
|
||||
@@ -84,7 +84,6 @@ var Package = function (name, endpoint, manager) {
|
||||
this.tag = split[1];
|
||||
} else {
|
||||
split = endpoint.split('#', 2);
|
||||
this.name = split[0];
|
||||
this.tag = split[1];
|
||||
}
|
||||
|
||||
@@ -93,6 +92,7 @@ var Package = function (name, endpoint, manager) {
|
||||
if (this.gitUrl) this.name = path.basename(endpoint).replace(/(\.git)?(#.*)?$/, '');
|
||||
else if (this.path) this.name = path.basename(this.path, this.assetType);
|
||||
else if (this.assetUrl) this.name = this.name = path.basename(this.assetUrl, this.assetType);
|
||||
else if (split) this.name = split[0];
|
||||
}
|
||||
|
||||
// Store a reference to the original tag & original path
|
||||
@@ -171,7 +171,7 @@ Package.prototype.install = function () {
|
||||
.on('data', this.emit.bind(this, 'data'));
|
||||
}
|
||||
|
||||
if (path.resolve(this.path) == this.localPath) {
|
||||
if (path.resolve(this.path) === this.localPath) {
|
||||
this.emit('install');
|
||||
return this;
|
||||
}
|
||||
@@ -232,7 +232,7 @@ Package.prototype.uninstall = function () {
|
||||
.on('data', this.emit.bind(this, 'data'));
|
||||
rimraf(this.path, function (err) {
|
||||
if (err) return this.emit('error', err);
|
||||
this.emit.bind(this, 'uninstall');
|
||||
this.emit('uninstall');
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
@@ -325,7 +325,7 @@ Package.prototype.download = function () {
|
||||
this.once('loadJSON', this.saveUnit).loadJSON();
|
||||
}.bind(this);
|
||||
|
||||
if (this.assetType === '.zip' || this.assetType == '.tar') this.once('extract', next).extract();
|
||||
if (this.assetType === '.zip' || this.assetType === '.tar') this.once('extract', next).extract();
|
||||
else next();
|
||||
}.bind(this));
|
||||
|
||||
@@ -624,26 +624,26 @@ Package.prototype.fetchEndpoint = function () {
|
||||
Package.prototype.readEndpoint = function (replace) {
|
||||
if (!this.json.repository) return;
|
||||
|
||||
if (this.json.repository.type == 'git') {
|
||||
if (this.json.repository.type === 'git') {
|
||||
if (replace || !this.gitUrl) {
|
||||
this.gitUrl = this.json.repository.url;
|
||||
this.generateResourceId();
|
||||
}
|
||||
return { type: 'git', endpoint: this.gitUrl };
|
||||
}
|
||||
if (this.json.repository.type == 'local-repo') {
|
||||
if (this.json.repository.type === 'local-repo') {
|
||||
if (replace || !this.gitPath) {
|
||||
this.gitPath = path.resolve(this.json.repository.path);
|
||||
}
|
||||
return { type: 'local', endpoint: this.path };
|
||||
}
|
||||
if (this.json.repository.type == 'local') {
|
||||
if (this.json.repository.type === 'local') {
|
||||
if (replace || !this.path) {
|
||||
this.path = path.resolve(this.json.repository.path);
|
||||
}
|
||||
return { type: 'local', endpoint: this.path };
|
||||
}
|
||||
if (this.json.repository.type == 'asset') {
|
||||
if (this.json.repository.type === 'asset') {
|
||||
if (replace || !this.assetUrl) {
|
||||
this.assetUrl = this.json.repository.url;
|
||||
this.assetType = path.extname(this.assetUrl);
|
||||
|
||||
@@ -13,7 +13,7 @@ var _ = require('lodash');
|
||||
|
||||
var config = require('../core/config');
|
||||
|
||||
function save(eventType, modifier, emitter, manager, paths) {
|
||||
function save(eventType, modifier, manager, paths) {
|
||||
// Tipically wait for the resolve event and also the load json event
|
||||
manager.on(eventType, manager.on('loadJSON', function () {
|
||||
// Find the original required packages in the command
|
||||
@@ -22,9 +22,9 @@ function save(eventType, modifier, emitter, manager, paths) {
|
||||
|
||||
return _.find(Object.keys(this.dependencies), function (key) {
|
||||
var dep = this.dependencies[key][0];
|
||||
return dep.name == curr
|
||||
|| (dep.url && dep.url == curr)
|
||||
|| (dep.originalPath && dep.originalPath == curr);
|
||||
return dep.name === curr
|
||||
|| (dep.url && dep.url === curr)
|
||||
|| (dep.originalPath && dep.originalPath === curr);
|
||||
}.bind(this));
|
||||
|
||||
}.bind(this));
|
||||
@@ -33,8 +33,7 @@ function save(eventType, modifier, emitter, manager, paths) {
|
||||
return this.dependencies[name][0];
|
||||
}.bind(this));
|
||||
|
||||
// The modifier can be addDependency or removeDependency
|
||||
pkgs.forEach(modifier.bind(this));
|
||||
pkgs.forEach(addDependency.bind(this));
|
||||
|
||||
// Finally save the modified json
|
||||
fs.writeFileSync(path.join(this.cwd, config.json), JSON.stringify(this.json, null, 2));
|
||||
@@ -61,9 +60,4 @@ function addDependency(pkg) {
|
||||
return this.json.dependencies[pkg.name] = path ? path + (tag ? '#' + tag : '') : tag || 'latest';
|
||||
}
|
||||
|
||||
function removeDependency(pkg) {
|
||||
delete this.json.dependencies[pkg.name];
|
||||
}
|
||||
|
||||
module.exports = save.bind(this, 'resolve', addDependency);
|
||||
module.exports.discard = save.bind(this, 'resolveLocal', removeDependency);
|
||||
module.exports = save.bind(this, 'resolve', addDependency);
|
||||
@@ -1 +1 @@
|
||||
{{#yellow}}warn{{/yellow}} {{name}} {{#grey}}{{shizzle}}{{/grey}}
|
||||
bower {{#yellow}}warn{{/yellow}} {{#grey}}{{message}}{{/grey}}
|
||||
@@ -1 +1 @@
|
||||
{{#yellow}}warning{{/yellow}} {{#cyan}}{{packageName}}{{/cyan}} depends on {{#grey}}{{conflictName}}{{/grey}}
|
||||
{{#red}}conflict{{/red}} {{#cyan}}{{packageName}}{{/cyan}} depends on {{#grey}}{{conflictName}}{{/grey}}
|
||||
Reference in New Issue
Block a user