uninstall.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. var mout = require('mout');
  2. var Q = require('q');
  3. var Project = require('../core/Project');
  4. var cli = require('../util/cli');
  5. var Tracker = require('../util/analytics').Tracker;
  6. var defaultConfig = require('../config');
  7. function uninstall(logger, names, options, config) {
  8. var project;
  9. var tracker;
  10. options = options || {};
  11. config = defaultConfig(config);
  12. project = new Project(config, logger);
  13. tracker = new Tracker(config);
  14. tracker.trackNames('uninstall', names);
  15. return project.getTree(options)
  16. .spread(function (tree, flattened) {
  17. // Uninstall nodes
  18. return project.uninstall(names, options)
  19. // Clean out non-shared uninstalled dependencies
  20. .then(function (uninstalled) {
  21. var names = Object.keys(uninstalled);
  22. var children = [];
  23. // Grab the dependencies of packages that were uninstalled
  24. mout.object.forOwn(flattened, function (node) {
  25. if (names.indexOf(node.endpoint.name) !== -1) {
  26. children.push.apply(children, mout.object.keys(node.dependencies));
  27. }
  28. });
  29. // Clean them!
  30. return clean(project, children, uninstalled);
  31. });
  32. });
  33. }
  34. function clean(project, names, removed) {
  35. removed = removed || {};
  36. return project.getTree()
  37. .spread(function (tree, flattened) {
  38. var nodes = [];
  39. var dependantsCounter = {};
  40. // Grab the nodes of each specified name
  41. mout.object.forOwn(flattened, function (node) {
  42. if (names.indexOf(node.endpoint.name) !== -1) {
  43. nodes.push(node);
  44. }
  45. });
  46. // Walk the down the tree, gathering dependants of the packages
  47. project.walkTree(tree, function (node, nodeName) {
  48. if (names.indexOf(nodeName) !== -1) {
  49. dependantsCounter[nodeName] = dependantsCounter[nodeName] || 0;
  50. dependantsCounter[nodeName] += node.nrDependants;
  51. }
  52. }, true);
  53. // Filter out those that have no dependants
  54. nodes = nodes.filter(function (node) {
  55. return !dependantsCounter[node.endpoint.name];
  56. });
  57. // Are we done?
  58. if (!nodes.length) {
  59. return Q.resolve(removed);
  60. }
  61. // Grab the nodes after filtering
  62. names = nodes.map(function (node) {
  63. return node.endpoint.name;
  64. });
  65. // Uninstall them
  66. return project.uninstall(names)
  67. // Clean out non-shared uninstalled dependencies
  68. .then(function (uninstalled) {
  69. var children;
  70. mout.object.mixIn(removed, uninstalled);
  71. // Grab the dependencies of packages that were uninstalled
  72. children = [];
  73. nodes.forEach(function (node) {
  74. children.push.apply(children, mout.object.keys(node.dependencies));
  75. });
  76. // Recurse!
  77. return clean(project, children, removed);
  78. });
  79. });
  80. }
  81. // -------------------
  82. uninstall.line = function (logger, argv) {
  83. var options = uninstall.options(argv);
  84. var names = options.argv.remain.slice(1);
  85. if (!names.length) {
  86. return new Q();
  87. } else {
  88. return uninstall(logger, names, options);
  89. }
  90. };
  91. uninstall.options = function (argv) {
  92. return cli.readOptions({
  93. 'save': { type: Boolean, shorthand: 'S' },
  94. 'save-dev': { type: Boolean, shorthand: 'D' }
  95. }, argv);
  96. };
  97. uninstall.completion = function () {
  98. // TODO:
  99. };
  100. module.exports = uninstall;