list.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. var path = require('path');
  2. var mout = require('mout');
  3. var Q = require('q');
  4. var Project = require('../core/Project');
  5. var semver = require('../util/semver');
  6. var cli = require('../util/cli');
  7. var defaultConfig = require('../config');
  8. function list(logger, options, config) {
  9. var project;
  10. options = options || {};
  11. // Make relative option true by default when used with paths
  12. if (options.paths && options.relative == null) {
  13. options.relative = true;
  14. }
  15. config = defaultConfig(config);
  16. project = new Project(config, logger);
  17. return project.getTree(options)
  18. .spread(function (tree, flattened) {
  19. // Relativize paths
  20. // Also normalize paths on windows
  21. project.walkTree(tree, function (node) {
  22. if (node.missing) {
  23. return;
  24. }
  25. if (options.relative) {
  26. node.canonicalDir = path.relative(config.cwd, node.canonicalDir);
  27. }
  28. if (options.paths) {
  29. node.canonicalDir = normalize(node.canonicalDir);
  30. }
  31. }, true);
  32. // Note that we need to to parse the flattened tree because it might
  33. // contain additional packages
  34. mout.object.forOwn(flattened, function (node) {
  35. if (node.missing) {
  36. return;
  37. }
  38. if (options.relative) {
  39. node.canonicalDir = path.relative(config.cwd, node.canonicalDir);
  40. }
  41. if (options.paths) {
  42. node.canonicalDir = normalize(node.canonicalDir);
  43. }
  44. });
  45. // Render paths?
  46. if (options.paths) {
  47. return paths(flattened);
  48. }
  49. // Do not check for new versions?
  50. if (config.offline) {
  51. return tree;
  52. }
  53. // Check for new versions
  54. return checkVersions(project, tree, logger)
  55. .then(function () {
  56. return tree;
  57. });
  58. });
  59. }
  60. function checkVersions(project, tree, logger) {
  61. var promises;
  62. var nodes = [];
  63. var repository = project.getPackageRepository();
  64. // Gather all nodes, ignoring linked nodes
  65. project.walkTree(tree, function (node) {
  66. if (!node.linked) {
  67. nodes.push(node);
  68. }
  69. }, true);
  70. if (nodes.length) {
  71. logger.info('check-new', 'Checking for new versions of the project dependencies..');
  72. }
  73. // Check for new versions for each node
  74. promises = nodes.map(function (node) {
  75. var target = node.endpoint.target;
  76. return repository.versions(node.endpoint.source)
  77. .then(function (versions) {
  78. node.versions = versions;
  79. // Do not check if node's target is not a valid semver one
  80. if (versions.length && semver.validRange(target)) {
  81. node.update = {
  82. target: semver.maxSatisfying(versions, target),
  83. latest: semver.maxSatisfying(versions, '*')
  84. };
  85. }
  86. });
  87. });
  88. // Set the versions also for the root node
  89. tree.versions = [];
  90. return Q.all(promises);
  91. }
  92. function paths(flattened) {
  93. var ret = {};
  94. mout.object.forOwn(flattened, function (pkg, name) {
  95. var main;
  96. if (pkg.missing) {
  97. return;
  98. }
  99. main = pkg.pkgMeta.main;
  100. // If no main was specified, fallback to canonical dir
  101. if (!main) {
  102. ret[name] = pkg.canonicalDir;
  103. return;
  104. }
  105. // Normalize main
  106. if (typeof main === 'string') {
  107. main = [main];
  108. }
  109. // Concatenate each main entry with the canonical dir
  110. main = main.map(function (part) {
  111. return normalize(path.join(pkg.canonicalDir, part).trim());
  112. });
  113. // If only one main file, use a string
  114. // Otherwise use an array
  115. ret[name] = main.length === 1 ? main[0] : main;
  116. });
  117. return ret;
  118. }
  119. function normalize(src) {
  120. return src.replace(/\\/g, '/');
  121. }
  122. // -------------------
  123. list.line = function (logger, argv) {
  124. var options = list.options(argv);
  125. return list(logger, options);
  126. };
  127. list.options = function (argv) {
  128. return cli.readOptions({
  129. 'paths': { type: Boolean, shorthand: 'p' },
  130. 'relative': { type: Boolean, shorthand: 'r' }
  131. }, argv);
  132. };
  133. list.completion = function () {
  134. // TODO:
  135. };
  136. module.exports = list;