react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / node_modules / commoner / node_modules / glob / sync.js
81164 viewsmodule.exports = globSync1globSync.GlobSync = GlobSync23var fs = require("fs")4var minimatch = require("minimatch")5var Minimatch = minimatch.Minimatch6var Glob = require("./glob.js").Glob7var util = require("util")8var path = require("path")9var assert = require("assert")10var common = require("./common.js")11var alphasort = common.alphasort12var isAbsolute = common.isAbsolute13var setopts = common.setopts14var ownProp = common.ownProp1516function globSync (pattern, options) {17if (typeof options === 'function' || arguments.length === 3)18throw new TypeError('callback provided to sync glob')1920return new GlobSync(pattern, options).found21}2223function GlobSync (pattern, options) {24if (!pattern)25throw new Error("must provide pattern")2627if (typeof options === 'function' || arguments.length === 3)28throw new TypeError('callback provided to sync glob')2930if (!(this instanceof GlobSync))31return new GlobSync(pattern, options)3233setopts(this, pattern, options)3435if (this.noprocess)36return this3738var n = this.minimatch.set.length39this.matches = new Array(n)40for (var i = 0; i < n; i ++) {41this._process(this.minimatch.set[i], i, false)42}43this._finish()44}4546GlobSync.prototype._finish = function () {47assert(this instanceof GlobSync)48common.finish(this)49}505152GlobSync.prototype._process = function (pattern, index, inGlobStar) {53assert(this instanceof GlobSync)5455// Get the first [n] parts of pattern that are all strings.56var n = 057while (typeof pattern[n] === "string") {58n ++59}60// now n is the index of the first one that is *not* a string.6162// See if there's anything else63var prefix64switch (n) {65// if not, then this is rather simple66case pattern.length:67this._processSimple(pattern.join('/'), index)68return6970case 0:71// pattern *starts* with some non-trivial item.72// going to readdir(cwd), but not include the prefix in matches.73prefix = null74break7576default:77// pattern has some string bits in the front.78// whatever it starts with, whether that's "absolute" like /foo/bar,79// or "relative" like "../baz"80prefix = pattern.slice(0, n).join("/")81break82}8384var remain = pattern.slice(n)8586// get the list of entries.87var read88if (prefix === null)89read = "."90else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) {91if (!prefix || !isAbsolute(prefix))92prefix = "/" + prefix93read = prefix94} else95read = prefix9697var abs = this._makeAbs(read)9899var isGlobStar = remain[0] === minimatch.GLOBSTAR100if (isGlobStar)101this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)102else103this._processReaddir(prefix, read, abs, remain, index, inGlobStar)104}105106GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {107var entries = this._readdir(abs, inGlobStar)108109// if the abs isn't a dir, then nothing can match!110if (!entries)111return112113// It will only match dot entries if it starts with a dot, or if114// dot is set. Stuff like @(.foo|.bar) isn't allowed.115var pn = remain[0]116var negate = !!this.minimatch.negate117var rawGlob = pn._glob118var dotOk = this.dot || rawGlob.charAt(0) === "."119120var matchedEntries = []121for (var i = 0; i < entries.length; i++) {122var e = entries[i]123if (e.charAt(0) !== "." || dotOk) {124var m125if (negate && !prefix) {126m = !e.match(pn)127} else {128m = e.match(pn)129}130if (m)131matchedEntries.push(e)132}133}134135var len = matchedEntries.length136// If there are no matched entries, then nothing matches.137if (len === 0)138return139140// if this is the last remaining pattern bit, then no need for141// an additional stat *unless* the user has specified mark or142// stat explicitly. We know they exist, since readdir returned143// them.144145if (remain.length === 1 && !this.mark && !this.stat) {146if (!this.matches[index])147this.matches[index] = Object.create(null)148149for (var i = 0; i < len; i ++) {150var e = matchedEntries[i]151if (prefix) {152if (prefix.slice(-1) !== "/")153e = prefix + "/" + e154else155e = prefix + e156}157158if (e.charAt(0) === "/" && !this.nomount) {159e = path.join(this.root, e)160}161this.matches[index][e] = true162}163// This was the last one, and no stats were needed164return165}166167// now test all matched entries as stand-ins for that part168// of the pattern.169remain.shift()170for (var i = 0; i < len; i ++) {171var e = matchedEntries[i]172var newPattern173if (prefix)174newPattern = [prefix, e]175else176newPattern = [e]177this._process(newPattern.concat(remain), index, inGlobStar)178}179}180181182GlobSync.prototype._emitMatch = function (index, e) {183if (!this.matches[index][e]) {184if (this.nodir) {185var c = this.cache[this._makeAbs(e)]186if (c === 'DIR' || Array.isArray(c))187return188}189190this.matches[index][e] = true191if (this.stat || this.mark)192this._stat(this._makeAbs(e))193}194}195196197GlobSync.prototype._readdirInGlobStar = function (abs) {198var entries199var lstat200var stat201try {202lstat = fs.lstatSync(abs)203} catch (er) {204// lstat failed, doesn't exist205return null206}207208var isSym = lstat.isSymbolicLink()209this.symlinks[abs] = isSym210211// If it's not a symlink or a dir, then it's definitely a regular file.212// don't bother doing a readdir in that case.213if (!isSym && !lstat.isDirectory())214this.cache[abs] = 'FILE'215else216entries = this._readdir(abs, false)217218return entries219}220221GlobSync.prototype._readdir = function (abs, inGlobStar) {222var entries223224if (inGlobStar && !ownProp(this.symlinks, abs))225return this._readdirInGlobStar(abs)226227if (ownProp(this.cache, abs)) {228var c = this.cache[abs]229if (!c || c === 'FILE')230return null231232if (Array.isArray(c))233return c234}235236try {237return this._readdirEntries(abs, fs.readdirSync(abs).sort(alphasort))238} catch (er) {239this._readdirError(abs, er)240return null241}242}243244GlobSync.prototype._readdirEntries = function (abs, entries) {245// if we haven't asked to stat everything, then just246// assume that everything in there exists, so we can avoid247// having to stat it a second time.248if (!this.mark && !this.stat) {249for (var i = 0; i < entries.length; i ++) {250var e = entries[i]251if (abs === "/")252e = abs + e253else254e = abs + "/" + e255this.cache[e] = true256}257}258259this.cache[abs] = entries260261// mark and cache dir-ness262return entries263}264265GlobSync.prototype._readdirError = function (f, er) {266// handle errors, and cache the information267switch (er.code) {268case "ENOTDIR": // totally normal. means it *does* exist.269this.cache[f] = 'FILE'270break271272case "ENOENT": // not terribly unusual273case "ELOOP":274case "ENAMETOOLONG":275case "UNKNOWN":276this.cache[f] = false277break278279default: // some unusual error. Treat as failure.280this.cache[f] = false281if (this.strict) throw er282if (!this.silent) console.error("glob error", er)283break284}285}286287GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {288289var entries = this._readdir(abs, inGlobStar)290291// no entries means not a dir, so it can never have matches292// foo.txt/** doesn't match foo.txt293if (!entries)294return295296// test without the globstar, and with every child both below297// and replacing the globstar.298var remainWithoutGlobStar = remain.slice(1)299var gspref = prefix ? [ prefix ] : []300var noGlobStar = gspref.concat(remainWithoutGlobStar)301302// the noGlobStar pattern exits the inGlobStar state303this._process(noGlobStar, index, false)304305var len = entries.length306var isSym = this.symlinks[abs]307308// If it's a symlink, and we're in a globstar, then stop309if (isSym && inGlobStar)310return311312for (var i = 0; i < len; i++) {313var e = entries[i]314if (e.charAt(0) === "." && !this.dot)315continue316317// these two cases enter the inGlobStar state318var instead = gspref.concat(entries[i], remainWithoutGlobStar)319this._process(instead, index, true)320321var below = gspref.concat(entries[i], remain)322this._process(below, index, true)323}324}325326GlobSync.prototype._processSimple = function (prefix, index) {327// XXX review this. Shouldn't it be doing the mounting etc328// before doing stat? kinda weird?329var exists = this._stat(prefix)330331if (!this.matches[index])332this.matches[index] = Object.create(null)333334// If it doesn't exist, then just mark the lack of results335if (!exists)336return337338if (prefix && isAbsolute(prefix) && !this.nomount) {339if (prefix.charAt(0) === "/") {340prefix = path.join(this.root, prefix)341} else {342prefix = path.resolve(this.root, prefix)343}344}345346if (process.platform === "win32")347prefix = prefix.replace(/\\/g, "/")348349// Mark this as a match350this.matches[index][prefix] = true351}352353// Returns either 'DIR', 'FILE', or false354GlobSync.prototype._stat = function (f) {355var abs = f356if (f.charAt(0) === "/")357abs = path.join(this.root, f)358else if (this.changedCwd)359abs = path.resolve(this.cwd, f)360361362if (f.length > this.maxLength)363return false364365if (!this.stat && ownProp(this.cache, f)) {366var c = this.cache[f]367368if (Array.isArray(c))369c = 'DIR'370371// It exists, but not how we need it372if (abs.slice(-1) === "/" && c !== 'DIR')373return false374375return c376}377378var exists379var stat = this.statCache[abs]380if (!stat) {381try {382stat = fs.statSync(abs)383} catch (er) {384return false385}386}387388this.statCache[abs] = stat389390if (abs.slice(-1) === "/" && !stat.isDirectory())391return false392393var c = stat.isDirectory() ? 'DIR' : 'FILE'394this.cache[f] = this.cache[f] || c395return c396}397398GlobSync.prototype._mark = function (p) {399return common.mark(this, p)400}401402GlobSync.prototype._makeAbs = function (f) {403return common.makeAbs(this, f)404}405406407