common.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. exports.alphasort = alphasort
  2. exports.alphasorti = alphasorti
  3. exports.setopts = setopts
  4. exports.ownProp = ownProp
  5. exports.makeAbs = makeAbs
  6. exports.finish = finish
  7. exports.mark = mark
  8. exports.isIgnored = isIgnored
  9. exports.childrenIgnored = childrenIgnored
  10. function ownProp (obj, field) {
  11. return Object.prototype.hasOwnProperty.call(obj, field)
  12. }
  13. var path = require("path")
  14. var minimatch = require("minimatch")
  15. var isAbsolute = require("path-is-absolute")
  16. var Minimatch = minimatch.Minimatch
  17. function alphasorti (a, b) {
  18. return a.toLowerCase().localeCompare(b.toLowerCase())
  19. }
  20. function alphasort (a, b) {
  21. return a.localeCompare(b)
  22. }
  23. function setupIgnores (self, options) {
  24. self.ignore = options.ignore || []
  25. if (!Array.isArray(self.ignore))
  26. self.ignore = [self.ignore]
  27. if (self.ignore.length) {
  28. self.ignore = self.ignore.map(ignoreMap)
  29. }
  30. }
  31. function ignoreMap (pattern) {
  32. var gmatcher = null
  33. if (pattern.slice(-3) === '/**') {
  34. var gpattern = pattern.replace(/(\/\*\*)+$/, '')
  35. gmatcher = new Minimatch(gpattern)
  36. }
  37. return {
  38. matcher: new Minimatch(pattern),
  39. gmatcher: gmatcher
  40. }
  41. }
  42. function setopts (self, pattern, options) {
  43. if (!options)
  44. options = {}
  45. // base-matching: just use globstar for that.
  46. if (options.matchBase && -1 === pattern.indexOf("/")) {
  47. if (options.noglobstar) {
  48. throw new Error("base matching requires globstar")
  49. }
  50. pattern = "**/" + pattern
  51. }
  52. self.silent = !!options.silent
  53. self.pattern = pattern
  54. self.strict = options.strict !== false
  55. self.realpath = !!options.realpath
  56. self.realpathCache = options.realpathCache || Object.create(null)
  57. self.follow = !!options.follow
  58. self.dot = !!options.dot
  59. self.mark = !!options.mark
  60. self.nodir = !!options.nodir
  61. if (self.nodir)
  62. self.mark = true
  63. self.sync = !!options.sync
  64. self.nounique = !!options.nounique
  65. self.nonull = !!options.nonull
  66. self.nosort = !!options.nosort
  67. self.nocase = !!options.nocase
  68. self.stat = !!options.stat
  69. self.noprocess = !!options.noprocess
  70. self.maxLength = options.maxLength || Infinity
  71. self.cache = options.cache || Object.create(null)
  72. self.statCache = options.statCache || Object.create(null)
  73. self.symlinks = options.symlinks || Object.create(null)
  74. setupIgnores(self, options)
  75. self.changedCwd = false
  76. var cwd = process.cwd()
  77. if (!ownProp(options, "cwd"))
  78. self.cwd = cwd
  79. else {
  80. self.cwd = options.cwd
  81. self.changedCwd = path.resolve(options.cwd) !== cwd
  82. }
  83. self.root = options.root || path.resolve(self.cwd, "/")
  84. self.root = path.resolve(self.root)
  85. if (process.platform === "win32")
  86. self.root = self.root.replace(/\\/g, "/")
  87. self.nomount = !!options.nomount
  88. // disable comments and negation unless the user explicitly
  89. // passes in false as the option.
  90. options.nonegate = options.nonegate === false ? false : true
  91. options.nocomment = options.nocomment === false ? false : true
  92. deprecationWarning(options)
  93. self.minimatch = new Minimatch(pattern, options)
  94. self.options = self.minimatch.options
  95. }
  96. // TODO(isaacs): remove entirely in v6
  97. // exported to reset in tests
  98. exports.deprecationWarned
  99. function deprecationWarning(options) {
  100. if (!options.nonegate || !options.nocomment) {
  101. if (process.noDeprecation !== true && !exports.deprecationWarned) {
  102. var msg = 'glob WARNING: comments and negation will be disabled in v6'
  103. if (process.throwDeprecation)
  104. throw new Error(msg)
  105. else if (process.traceDeprecation)
  106. console.trace(msg)
  107. else
  108. console.error(msg)
  109. exports.deprecationWarned = true
  110. }
  111. }
  112. }
  113. function finish (self) {
  114. var nou = self.nounique
  115. var all = nou ? [] : Object.create(null)
  116. for (var i = 0, l = self.matches.length; i < l; i ++) {
  117. var matches = self.matches[i]
  118. if (!matches || Object.keys(matches).length === 0) {
  119. if (self.nonull) {
  120. // do like the shell, and spit out the literal glob
  121. var literal = self.minimatch.globSet[i]
  122. if (nou)
  123. all.push(literal)
  124. else
  125. all[literal] = true
  126. }
  127. } else {
  128. // had matches
  129. var m = Object.keys(matches)
  130. if (nou)
  131. all.push.apply(all, m)
  132. else
  133. m.forEach(function (m) {
  134. all[m] = true
  135. })
  136. }
  137. }
  138. if (!nou)
  139. all = Object.keys(all)
  140. if (!self.nosort)
  141. all = all.sort(self.nocase ? alphasorti : alphasort)
  142. // at *some* point we statted all of these
  143. if (self.mark) {
  144. for (var i = 0; i < all.length; i++) {
  145. all[i] = self._mark(all[i])
  146. }
  147. if (self.nodir) {
  148. all = all.filter(function (e) {
  149. return !(/\/$/.test(e))
  150. })
  151. }
  152. }
  153. if (self.ignore.length)
  154. all = all.filter(function(m) {
  155. return !isIgnored(self, m)
  156. })
  157. self.found = all
  158. }
  159. function mark (self, p) {
  160. var abs = makeAbs(self, p)
  161. var c = self.cache[abs]
  162. var m = p
  163. if (c) {
  164. var isDir = c === 'DIR' || Array.isArray(c)
  165. var slash = p.slice(-1) === '/'
  166. if (isDir && !slash)
  167. m += '/'
  168. else if (!isDir && slash)
  169. m = m.slice(0, -1)
  170. if (m !== p) {
  171. var mabs = makeAbs(self, m)
  172. self.statCache[mabs] = self.statCache[abs]
  173. self.cache[mabs] = self.cache[abs]
  174. }
  175. }
  176. return m
  177. }
  178. // lotta situps...
  179. function makeAbs (self, f) {
  180. var abs = f
  181. if (f.charAt(0) === '/') {
  182. abs = path.join(self.root, f)
  183. } else if (isAbsolute(f) || f === '') {
  184. abs = f
  185. } else if (self.changedCwd) {
  186. abs = path.resolve(self.cwd, f)
  187. } else {
  188. abs = path.resolve(f)
  189. }
  190. return abs
  191. }
  192. // Return true, if pattern ends with globstar '**', for the accompanying parent directory.
  193. // Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
  194. function isIgnored (self, path) {
  195. if (!self.ignore.length)
  196. return false
  197. return self.ignore.some(function(item) {
  198. return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
  199. })
  200. }
  201. function childrenIgnored (self, path) {
  202. if (!self.ignore.length)
  203. return false
  204. return self.ignore.some(function(item) {
  205. return !!(item.gmatcher && item.gmatcher.match(path))
  206. })
  207. }