common.js 5.8 KB

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