find-prefix.js 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. 'use strict';
  2. var fs = require('fs');
  3. var path = require('path');
  4. module.exports = function (options, cb) {
  5. return findPrefix(options.cwd, options.isSync, cb);
  6. };
  7. function readdir(p, isSync, fn) {
  8. var val = null;
  9. if (isSync) {
  10. try {
  11. val = fs.readdirSync(p);
  12. } catch (err) {
  13. return fn(err);
  14. }
  15. return fn(null, val);
  16. }
  17. return fs.readdir(p, fn);
  18. }
  19. // try to find the most reasonable prefix to use
  20. function findPrefix(p, isSync, cb_) {
  21. function cb(err, p) {
  22. if (isSync) return cb_(err, p);
  23. process.nextTick(function () {
  24. cb_(err, p);
  25. });
  26. }
  27. p = path.resolve(p);
  28. // if there's no node_modules folder, then
  29. // walk up until we hopefully find one.
  30. // if none anywhere, then use cwd.
  31. var walkedUp = false;
  32. while (path.basename(p) === 'node_modules') {
  33. p = path.dirname(p);
  34. walkedUp = true;
  35. }
  36. if (walkedUp) return cb(null, p);
  37. findPrefix_(p, p, isSync, cb);
  38. }
  39. function findPrefix_(p, original, isSync, cb) {
  40. if (p === '/' || process.platform === 'win32' && p.match(/^[a-zA-Z]:(\\|\/)?$/)) {
  41. return cb(null, original);
  42. }
  43. readdir(p, isSync, function (err, files) {
  44. // an error right away is a bad sign.
  45. // unless the prefix was simply a non
  46. // existent directory.
  47. if (err && p === original) {
  48. if (err.code === 'ENOENT') return cb(null, original);
  49. return cb(err);
  50. }
  51. // walked up too high or something.
  52. if (err) return cb(null, original);
  53. if (files.indexOf('node_modules') !== -1 || files.indexOf('package.json') !== -1) {
  54. return cb(null, p);
  55. }
  56. var d = path.dirname(p);
  57. if (d === p) return cb(null, original);
  58. return findPrefix_(d, original, isSync, cb);
  59. });
  60. }