Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

301 Permanent Redirect

Renamed.  Please use <https://github.com/isaacs/node-glob> instead.
  • Loading branch information...
commit 278b2086717d78e0f81e82255cc1510181059807 1 parent 7e07ba2
@isaacs authored
View
2  .gitignore
@@ -1,2 +0,0 @@
-.*.swp
-test/a/
View
104 README.md
@@ -1,103 +1,3 @@
-# Glob
+# 301 Permanent Redirect
-This is a glob implementation in JavaScript. It uses the `minimatch`
-library to do its matching.
-
-## Usage
-
-```javascript
-var glob = require("glob")
-
-// options is optional
-glob("**/*.js", options, function (er, files) {
- // files is an array of filenames.
- // If the `nonull` option is set, and nothing
- // was found, then files is ["**/*.js"]
- // er is an error object or null.
-})
-```
-
-## Features
-
-Please see the [minimatch
-documentation](https://github.com/isaacs/minimatch) for more details.
-
-Supports these glob features:
-
-* Brace Expansion
-* Extended glob matching
-* "Globstar" `**` matching
-
-See:
-
-* `man sh`
-* `man bash`
-* `man 3 fnmatch`
-* `man 5 gitignore`
-* [minimatch documentation](https://github.com/isaacs/minimatch)
-
-## Glob Class
-
-Create a glob object by instanting the `glob.Glob` class.
-
-```javascript
-var Glob = require("glob").Glob
-var mg = new Glob(pattern, options)
-```
-
-It's an EventEmitter.
-
-### Properties
-
-* `minimatch` The minimatch object that the glob uses.
-* `options` The options object passed in.
-* `matches` A [FastList](https://github.com/isaacs/fast-list) object
- containing the matches as they are found.
-* `error` The error encountered. When an error is encountered, the
- glob object is in an undefined state, and should be discarded.
-* `aborted` Boolean which is set to true when calling `abort()`. There
- is no way at this time to continue a glob search after aborting.
-
-### Events
-
-* `end` When the matching is finished, this is emitted with all the
- matches found. If the `nonull` option is set, and no match was found,
- then the `matches` list contains the original pattern. The matches
- are sorted, unless the `nosort` flag is set.
-* `match` Every time a match is found, this is emitted with the pattern.
-* `partial` Emitted when a directory matches the start of a pattern, and
- is then searched for additional matches.
-* `error` Emitted when an unexpected error is encountered.
-* `abort` When `abort()` is called, this event is raised.
-
-### Methods
-
-* `abort` Stop the search.
-
-### Options
-
-All the options that can be passed to Minimatch can also be passed to
-Glob to change pattern matching behavior. Additionally, these ones
-are added which are glob-specific, or have glob-specific ramifcations.
-
-All options are false by default.
-
-* `cwd` The current working directory in which to search. Since, unlike
- Minimatch, Glob requires a working directory to start in, this
- defaults to `process.cwd()`.
-* `root` Since Glob requires a root setting, this defaults to
- `path.resolve(options.cwd, "/")`.
-* `mark` Add a `/` character to directory matches.
-* `follow` Use `stat` instead of `lstat`. This can cause undesirable
- behavior in the case of symbolic link cycles.
-* `nosort` Don't sort the results.
-* `stat` Set to true to stat/lstat *all* results. This reduces performance
- somewhat, but guarantees that the results are files that actually
- exist.
-* `silent` When an error other than `ENOENT` or `ENOTDIR` is encountered
- when attempting to read a directory, a warning will be printed to
- stderr. Set the `silent` option to true to suppress these warnings.
-* `strict` When an error other than `ENOENT` or `ENOTDIR` is encountered
- when attempting to read a directory, the process will just continue on
- in search of other matches. Set the `strict` option to raise an error
- in these cases.
+Renamed. Please use <https://github.com/isaacs/node-glob> instead.
View
9 examples/g.js
@@ -1,9 +0,0 @@
-var MG = require("./").Miniglob
-
-var pattern = "test/a/**/[cg]/../[cg]"
-console.log(pattern)
-
-var mg = new MG(pattern, {mark: true, sync:true}, function (er, matches) {
- console.log("matches", matches)
-})
-console.log("after")
View
369 glob.js
@@ -1,369 +0,0 @@
-module.exports = glob
-
-var fs = require("graceful-fs")
-, minimatch = require("minimatch")
-, Minimatch = minimatch.Minimatch
-, inherits = require("inherits")
-, EE = require("events").EventEmitter
-, FastList = require("fast-list")
-, path = require("path")
-, isDir = {}
-
-// Globbing is a *little* bit different than just matching, in some
-// key ways.
-//
-// First, and importantly, it matters a great deal whether a pattern
-// is "absolute" or "relative". Absolute patterns are patterns that
-// start with / on unix, or a full device/unc path on windows.
-//
-// Second, globs interact with the actual filesystem, so being able
-// to stop searching as soon as a match is no longer possible is of
-// the utmost importance. It would not do to traverse a large file
-// tree, and then eliminate all but one of the options, if it could
-// be possible to skip the traversal early.
-
-// Get a Minimatch object from the pattern and options. Then, starting
-// from the options.root or the cwd, read the dir, and do a partial
-// match on all the files if it's a dir, or a regular match if it's not.
-
-
-function glob (pattern, options, cb) {
- if (typeof options === "function") cb = options, options = {}
- if (!options) options = {}
-
- if (typeof options === "number") {
- deprecated()
- return
- }
-
- var m = new Glob(pattern, options, cb)
-
- if (options.sync) {
- return m.found
- } else {
- return m
- }
-}
-
-glob.fnmatch = deprecated
-
-function deprecated () {
- throw new Error("glob's interface has changed. Please see the docs.")
-}
-
-glob.sync = globSync
-function globSync (pattern, options) {
- if (typeof options === "number") {
- deprecated()
- return
- }
-
- options = options || {}
- options.sync = true
- return glob(pattern, options)
-}
-
-
-glob.Glob = Glob
-inherits(Glob, EE)
-function Glob (pattern, options, cb) {
- if (!(this instanceof Glob)) {
- return new Glob(pattern, options, cb)
- }
-
- if (typeof cb === "function") {
- this.on("error", cb)
- this.on("end", function (matches) { cb(null, matches) })
- }
-
- options = options || {}
-
- if (!options.hasOwnProperty("maxDepth")) options.maxDepth = 1000
- if (!options.hasOwnProperty("maxLength")) options.maxLength = 4096
-
- var cwd = this.cwd = options.cwd =
- options.cwd || process.cwd()
-
- this.root = options.root =
- options.root || path.resolve(cwd, "/")
-
- if (!pattern) {
- throw new Error("must provide pattern")
- }
-
- var mm = this.minimatch = new Minimatch(pattern, options)
- options = this.options = mm.options
- pattern = this.pattern = mm.pattern
-
- this.error = null
- this.aborted = false
-
- this.matches = new FastList()
- EE.call(this)
- var me = this
-
- this._process(this.cwd, 1, this._finish.bind(this))
-}
-
-Glob.prototype._finish = _finish
-function _finish () {
- var me = this
- if (me.options.debug) {
- console.error("!!! GLOB top level cb", me)
- }
- if (me.options.nonull && me.matches.length === 0) {
- return me.emit("end", [pattern])
- }
-
- var found = me.found = me.matches.slice()
-
- found = me.found = found.map(function (m) {
- if (m.indexOf(me.options.cwd) === 0) {
- m = m.substr(me.options.cwd.length + 1)
- }
- return m
- })
-
- if (!me.options.mark) return next()
-
- // mark all directories with a /.
- // This may involve some stat calls for things that are unknown.
- var needStat = []
- found = me.found = found.map(function (f) {
- if (isDir[f] === undefined) needStat.push(f)
- else if (isDir[f] && f.slice(-1) !== "/") f += "/"
- return f
- })
- var c = needStat.length
- if (c === 0) return next()
-
- var stat = me.options.follow ? "stat" : "lstat"
- needStat.forEach(function (f) {
- if (me.options.sync) {
- try {
- afterStat(null, fs[stat + "Sync"](f))
- } catch (er) {
- afterStat(er)
- }
- } else fs[stat](f, afterStat)
- })
-
- function afterStat (er, st) {
- // ignore errors. if the user only wants to show
- // existing files, then set options.stat to exclude anything
- // that doesn't exist.
- if (st && st.isDirectory()) {
- found.splice(found.indexOf(f), 1, f + "/")
- }
- if (-- c <= 0) return next()
- }
-
- function next () {
- if (!me.options.nosort) {
- found = found.sort(function (a, b) {
- return a > b ? 1 : a < b ? -1 : 0
- })
- }
- me.emit("end", found)
- }
-}
-
-
-Glob.prototype.abort = abort
-function abort () {
- this.aborted = true
- this.emit("abort")
-}
-
-
-Glob.prototype._process = _process
-function _process (f, depth, cb) {
- if (this.aborted) return cb()
-
- var me = this
-
- // if f matches, then it's a match. emit it, move on.
- // if it *partially* matches, then it might be a dir.
- //
- // possible optimization: don't just minimatch everything
- // against the full pattern. if a bit of the pattern is
- // not magical, it'd be good to reduce the number of stats
- // that had to be made. so, in the pattern: "a/*/b", we could
- // readdir a, then stat a/<child>/b in all of them.
- //
- // however, that'll require a lot of muddying between minimatch
- // and glob, and at least for the time being, it's kind of nice to
- // keep them a little bit separate.
-
- // if this thing is a match, then add to the matches list.
- var match = me.minimatch.match(f)
- if (!match) return me._processPartial(f, depth, cb)
-
- if (match) {
- if (me.options.debug) {
- console.error(" %s matches %s", f, me.pattern)
- }
- // make sure it exists if asked.
- if (me.options.stat) {
- var stat = me.options.follow ? "stat" : "lstat"
- if (me.options.sync) {
- try {
- afterStat(null, fs[stat + "Sync"](f))
- } catch (ex) {
- afterStat(ex)
- }
- } else fs[stat](f, afterStat)
- } else if (me.options.sync) {
- emitMatch()
- } else {
- process.nextTick(emitMatch)
- }
-
- return
-
- function afterStat (er, st) {
- if (er) return cb()
- isDir[f] = st.isDirectory()
- emitMatch()
- }
-
- function emitMatch () {
- if (me.options.debug) {
- console.error("emitting match", f)
- }
- me.matches.push(f)
- me.emit("match", f)
- // move on, since it might also be a partial match
- // eg, a/**/c matches both a/c and a/c/d/c
- me._processPartial(f, depth, cb)
- }
- }
-
-}
-
-
-Glob.prototype._processPartial = _processPartial
-function _processPartial (f, depth, cb) {
- if (this.aborted) return cb()
-
- var me = this
-
- var partial = me.minimatch.match(f, true)
- if (!partial) {
- if (me.options.debug) console.error("not a partial", f)
-
- // if not a match or partial match, just move on.
- return cb()
- }
-
- // partial match
- // however, this only matters if it's a dir.
- //if (me.options.debug)
- if (me.options.debug) {
- console.error("got a partial", f)
- }
- me.emit("partial", f)
-
- me._processDir(f, depth, cb)
-}
-
-Glob.prototype._processDir = _processDir
-function _processDir (f, depth, cb) {
- if (this.aborted) return cb()
-
- // If we're already at the maximum depth, then don't read the dir.
- if (depth >= this.options.maxDepth) return cb()
-
- // if the path is at the maximum length, then don't proceed, either.
- if (f.length >= this.options.maxLength) return cb()
-
- // now the fun stuff.
- // if it's a dir, then we'll read all the children, and process them.
- // if it's not a dir, or we can't access it, then it'll fail.
- // We log a warning for EACCES and EPERM, but ENOTDIR and ENOENT are
- // expected and fine.
- cb = this._afterReaddir(f, depth, cb)
- if (this.options.sync) return this._processDirSync(f, depth, cb)
- fs.readdir(f, cb)
-}
-
-Glob.prototype._processDirSync = _processDirSync
-function _processDirSync (f, depth, cb) {
- try {
- cb(null, fs.readdirSync(f))
- } catch (ex) {
- cb(ex)
- }
-}
-
-Glob.prototype._afterReaddir = _afterReaddir
-function _afterReaddir (f, depth, cb) {
- var me = this
- return function afterReaddir (er, children) {
- if (er) switch (er.code) {
- case "UNKNOWN": // probably too deep
- case "ENOTDIR": // completely expected and normal.
- isDir[f] = false
- return cb()
- case "ENOENT": // should never happen.
- default: // some other kind of problem.
- if (!me.options.silent) console.error("glob error", er)
- if (me.options.strict) return cb(er)
- return cb()
- }
-
- // at this point, we know it's a dir, so save a stat later if
- // mark is set.
- isDir[f] = true
-
- me._processChildren(f, depth, children, cb)
- }
-}
-
-Glob.prototype._processChildren = _processChildren
-function _processChildren (f, depth, children, cb) {
- var me = this
-
- // note: the file ending with / might match, but only if
- // it's a directory, which we know it is at this point.
- // For example, /a/b/ or /a/b/** would match /a/b/ but not
- // /a/b. Note: it'll get the trailing "/" strictly based
- // on the "mark" param, but that happens later.
- // This is slightly different from bash's glob.
- if (!me.minimatch.match(f) && me.minimatch.match(f + "/")) {
- me.matches.push(f)
- me.emit("match", f)
- }
-
- if (-1 === children.indexOf(".")) children.push(".")
- if (-1 === children.indexOf("..")) children.push("..")
-
- var count = children.length
- if (me.options.debug) {
- console.error("count=%d %s", count, f, children)
- }
-
- if (count === 0) {
- if (me.options.debug) {
- console.error("no children?", children, f)
- }
- return then()
- }
-
- children.forEach(function (c) {
- if (me.options.debug) {
- console.error(" processing", f + "/" + c)
- }
- me._process(f + "/" + c, depth + 1, then)
- })
-
- function then (er) {
- count --
- if (me.options.debug) {
- console.error("%s THEN %s", f, count, count <= 0 ? "done" : "not done")
- }
- if (me.error) return
- if (er) return me.emit("error", me.error = er)
- if (count <= 0) cb()
- }
-}
View
28 package.json
@@ -1,28 +0,0 @@
-{
- "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
- "name": "glob",
- "description": "a little globber",
- "version": "3.0.0",
- "repository": {
- "type": "git",
- "url": "git://github.com/isaacs/glob.git"
- },
- "main": "glob.js",
- "engines": {
- "node": "*"
- },
- "dependencies": {
- "fast-list":"1",
- "minimatch": "0.1",
- "graceful-fs": "~1.1.2",
- "inherits": "1"
- },
- "devDependencies": {
- "tap": "0.1",
- "mkdirp":"0.2",
- "rimraf":"1"
- },
- "scripts": {
- "test": "tap test/*.js"
- }
-}
View
61 test/00-setup.js
@@ -1,61 +0,0 @@
-// just a little pre-run script to set up the fixtures.
-// zz-finish cleans it up
-
-var mkdirp = require("mkdirp")
-var path = require("path")
-var i = 0
-var tap = require("tap")
-var fs = require("fs")
-var rimraf = require("rimraf")
-
-var files =
-[ "a/.abcdef/x/y/z/a"
-, "a/abcdef/g/h"
-, "a/abcfed/g/h"
-, "a/b/c/d"
-, "a/bc/e/f"
-, "a/c/d/c/b"
-, "a/cb/e/f"
-]
-
-var symlinkTo = path.resolve(__dirname, "a/symlink/a/b/c")
-var symlinkFrom = "../.."
-
-files = files.map(function (f) {
- return path.resolve(__dirname, f)
-})
-
-tap.test("remove fixtures", function (t) {
- rimraf(path.resolve(__dirname, "a"), function (er) {
- t.ifError(er, "remove fixtures")
- t.end()
- })
-})
-
-files.forEach(function (f) {
- tap.test(f, function (t) {
- var d = path.dirname(f)
- mkdirp(d, 0755, function (er) {
- if (er) {
- t.fail(er)
- return t.bailout()
- }
- fs.writeFile(f, "i like tests", function (er) {
- t.ifError(er, "make file")
- t.end()
- })
- })
- })
-})
-
-tap.test("symlinky", function (t) {
- var d = path.dirname(symlinkTo)
- console.error("mkdirp", d)
- mkdirp(d, 0755, function (er) {
- t.ifError(er)
- fs.symlink(symlinkFrom, symlinkTo, function (er) {
- t.ifError(er, "make symlink")
- t.end()
- })
- })
-})
View
101 test/bash-comparison.js
@@ -1,101 +0,0 @@
-// basic test
-// show that it does the same thing by default as the shell.
-var tap = require("tap")
-, child_process = require("child_process")
-
-// put more patterns here.
-, globs =
- ["test/a/*/+(c|g)/./d"
- ,"test/a/**/[cg]/../[cg]"
- ,"test/a/{b,c,d,e,f}/**/g"
- ,"test/a/b/**"
- ,"test/**/g"
- ,"test/a/abc{fed,def}/g/h"
- ,"test/a/abc{fed/g,def}/**/"
- ,"test/a/abc{fed/g,def}/**///**/"
- ,"test/**/a/**/"
- ,"test/+(a|b|c)/a{/,bc*}/**"
- ,"test/*/*/*/f"
- ,"test/**/f"
- ,"test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**"
- ]
-, glob = require("../")
-, path = require("path")
-
-// run from the root of the project
-// this is usually where you're at anyway, but be sure.
-process.chdir(path.resolve(__dirname, ".."))
-
-function alphasort (a, b) {
- a = a.toLowerCase()
- b = b.toLowerCase()
- return a > b ? 1 : a < b ? -1 : 0
-}
-
-globs.forEach(function (pattern) {
- var echoOutput
- tap.test(pattern, function (t) {
- var bashPattern = pattern //.replace(/(\(|\||\))/g, "\\$1")
- , cmd = "shopt -s globstar && " +
- "shopt -s extglob && " +
- "shopt -s nullglob && " +
- // "shopt >&2; " +
- "eval \'for i in " + bashPattern + "; do echo $i; done\'"
- , cp = child_process.spawn("bash", ["-c",cmd])
- , out = []
- , globResult
- cp.stdout.on("data", function (c) {
- out.push(c)
- })
- cp.stderr.on("data", function (c) {
- process.stderr.write(c)
- })
- cp.on("exit", function () {
- echoOutput = flatten(out)
- if (!echoOutput) echoOutput = []
- else {
- echoOutput = echoOutput.split(/\r*\n/).map(function (m) {
- // Bash is a oddly inconsistent with slashes in the
- // the results. This implementation is a bit more
- // normalized. Account for this in the test results.
- return m.replace(/\/+/g, "/").replace(/\/$/, "")
- }).sort(alphasort).reduce(function (set, f) {
- if (f !== set[set.length - 1]) set.push(f)
- return set
- }, [])
- }
- next()
- })
-
- glob(pattern, function (er, matches) {
- t.ifError(er, pattern + " should not error")
- globResult = matches
- next()
- })
-
- function next () {
- if (!echoOutput || !globResult) return
-
- t.deepEqual(globResult, echoOutput, "should match shell")
- t.end()
- }
- })
-
- tap.test(pattern + " sync", function (t) {
- t.deepEqual(glob.sync(pattern), echoOutput, "should match shell")
- t.end()
- })
-})
-
-function flatten (chunks) {
- var s = 0
- chunks.forEach(function (c) { s += c.length })
- var out = new Buffer(s)
- s = 0
- chunks.forEach(function (c) {
- c.copy(out, s)
- s += c.length
- })
-
- return out.toString().trim()
-}
View
11 test/zz-cleanup.js
@@ -1,11 +0,0 @@
-// remove the fixtures
-var tap = require("tap")
-, rimraf = require("rimraf")
-, path = require("path")
-
-tap.test("cleanup fixtures", function (t) {
- rimraf(path.resolve(__dirname, "a"), function (er) {
- t.ifError(er, "removed")
- t.end()
- })
-})
Please sign in to comment.
Something went wrong with that request. Please try again.