[Pkg-javascript-commits] [SCM] glob/fnmatch binding for NodeJS branch, master, updated. debian/2.0.9-1-3-ga067315
Jérémy Lal
kapouer at melix.org
Fri Mar 16 21:56:47 UTC 2012
The following commit has been merged in the master branch:
commit 98d9eef08c2465cab993209a83b41e045f16f290
Author: Jérémy Lal <kapouer at melix.org>
Date: Fri Mar 16 22:02:29 2012 +0100
Imported Upstream version 3.1.6
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 73ee92d..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.lock-wscript
-build/
-test/core
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..2af4b71
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,2 @@
+.*.swp
+test/a/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..94cd7f6
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.7
diff --git a/LICENCE b/LICENCE
deleted file mode 100644
index ca677bf..0000000
--- a/LICENCE
+++ /dev/null
@@ -1,30 +0,0 @@
-
-Copyright (c) 2011 Isaac Z. Schlueter
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-This program includes software contributed to The NetBSD Foundation.
-See dep/bsdglob/LICENSE.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 30ad932..0000000
--- a/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-
-build:
- node-waf configure build
-
-clean:
- node-waf clean
-
-install:
- npm install
-
-.PHONY: build clean install
diff --git a/README.md b/README.md
index 7955ee0..6e27df6 100644
--- a/README.md
+++ b/README.md
@@ -1,148 +1,233 @@
+# Glob
-node-glob - Globbing for Node
+This is a glob implementation in JavaScript. It uses the `minimatch`
+library to do its matching.
-## One day, in <irc://irc.freenode.net#node.js>...
+## Attention: node-glob users!
-<code>[4:46pm] <a href="http://tinyclouds.org/">_ry</a>: it would be good to
-have a file system Glob functionality (to get an array of
-filenames)</code>
+The API has changed dramatically between 2.x and 3.x. This library is
+now 100% JavaScript, and the integer flags have been replaced with an
+options object.
-## // 9 months later...
+Also, there's an event emitter class, proper tests, and all the other
+things you've come to expect from node modules.
- npm install glob
-
-(You can also install it by doing `node-waf configure build` and then
-linking or copying the folder into your project's `node_modules`
-directory.)
-
-## Wtf's a "glob"?
-
-A glob is a pattern-matching syntax that shells use. Like when you do
-`rm *.js`, the `*.js` is a glob.
-
-You can do nifty things with them.
-
-## Supported Environments
-
-* Macintosh OS X (Darwin)
-* FreeBSD
-* NetBSD
-* Linux
-* Solaris
-
-If it doesn't work on one of those environments, please <a
-href="https://github.com/isaacs/node-glob/issues">post a bug</a>.
+And best of all, no compilation!
## Usage
-This is a binding to
-[glob(3)](http://www.daemon-systems.org/man/glob.3.html) and
-[fnmatch(3)](http://www.daemon-systems.org/man/fnmatch.3.html). It includes
-a statically compiled port of the NetBSD glob and fnmatch
-programs, so it might not exactly match what `#include <fnmatch.h>`
-or `#include <glob.h>` implements on your system.
-
-To load the library:
-
- var glob = require("glob")
-
-## Methods
-
-### glob
-
-Search through the filesystem asynchronously.
-
-#### Params
-
-* pattern: String
-* flags: int, Optional (see below)
-* cb: function
-
-#### Return
-
-NOTHING!
-
-#### Example
-
- glob(pattern, flags, function (er, matches) {
- // if an error occurred, it's in er.
- // otherwise, "matches" is an array of filenames.
- ...
- })
-
-### globSync
-
-Search through the filesystem synchronously
-
-#### Params
-
-* pattern: String
-* flags: int, Optional (see below)
-
-#### Return
-
-Array of strings that match.
-
-#### Example
-
- var matches = glob.globSync(pattern, flags) // throws on error
-
-### fnmatch
-
-Test if a string matches a pattern. (no i/o performed)
-
-#### Params
-
-* pattern: String
-* str: String to test
-* flags: int, Optional (see below)
-
-#### Example
-
- var isMatch = glob.fnmatch(pattern, str, flags)
-
+```javascript
+var glob = require("glob")
-## Flags
+// 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.
+})
+```
-The behavior of glob and fnmatch are modified by several bitwise flags.
+## Features
-The flags are defined on the main glob object. If you have an integer,
-and want to look up which flag it corresponds to, you can look it up on
-the glob/globSync functions if it is a glob flag, or on the fnmatch
-function if it is an fnmatch flag.
+Please see the [minimatch
+documentation](https://github.com/isaacs/minimatch) for more details.
-That is, `fnmatch[fnmatch.FNM_CASEFOLD] === 'FNM_CASEFOLD'`.
+Supports these glob features:
-* `GLOB_DEFAULT` Used if no flags are passed to `glob()` or
- `globSync()`. Equivalent of
- `GLOB_BRACE|GLOB_LIMIT|GLOB_STAR|GLOB_MARK|GLOB_TILDE`.
-* `FNM_DEFAULT` Used if no flags are passed to `fnmatch()`. Equivalent
- of `FNM_PATHNAME|FNM_PERIOD`.
-* `GLOB_MARK` Append / to matching directories.
-* `GLOB_NOCHECK` Return pattern itself if nothing matches.
-* `GLOB_NOSORT` Don't sort.
-* `GLOB_NOESCAPE` Disable backslash escaping.
-* `GLOB_NOSPACE` Malloc call failed.
-* `GLOB_ABORTED` Unignored error.
-* `GLOB_NOMATCH` No match, and GLOB_NOCHECK was not set.
-* `GLOB_NOSYS` Implementation does not support function.
-* `GLOB_BRACE` Expand braces ala csh.
-* `GLOB_NOMAGIC` GLOB_NOCHECK without magic chars (csh).
-* `GLOB_LIMIT` Limit memory used by matches to ARG_MAX
-* `GLOB_TILDE` Expand tilde names from the passwd file.
-* `GLOB_PERIOD` Allow metachars to match leading periods.
-* `GLOB_NO_DOTDIRS` Make . and .. vanish from wildcards.
-* `GLOB_STAR` Use glob `**` to recurse directories
-* `GLOB_QUOTE` source compatibility
-* `FNM_NOMATCH` Match failed.
-* `FNM_NOSYS` Function not implemented.
-* `FNM_NORES` Out of resources
-* `FNM_NOESCAPE` Disable backslash escaping.
-* `FNM_PATHNAME` Slash must be matched by slash.
-* `FNM_PERIOD` Period must be matched by period.
-* `FNM_CASEFOLD` Pattern is matched case-insensitive
-* `FNM_LEADING_DIR` Ignore /<tail> after Imatch.
+* Brace Expansion
+* Extended glob matching
+* "Globstar" `**` matching
-## Bugs
+See:
-See <https://github.com/isaacs/node-glob/issues>.
+* `man sh`
+* `man bash`
+* `man 3 fnmatch`
+* `man 5 gitignore`
+* [minimatch documentation](https://github.com/isaacs/minimatch)
+
+## glob(pattern, [options], cb)
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* `cb` {Function}
+ * `err` {Error | null}
+ * `matches` {Array<String>} filenames found matching the pattern
+
+Perform an asynchronous glob search.
+
+## glob.sync(pattern, [options]
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* return: {Array<String>} filenames found matching the pattern
+
+Perform a synchronous glob search.
+
+## Class: glob.Glob
+
+Create a Glob object by instanting the `glob.Glob` class.
+
+```javascript
+var Glob = require("glob").Glob
+var mg = new Glob(pattern, options, cb)
+```
+
+It's an EventEmitter, and starts walking the filesystem to find matches
+immediately.
+
+### new glob.Glob(pattern, [options], [cb])
+
+* `pattern` {String} pattern to search for
+* `options` {Object}
+* `cb` {Function} Called when an error occurs, or matches are found
+ * `err` {Error | null}
+ * `matches` {Array<String>} filenames found matching the pattern
+
+Note that if the `sync` flag is set in the options, then matches will
+be immediately available on the `g.found` member.
+
+### Properties
+
+* `minimatch` The minimatch object that the glob uses.
+* `options` The options object passed in.
+* `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, but
+ you can re-use the statCache to avoid having to duplicate syscalls.
+
+### 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 matched.
+* `error` Emitted when an unexpected error is encountered, or whenever
+ any fs error occurs if `options.strict` is set.
+* `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. Also, some have been added,
+or have glob-specific ramifications.
+
+All options are false by default, unless otherwise noted.
+
+All options are added to the glob object, as well.
+
+* `cwd` The current working directory in which to search. Defaults
+ to `process.cwd()`.
+* `root` The place where patterns starting with `/` will be mounted
+ onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
+ systems, and `C:\` or some such on Windows.)
+* `nomount` By default, a pattern starting with a forward-slash will be
+ "mounted" onto the root setting, so that a valid filesystem path is
+ returned. Set this flag to disable that behavior.
+* `mark` Add a `/` character to directory matches. Note that this
+ requires additional stat calls.
+* `nosort` Don't sort the results.
+* `stat` Set to true to stat *all* results. This reduces performance
+ somewhat, and is completely unnecessary, unless `readdir` is presumed
+ to be an untrustworthy indicator of file existence. It will cause
+ ELOOP to be triggered one level sooner in the case of cyclical
+ symbolic links.
+* `silent` When an unusual error 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 unusual error 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.
+* `statCache` A cache of results of filesystem information, to prevent
+ unnecessary stat calls. While it should not normally be necessary to
+ set this, you may pass the statCache from one glob() call to the
+ options object of another, if you know that the filesystem will not
+ change between calls. (See "Race Conditions" below.)
+* `sync` Perform a synchronous glob search.
+* `nounique` In some cases, brace-expanded patterns can result in the
+ same file showing up multiple times in the result set. By default,
+ this implementation prevents duplicates in the result set.
+ Set this flag to disable that behavior.
+* `nonull` Set to never return an empty set, instead returning a set
+ containing the pattern itself. This is the default in glob(3).
+* `nocase` Perform a case-insensitive match. Note that case-insensitive
+ filesystems will sometimes result in glob returning results that are
+ case-insensitively matched anyway, since readdir and stat will not
+ raise an error.
+* `debug` Set to enable debug logging in minimatch and glob.
+* `globDebug` Set to enable debug logging in glob, but not minimatch.
+
+## Comparisons to other fnmatch/glob implementations
+
+While strict compliance with the existing standards is a worthwhile
+goal, some discrepancies exist between node-glob and other
+implementations, and are intentional.
+
+If the pattern starts with a `!` character, then it is negated. Set the
+`nonegate` flag to suppress this behavior, and treat leading `!`
+characters normally. This is perhaps relevant if you wish to start the
+pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
+characters at the start of a pattern will negate the pattern multiple
+times.
+
+If a pattern starts with `#`, then it is treated as a comment, and
+will not match anything. Use `\#` to match a literal `#` at the
+start of a line, or set the `nocomment` flag to suppress this behavior.
+
+The double-star character `**` is supported by default, unless the
+`noglobstar` flag is set. This is supported in the manner of bsdglob
+and bash 4.1, where `**` only has special significance if it is the only
+thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
+`a/**b` will not. **Note that this is different from the way that `**` is
+handled by ruby's `Dir` class.**
+
+If an escaped pattern has no matches, and the `nonull` flag is set,
+then glob returns the pattern as-provided, rather than
+interpreting the character escapes. For example,
+`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
+`"*a?"`. This is akin to setting the `nullglob` option in bash, except
+that it does not resolve escaped pattern characters.
+
+If brace expansion is not disabled, then it is performed before any
+other interpretation of the glob pattern. Thus, a pattern like
+`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
+**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
+checked for validity. Since those two are valid, matching proceeds.
+
+## Windows
+
+**Please only use forward-slashes in glob expressions.**
+
+Though windows uses either `/` or `\` as its path separator, only `/`
+characters are used by this glob implementation. You must use
+forward-slashes **only** in glob expressions. Back-slashes will always
+be interpreted as escape characters, not path separators.
+
+Results from absolute patterns such as `/foo/*` are mounted onto the
+root setting using `path.join`. On windows, this will by default result
+in `/foo/*` matching `C:\foo\bar.txt`.
+
+## Race Conditions
+
+Glob searching, by its very nature, is susceptible to race conditions,
+since it relies on directory walking and such.
+
+As a result, it is possible that a file that exists when glob looks for
+it may have been deleted or modified by the time it returns the result.
+
+As part of its internal implementation, this program caches all stat
+and readdir calls that it makes, in order to cut down on system
+overhead. However, this also makes it even more susceptible to races,
+especially if the statCache object is reused between glob calls.
+
+Users are thus advised not to use a glob result as a
+guarantee of filesystem state in the face of rapid changes.
+For the vast majority of operations, this is never a problem.
diff --git a/deps/fnmatch/LICENSE b/deps/fnmatch/LICENSE
deleted file mode 100644
index bf33ae5..0000000
--- a/deps/fnmatch/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2008 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/deps/fnmatch/fnmatch.c b/deps/fnmatch/fnmatch.c
deleted file mode 100644
index 8bfbecd..0000000
--- a/deps/fnmatch/fnmatch.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/* $NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $ */
-
-/*
- * Copyright (c) 1989, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* isaacs */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
-#else
-__RCSID("$NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-/* isaacs */
-#ifndef __UNCONST
-# define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
-#endif
-
-/* isaacs */
-#ifndef _DIAGASSERT
-# ifdef DEBUG
-# define _DIAGASSERT(a) assert(a)
-# else
-# define _DIAGASSERT(a)
-# endif
-#endif
-
-/*
- * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
- * Compares a filename or pathname to a pattern.
- */
-
-#include <fnmatch.h>
-#include <assert.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef __weak_alias
-__weak_alias(fnmatch,_fnmatch)
-#endif
-
-#define EOS '\0'
-
-static inline int
-foldcase(int ch, int flags)
-{
-
- if ((flags & FNM_CASEFOLD) != 0 && isupper(ch))
- return tolower(ch);
- return ch;
-}
-
-#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags))
-
-static const char *
-rangematch(const char *pattern, int test, int flags)
-{
- int negate, ok;
- char c, c2;
-
- _DIAGASSERT(pattern != NULL);
-
- /*
- * A bracket expression starting with an unquoted circumflex
- * character produces unspecified results (IEEE 1003.2-1992,
- * 3.13.2). This implementation treats it like '!', for
- * consistency with the regular expression syntax.
- * J.T. Conklin (conklin at ngai.kaleida.com)
- */
- if ((negate = (*pattern == '!' || *pattern == '^')) != 0)
- ++pattern;
-
- for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) {
- if (c == '\\' && !(flags & FNM_NOESCAPE))
- c = FOLDCASE(*pattern++, flags);
- if (c == EOS)
- return NULL;
- if (*pattern == '-'
- && (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS &&
- c2 != ']') {
- pattern += 2;
- if (c2 == '\\' && !(flags & FNM_NOESCAPE))
- c2 = FOLDCASE(*pattern++, flags);
- if (c2 == EOS)
- return NULL;
- if (c <= test && test <= c2)
- ok = 1;
- } else if (c == test)
- ok = 1;
- }
- return ok == negate ? NULL : pattern;
-}
-
-
-static int
-fnmatchx(const char *pattern, const char *string, int flags, size_t recursion)
-{
- const char *stringstart;
- char c, test;
-
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(string != NULL);
-
- if (recursion-- == 0)
- return FNM_NORES;
-
- for (stringstart = string;;) {
- switch (c = FOLDCASE(*pattern++, flags)) {
- case EOS:
- if ((flags & FNM_LEADING_DIR) && *string == '/')
- return 0;
- return *string == EOS ? 0 : FNM_NOMATCH;
- case '?':
- if (*string == EOS)
- return FNM_NOMATCH;
- if (*string == '/' && (flags & FNM_PATHNAME))
- return FNM_NOMATCH;
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return FNM_NOMATCH;
- ++string;
- break;
- case '*':
- c = FOLDCASE(*pattern, flags);
- /* Collapse multiple stars. */
- while (c == '*')
- c = FOLDCASE(*++pattern, flags);
-
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return FNM_NOMATCH;
-
- /* Optimize for pattern with * at end or before /. */
- if (c == EOS) {
- if (flags & FNM_PATHNAME)
- return (flags & FNM_LEADING_DIR) ||
- strchr(string, '/') == NULL ?
- 0 : FNM_NOMATCH;
- else
- return 0;
- } else if (c == '/' && flags & FNM_PATHNAME) {
- if ((string = strchr(string, '/')) == NULL)
- return FNM_NOMATCH;
- break;
- }
-
- /* General case, use recursion. */
- while ((test = FOLDCASE(*string, flags)) != EOS) {
- int e;
- switch ((e = fnmatchx(pattern, string,
- flags & ~FNM_PERIOD, recursion))) {
- case FNM_NOMATCH:
- break;
- default:
- return e;
- }
- if (test == '/' && flags & FNM_PATHNAME)
- break;
- ++string;
- }
- return FNM_NOMATCH;
- case '[':
- if (*string == EOS)
- return FNM_NOMATCH;
- if (*string == '/' && flags & FNM_PATHNAME)
- return FNM_NOMATCH;
- if ((pattern = rangematch(pattern,
- FOLDCASE(*string, flags), flags)) == NULL)
- return FNM_NOMATCH;
- ++string;
- break;
- case '\\':
- if (!(flags & FNM_NOESCAPE)) {
- if ((c = FOLDCASE(*pattern++, flags)) == EOS) {
- c = '\\';
- --pattern;
- }
- }
- /* FALLTHROUGH */
- default:
- if (c != FOLDCASE(*string++, flags))
- return FNM_NOMATCH;
- break;
- }
- }
- /* NOTREACHED */
-}
-
-int
-fnmatch(const char *pattern, const char *string, int flags)
-{
- return fnmatchx(pattern, string, flags, 64);
-}
-
-/* isaacs */
-#ifdef __cplusplus
-}
-#endif
diff --git a/deps/fnmatch/fnmatch.h b/deps/fnmatch/fnmatch.h
deleted file mode 100644
index d4c3129..0000000
--- a/deps/fnmatch/fnmatch.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $NetBSD: fnmatch.h,v 1.13 2011/01/31 04:49:46 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _FNMATCH_H_
-#define _FNMATCH_H_
-
-#define FNM_NOMATCH 1 /* Match failed. */
-#define FNM_NOSYS 2 /* Function not implemented. */
-#define FNM_NORES 3 /* Out of resources */
-
-#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
-#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
-#define FNM_PERIOD 0x04 /* Period must be matched by period. */
-#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */
-#define FNM_LEADING_DIR 0x10 /* Ignore /<tail> after Imatch. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-int fnmatch(const char *, const char *, int);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_FNMATCH_H_ */
diff --git a/deps/glob/LICENSE b/deps/glob/LICENSE
deleted file mode 100644
index bf33ae5..0000000
--- a/deps/glob/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2008 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/deps/glob/glob.c b/deps/glob/glob.c
deleted file mode 100644
index b5feb1a..0000000
--- a/deps/glob/glob.c
+++ /dev/null
@@ -1,1256 +0,0 @@
-/* $NetBSD: glob.c,v 1.27 2010/09/06 14:40:25 christos Exp $ */
-
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* isaacs */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
-#else
-__RCSID("$NetBSD: glob.c,v 1.27 2010/09/06 14:40:25 christos Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-/* isaacs */
-#ifndef __UNCONST
-# define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
-#endif
-
-/*
- * glob(3) -- a superset of the one defined in POSIX 1003.2.
- *
- * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
- *
- * Optional extra services, controlled by flags not defined by POSIX:
- *
- * GLOB_MAGCHAR:
- * Set in gl_flags if pattern contained a globbing character.
- * GLOB_NOMAGIC:
- * Same as GLOB_NOCHECK, but it will only append pattern if it did
- * not contain any magic characters. [Used in csh style globbing]
- * GLOB_ALTDIRFUNC:
- * Use alternately specified directory access functions.
- * GLOB_TILDE:
- * expand ~user/foo to the /home/dir/of/user/foo
- * GLOB_BRACE:
- * expand {1,2}{a,b} to 1a 1b 2a 2b
- * GLOB_PERIOD:
- * allow metacharacters to match leading dots in filenames.
- * GLOB_NO_DOTDIRS:
- * . and .. are hidden from wildcards, even if GLOB_PERIOD is set.
- * gl_matchc:
- * Number of matches in the current invocation of glob.
- */
-
-/* isaacs #include "namespace.h" */
-#include <assert.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <glob.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#ifndef __P
-# if __STDC__ || defined(__cplusplus)
-# define __P(protos) protos /* full-blown ANSI C */
-# else
-# define __P(protos) ()
-# endif
-#endif
-
-#ifdef HAVE_NBTOOL_CONFIG_H
-#define NO_GETPW_R
-#endif
-
-
-/* isaacs - added strlcpy implementation for systems that lack it. */
-#ifndef strlcpy
-/* $NetBSD: strlcpy.c,v 1.1 2010/12/05 03:15:43 christos Exp $ */
-/* from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
- register char *d = dst;
- register const char *s = src;
- register size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0) {
- do {
- if ((*d++ = *s++) == 0)
- break;
- } while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
-#endif
-
-#define GLOB_LIMIT_MALLOC 65536
-#define GLOB_LIMIT_STAT 128
-#define GLOB_LIMIT_READDIR 16384
-
-#define GLOB_INDEX_MALLOC 0
-#define GLOB_INDEX_STAT 1
-#define GLOB_INDEX_READDIR 2
-
-#ifndef _DIAGASSERT
-# ifdef DEBUG
-# define _DIAGASSERT(a) assert(a)
-# else
-# define _DIAGASSERT(a)
-# endif
-#endif
-
-#define DOLLAR '$'
-#define DOT '.'
-#define EOS '\0'
-#define LBRACKET '['
-#define NOT '!'
-#define QUESTION '?'
-#define QUOTE '\\'
-#define RANGE '-'
-#define RBRACKET ']'
-#define SEP '/'
-#define STAR '*'
-#define TILDE '~'
-#define UNDERSCORE '_'
-#define LBRACE '{'
-#define RBRACE '}'
-#define SLASH '/'
-#define COMMA ','
-
-#ifndef USE_8BIT_CHARS
-
-#define M_QUOTE 0x8000
-#define M_PROTECT 0x4000
-#define M_MASK 0xffff
-#define M_ASCII 0x00ff
-
-typedef u_short Char;
-
-#else
-
-#define M_QUOTE (Char)0x80
-#define M_PROTECT (Char)0x40
-#define M_MASK (Char)0xff
-#define M_ASCII (Char)0x7f
-
-typedef char Char;
-
-#endif
-
-
-#define CHAR(c) ((Char)((c)&M_ASCII))
-#define META(c) ((Char)((c)|M_QUOTE))
-#define M_ALL META('*')
-#define M_END META(']')
-#define M_NOT META('!')
-#define M_ONE META('?')
-#define M_RNG META('-')
-#define M_SET META('[')
-#define ismeta(c) (((c)&M_QUOTE) != 0)
-
-
-static int compare(const void *, const void *);
-static int g_Ctoc(const Char *, char *, size_t);
-static int g_lstat(Char *, __gl_stat_t *, glob_t *);
-static DIR *g_opendir(Char *, glob_t *);
-static Char *g_strchr(const Char *, int);
-static int g_stat(Char *, __gl_stat_t *, glob_t *);
-static int glob0(const Char *, glob_t *, size_t *);
-static int glob1(Char *, glob_t *, size_t *);
-static int glob2(Char *, Char *, Char *, const Char *, glob_t *,
- size_t *);
-static int glob3(Char *, Char *, Char *, const Char *, const Char *,
- const Char *, glob_t *, size_t *);
-static int globextend(const Char *, glob_t *, size_t *);
-static const Char *globtilde(const Char *, Char *, size_t, glob_t *);
-static int globexp1(const Char *, glob_t *, size_t *);
-static int globexp2(const Char *, const Char *, glob_t *, int *,
- size_t *);
-static int match(const Char *, const Char *, const Char *);
-#ifdef DEBUG
-static void qprintf(const char *, Char *);
-#else
-#define qprintf(a,b)
-#endif
-
-int
-myglob(const char *pattern, int flags, int (*errfunc)(const char *, int),
- glob_t *pglob)
-{
- const u_char *patnext;
- int c;
- Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
- /* 0 = malloc(), 1 = stat(), 2 = readdir() */
- size_t limit[] = { 0, 0, 0 };
-
- _DIAGASSERT(pattern != NULL);
-
- patnext = (const u_char *) pattern;
- if (!(flags & GLOB_APPEND)) {
- pglob->gl_pathc = 0;
- pglob->gl_pathv = NULL;
- if (!(flags & GLOB_DOOFFS))
- pglob->gl_offs = 0;
- }
- pglob->gl_flags = flags & ~GLOB_MAGCHAR;
- pglob->gl_errfunc = errfunc;
- pglob->gl_matchc = 0;
-
- bufnext = patbuf;
- bufend = bufnext + MAXPATHLEN;
- if (flags & GLOB_NOESCAPE) {
- while (bufnext < bufend && (c = *patnext++) != EOS)
- *bufnext++ = c;
- } else {
- /* Protect the quoted characters. */
- while (bufnext < bufend && (c = *patnext++) != EOS)
- if (c == QUOTE) {
- if ((c = *patnext++) == EOS) {
- c = QUOTE;
- --patnext;
- }
- *bufnext++ = c | M_PROTECT;
- }
- else
- *bufnext++ = c;
- }
- *bufnext = EOS;
-
- if (flags & GLOB_BRACE)
- return globexp1(patbuf, pglob, limit);
- else
- return glob0(patbuf, pglob, limit);
-}
-
-/*
- * Expand recursively a glob {} pattern. When there is no more expansion
- * invoke the standard globbing routine to glob the rest of the magic
- * characters
- */
-static int
-globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
-{
- const Char* ptr = pattern;
- int rv;
-
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(pglob != NULL);
-
- /* Protect a single {}, for find(1), like csh */
- if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
- return glob0(pattern, pglob, limit);
-
- while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
- if (!globexp2(ptr, pattern, pglob, &rv, limit))
- return rv;
-
- return glob0(pattern, pglob, limit);
-}
-
-
-/*
- * Recursive brace globbing helper. Tries to expand a single brace.
- * If it succeeds then it invokes globexp1 with the new pattern.
- * If it fails then it tries to glob the rest of the pattern and returns.
- */
-static int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
- size_t *limit)
-{
- int i;
- Char *lm, *ls;
- const Char *pe, *pm, *pl;
- Char patbuf[MAXPATHLEN + 1];
-
- _DIAGASSERT(ptr != NULL);
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(pglob != NULL);
- _DIAGASSERT(rv != NULL);
-
- /* copy part up to the brace */
- for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
- continue;
- ls = lm;
-
- /* Find the balanced brace */
- for (i = 0, pe = ++ptr; *pe; pe++)
- if (*pe == LBRACKET) {
- /* Ignore everything between [] */
- for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
- continue;
- if (*pe == EOS) {
- /*
- * We could not find a matching RBRACKET.
- * Ignore and just look for RBRACE
- */
- pe = pm;
- }
- }
- else if (*pe == LBRACE)
- i++;
- else if (*pe == RBRACE) {
- if (i == 0)
- break;
- i--;
- }
-
- /* Non matching braces; just glob the pattern */
- if (i != 0 || *pe == EOS) {
- /*
- * we use `pattern', not `patbuf' here so that that
- * unbalanced braces are passed to the match
- */
- *rv = glob0(pattern, pglob, limit);
- return 0;
- }
-
- for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
- switch (*pm) {
- case LBRACKET:
- /* Ignore everything between [] */
- for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
- continue;
- if (*pm == EOS) {
- /*
- * We could not find a matching RBRACKET.
- * Ignore and just look for RBRACE
- */
- pm = pl;
- }
- break;
-
- case LBRACE:
- i++;
- break;
-
- case RBRACE:
- if (i) {
- i--;
- break;
- }
- /* FALLTHROUGH */
- case COMMA:
- if (i && *pm == COMMA)
- break;
- else {
- /* Append the current string */
- for (lm = ls; (pl < pm); *lm++ = *pl++)
- continue;
- /*
- * Append the rest of the pattern after the
- * closing brace
- */
- for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
- continue;
-
- /* Expand the current pattern */
- qprintf("globexp2", patbuf);
- *rv = globexp1(patbuf, pglob, limit);
-
- /* move after the comma, to the next string */
- pl = pm + 1;
- }
- break;
-
- default:
- break;
- }
- }
- *rv = 0;
- return 0;
-}
-
-
-
-/*
- * expand tilde from the passwd file.
- */
-static const Char *
-globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
-{
- struct passwd *pwd;
- const char *h;
- const Char *p;
- Char *b;
- char *d;
- Char *pend = &patbuf[patsize / sizeof(Char)];
-#ifndef NO_GETPW_R
- struct passwd pwres;
- char pwbuf[1024];
-#endif
-
- pend--;
-
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(patbuf != NULL);
- _DIAGASSERT(pglob != NULL);
-
- if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
- return pattern;
-
- /* Copy up to the end of the string or / */
- for (p = pattern + 1, d = (char *)(void *)patbuf;
- d < (char *)(void *)pend && *p && *p != SLASH;
- *d++ = *p++)
- continue;
-
- if (d == (char *)(void *)pend)
- return NULL;
-
- *d = EOS;
- d = (char *)(void *)patbuf;
-
- if (*d == EOS) {
- /*
- * handle a plain ~ or ~/ by expanding $HOME
- * first and then trying the password file
- */
- if ((h = getenv("HOME")) == NULL) {
-#ifdef NO_GETPW_R
- if ((pwd = getpwuid(getuid())) == NULL)
-#else
- if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
- &pwd) != 0 || pwd == NULL)
-#endif
- return pattern;
- else
- h = pwd->pw_dir;
- }
- }
- else {
- /*
- * Expand a ~user
- */
-#ifdef NO_GETPW_R
- if ((pwd = getpwnam(d)) == NULL)
-#else
- if (getpwnam_r(d, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
- pwd == NULL)
-#endif
- return pattern;
- else
- h = pwd->pw_dir;
- }
-
- /* Copy the home directory */
- for (b = patbuf; b < pend && *h; *b++ = *h++)
- continue;
-
- if (b == pend)
- return NULL;
-
- /* Append the rest of the pattern */
- while (b < pend && (*b++ = *p++) != EOS)
- continue;
-
- if (b == pend)
- return NULL;
-
- return patbuf;
-}
-
-
-/*
- * The main glob() routine: compiles the pattern (optionally processing
- * quotes), calls glob1() to do the real pattern matching, and finally
- * sorts the list (unless unsorted operation is requested). Returns 0
- * if things went well, nonzero if errors occurred. It is not an error
- * to find no matches.
- */
-static int
-glob0(const Char *pattern, glob_t *pglob, size_t *limit)
-{
- const Char *qpatnext;
- int c, error;
- __gl_size_t oldpathc;
- Char *bufnext, patbuf[MAXPATHLEN+1];
-
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(pglob != NULL);
-
- if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf),
- pglob)) == NULL)
- return GLOB_ABEND;
- oldpathc = pglob->gl_pathc;
- bufnext = patbuf;
-
- /* We don't need to check for buffer overflow any more. */
- while ((c = *qpatnext++) != EOS) {
- switch (c) {
- case LBRACKET:
- c = *qpatnext;
- if (c == NOT)
- ++qpatnext;
- if (*qpatnext == EOS ||
- g_strchr(qpatnext+1, RBRACKET) == NULL) {
- *bufnext++ = LBRACKET;
- if (c == NOT)
- --qpatnext;
- break;
- }
- *bufnext++ = M_SET;
- if (c == NOT)
- *bufnext++ = M_NOT;
- c = *qpatnext++;
- do {
- *bufnext++ = CHAR(c);
- if (*qpatnext == RANGE &&
- (c = qpatnext[1]) != RBRACKET) {
- *bufnext++ = M_RNG;
- *bufnext++ = CHAR(c);
- qpatnext += 2;
- }
- } while ((c = *qpatnext++) != RBRACKET);
- pglob->gl_flags |= GLOB_MAGCHAR;
- *bufnext++ = M_END;
- break;
- case QUESTION:
- pglob->gl_flags |= GLOB_MAGCHAR;
- *bufnext++ = M_ONE;
- break;
- case STAR:
- pglob->gl_flags |= GLOB_MAGCHAR;
- /* collapse adjacent stars to one [or three if globstar]
- * to avoid exponential behavior
- */
- if (bufnext == patbuf || bufnext[-1] != M_ALL ||
- ((pglob->gl_flags & GLOB_STAR) != 0 &&
- (bufnext - 1 == patbuf || bufnext[-2] != M_ALL ||
- bufnext - 2 == patbuf || bufnext[-3] != M_ALL)))
- *bufnext++ = M_ALL;
- break;
- default:
- *bufnext++ = CHAR(c);
- break;
- }
- }
- *bufnext = EOS;
- qprintf("glob0", patbuf);
-
- if ((error = glob1(patbuf, pglob, limit)) != 0)
- return error;
-
- if (pglob->gl_pathc == oldpathc) {
- /*
- * If there was no match we are going to append the pattern
- * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was
- * specified and the pattern did not contain any magic
- * characters GLOB_NOMAGIC is there just for compatibility
- * with csh.
- */
- if ((pglob->gl_flags & GLOB_NOCHECK) ||
- ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR))
- == GLOB_NOMAGIC)) {
- return globextend(pattern, pglob, limit);
- } else {
- return GLOB_NOMATCH;
- }
- } else if (!(pglob->gl_flags & GLOB_NOSORT)) {
- qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
- (size_t)pglob->gl_pathc - oldpathc, sizeof(char *),
- compare);
- }
-
- return 0;
-}
-
-static int
-compare(const void *p, const void *q)
-{
-
- _DIAGASSERT(p != NULL);
- _DIAGASSERT(q != NULL);
-
- return strcoll(*(const char * const *)p, *(const char * const *)q);
-}
-
-static int
-glob1(Char *pattern, glob_t *pglob, size_t *limit)
-{
- Char pathbuf[MAXPATHLEN+1];
-
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(pglob != NULL);
-
- /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
- if (*pattern == EOS)
- return 0;
- /*
- * we save one character so that we can use ptr >= limit,
- * in the general case when we are appending non nul chars only.
- */
- return glob2(pathbuf, pathbuf,
- pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern,
- pglob, limit);
-}
-
-/*
- * The functions glob2 and glob3 are mutually recursive; there is one level
- * of recursion for each segment in the pattern that contains one or more
- * meta characters.
- */
-static int
-glob2(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
- glob_t *pglob, size_t *limit)
-{
- __gl_stat_t sb;
- const Char *p;
- Char *q;
- int anymeta;
- Char *pend;
- ptrdiff_t diff;
-
- _DIAGASSERT(pathbuf != NULL);
- _DIAGASSERT(pathend != NULL);
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(pglob != NULL);
-
- qprintf("glob2", pathbuf);
- /*
- * Loop over pattern segments until end of pattern or until
- * segment with meta character found.
- */
- for (anymeta = 0;;) {
- if (*pattern == EOS) { /* End of pattern? */
- *pathend = EOS;
- if (g_lstat(pathbuf, &sb, pglob))
- return 0;
-
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) {
- errno = 0;
- *pathend++ = SEP;
- *pathend = EOS;
- return GLOB_NOSPACE;
- }
- if (((pglob->gl_flags & GLOB_MARK) &&
- pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
- (S_ISLNK(sb.st_mode) &&
- (g_stat(pathbuf, &sb, pglob) == 0) &&
- S_ISDIR(sb.st_mode)))) {
- if (pathend >= pathlim)
- return GLOB_ABORTED;
- *pathend++ = SEP;
- *pathend = EOS;
- }
- ++pglob->gl_matchc;
- return globextend(pathbuf, pglob, limit);
- }
-
- /* Find end of next segment, copy tentatively to pathend. */
- q = pathend;
- p = pattern;
- while (*p != EOS && *p != SEP) {
- if (ismeta(*p))
- anymeta = 1;
- if (q >= pathlim)
- return GLOB_ABORTED;
- *q++ = *p++;
- }
-
- /*
- * No expansion, or path ends in slash-dot shash-dot-dot,
- * do next segment.
- */
- if (pglob->gl_flags & GLOB_PERIOD) {
- for (pend = pathend; pend > pathbuf && pend[-1] == '/';
- pend--)
- continue;
- diff = pend - pathbuf;
- } else {
- /* XXX: GCC */
- diff = 0;
- pend = pathend;
- }
-
- if ((!anymeta) ||
- ((pglob->gl_flags & GLOB_PERIOD) &&
- (diff >= 1 && pend[-1] == DOT) &&
- (diff >= 2 && (pend[-2] == SLASH || pend[-2] == DOT)) &&
- (diff < 3 || pend[-3] == SLASH))) {
- pathend = q;
- pattern = p;
- while (*pattern == SEP) {
- if (pathend >= pathlim)
- return GLOB_ABORTED;
- *pathend++ = *pattern++;
- }
- } else /* Need expansion, recurse. */
- return glob3(pathbuf, pathend, pathlim, pattern, p,
- pattern, pglob, limit);
- }
- /* NOTREACHED */
-}
-
-static int
-glob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
- const Char *restpattern, const Char *pglobstar, glob_t *pglob,
- size_t *limit)
-{
- struct dirent *dp;
- DIR *dirp;
- __gl_stat_t sbuf;
- int error;
- char buf[MAXPATHLEN];
- int globstar = 0;
- int chase_symlinks = 0;
- const Char *termstar = NULL;
-
- /*
- * The readdirfunc declaration can't be prototyped, because it is
- * assigned, below, to two functions which are prototyped in glob.h
- * and dirent.h as taking pointers to differently typed opaque
- * structures.
- */
- struct dirent *(*readdirfunc)(void *);
-
- _DIAGASSERT(pathbuf != NULL);
- _DIAGASSERT(pathend != NULL);
- _DIAGASSERT(pattern != NULL);
- _DIAGASSERT(restpattern != NULL);
- _DIAGASSERT(pglob != NULL);
-
- *pathend = EOS;
- errno = 0;
-
- while (pglobstar < restpattern) {
- if ((pglobstar[0] & M_MASK) == M_ALL &&
- (pglobstar[1] & M_MASK) == M_ALL) {
- globstar = 1;
- chase_symlinks = (pglobstar[2] & M_MASK) == M_ALL;
- termstar = pglobstar + (2 + chase_symlinks);
- break;
- }
- pglobstar++;
- }
-
- if (globstar) {
- error = pglobstar == pattern && termstar == restpattern ?
- *restpattern == EOS ?
- glob2(pathbuf, pathend, pathlim, restpattern - 1, pglob,
- limit) :
- glob2(pathbuf, pathend, pathlim, restpattern + 1, pglob,
- limit) :
- glob3(pathbuf, pathend, pathlim, pattern, restpattern,
- termstar, pglob, limit);
- if (error)
- return error;
- *pathend = EOS;
- }
-
- if (*pathbuf && (g_lstat(pathbuf, &sbuf, pglob) ||
- !S_ISDIR(sbuf.st_mode)
-#ifdef S_IFLINK
- && ((globstar && !chase_symlinks) || !S_ISLNK(sbuf.st_mode))
-#endif
- ))
- return 0;
-
- if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
- if (pglob->gl_errfunc) {
- if (g_Ctoc(pathbuf, buf, sizeof(buf)))
- return GLOB_ABORTED;
- if (pglob->gl_errfunc(buf, errno) ||
- pglob->gl_flags & GLOB_ERR)
- return GLOB_ABORTED;
- }
- /*
- * Posix/XOpen: glob should return when it encounters a
- * directory that it cannot open or read
- * XXX: Should we ignore ENOTDIR and ENOENT though?
- * I think that Posix had in mind EPERM...
- */
- if (pglob->gl_flags & GLOB_ERR)
- return GLOB_ABORTED;
-
- return 0;
- }
-
- error = 0;
-
- /* Search directory for matching names. */
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- readdirfunc = pglob->gl_readdir;
- else
- readdirfunc = (struct dirent *(*)__P((void *))) readdir;
- while ((dp = (*readdirfunc)(dirp)) != NULL) {
- u_char *sc;
- Char *dc;
-
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) {
- errno = 0;
- *pathend++ = SEP;
- *pathend = EOS;
- return GLOB_NOSPACE;
- }
-
- /*
- * Initial DOT must be matched literally, unless we have
- * GLOB_PERIOD set.
- */
- if ((pglob->gl_flags & GLOB_PERIOD) == 0)
- if (dp->d_name[0] == DOT && *pattern != DOT)
- continue;
- /*
- * If GLOB_NO_DOTDIRS is set, . and .. vanish.
- */
- if ((pglob->gl_flags & GLOB_NO_DOTDIRS) &&
- (dp->d_name[0] == DOT) &&
- ((dp->d_name[1] == EOS) ||
- ((dp->d_name[1] == DOT) && (dp->d_name[2] == EOS))))
- continue;
- /*
- * The resulting string contains EOS, so we can
- * use the pathlim character, if it is the nul
- */
- for (sc = (u_char *) dp->d_name, dc = pathend;
- dc <= pathlim && (*dc++ = *sc++) != EOS;)
- continue;
-
- /*
- * Have we filled the buffer without seeing EOS?
- */
- if (dc > pathlim && *pathlim != EOS) {
- /*
- * Abort when requested by caller, otherwise
- * reset pathend back to last SEP and continue
- * with next dir entry.
- */
- if (pglob->gl_flags & GLOB_ERR) {
- error = GLOB_ABORTED;
- break;
- }
- else {
- *pathend = EOS;
- continue;
- }
- }
-
- if (globstar) {
-#ifdef S_IFLNK
- if (!chase_symlinks &&
- (g_lstat(pathbuf, &sbuf, pglob) ||
- S_ISLNK(sbuf.st_mode)))
- continue;
-#endif
-
- if (!match(pathend, pattern, termstar))
- continue;
-
- if (--dc < pathlim - 2)
- *dc++ = SEP;
- *dc = EOS;
- error = glob2(pathbuf, dc, pathlim, pglobstar,
- pglob, limit);
- if (error)
- break;
- *pathend = EOS;
- } else {
- if (!match(pathend, pattern, restpattern)) {
- *pathend = EOS;
- continue;
- }
- error = glob2(pathbuf, --dc, pathlim, restpattern,
- pglob, limit);
- if (error)
- break;
- }
- }
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- (*pglob->gl_closedir)(dirp);
- else
- closedir(dirp);
-
- /*
- * Again Posix X/Open issue with regards to error handling.
- */
- if ((error || errno) && (pglob->gl_flags & GLOB_ERR))
- return GLOB_ABORTED;
-
- return error;
-}
-
-
-/*
- * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
- * add the new item, and update gl_pathc.
- *
- * This assumes the BSD realloc, which only copies the block when its size
- * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
- * behavior.
- *
- * Return 0 if new item added, error code if memory couldn't be allocated.
- *
- * Invariant of the glob_t structure:
- * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
- * gl_pathv points to (gl_offs + gl_pathc + 1) items.
- */
-static int
-globextend(const Char *path, glob_t *pglob, size_t *limit)
-{
- char **pathv;
- size_t i, newsize, len;
- char *copy;
- const Char *p;
-
- _DIAGASSERT(path != NULL);
- _DIAGASSERT(pglob != NULL);
-
- newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
- /* isaacs - added explicit cast */
- pathv = (char**) (pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) :
- malloc(newsize));
- if (pathv == NULL)
- return GLOB_NOSPACE;
-
- if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
- /* first time around -- clear initial gl_offs items */
- pathv += pglob->gl_offs;
- for (i = pglob->gl_offs + 1; --i > 0; )
- *--pathv = NULL;
- }
- pglob->gl_pathv = pathv;
-
- for (p = path; *p++;)
- continue;
- len = (size_t)(p - path);
- limit[GLOB_INDEX_MALLOC] += len;
- /* isaacs - added explicit cast */
- if ((copy = (char*)malloc(len)) != NULL) {
- if (g_Ctoc(path, copy, len)) {
- free(copy);
- return GLOB_ABORTED;
- }
- pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
- }
- pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) {
- errno = 0;
- return GLOB_NOSPACE;
- }
-
- return copy == NULL ? GLOB_NOSPACE : 0;
-}
-
-
-/*
- * pattern matching function for filenames. Each occurrence of the *
- * pattern causes a recursion level.
- */
-static int
-match(const Char *name, const Char *pat, const Char *patend)
-{
- int ok, negate_range;
- Char c, k;
-
- _DIAGASSERT(name != NULL);
- _DIAGASSERT(pat != NULL);
- _DIAGASSERT(patend != NULL);
-
- while (pat < patend) {
- c = *pat++;
- switch (c & M_MASK) {
- case M_ALL:
- while (pat < patend && (*pat & M_MASK) == M_ALL)
- pat++; /* eat consecutive '*' */
- if (pat == patend)
- return 1;
- for (; !match(name, pat, patend); name++)
- if (*name == EOS)
- return 0;
- return 1;
- case M_ONE:
- if (*name++ == EOS)
- return 0;
- break;
- case M_SET:
- ok = 0;
- if ((k = *name++) == EOS)
- return 0;
- if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
- ++pat;
- while (((c = *pat++) & M_MASK) != M_END)
- if ((*pat & M_MASK) == M_RNG) {
- if (c <= k && k <= pat[1])
- ok = 1;
- pat += 2;
- } else if (c == k)
- ok = 1;
- if (ok == negate_range)
- return 0;
- break;
- default:
- if (*name++ != c)
- return 0;
- break;
- }
- }
- return *name == EOS;
-}
-
-/* Free allocated data belonging to a glob_t structure. */
-void
-myglobfree(glob_t *pglob)
-{
- size_t i;
- char **pp;
-
- _DIAGASSERT(pglob != NULL);
-
- if (pglob->gl_pathv != NULL) {
- pp = pglob->gl_pathv + pglob->gl_offs;
- for (i = pglob->gl_pathc; i--; ++pp)
- if (*pp)
- free(*pp);
- free(pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- pglob->gl_pathc = 0;
- }
-}
-
-int
-myglob_pattern_p(const char *pattern, int quote)
-{
- int range = 0;
-
- for (; *pattern; pattern++)
- switch (*pattern) {
- case QUESTION:
- case STAR:
- return 1;
-
- case QUOTE:
- if (quote && pattern[1] != EOS)
- ++pattern;
- break;
-
- case LBRACKET:
- range = 1;
- break;
-
- case RBRACKET:
- if (range)
- return 1;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static DIR *
-g_opendir(Char *str, glob_t *pglob)
-{
- char buf[MAXPATHLEN];
-
- _DIAGASSERT(str != NULL);
- _DIAGASSERT(pglob != NULL);
-
- if (!*str)
- (void)strlcpy(buf, ".", sizeof(buf));
- else {
- if (g_Ctoc(str, buf, sizeof(buf)))
- return NULL;
- }
-
- /* isaacs - added explicit cast */
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return (DIR *)(*pglob->gl_opendir)(buf);
-
- /* isaacs - added explicit cast */
- return (DIR *)opendir(buf);
-}
-
-static int
-g_lstat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
-{
- char buf[MAXPATHLEN];
-
- _DIAGASSERT(fn != NULL);
- _DIAGASSERT(sb != NULL);
- _DIAGASSERT(pglob != NULL);
-
- if (g_Ctoc(fn, buf, sizeof(buf)))
- return -1;
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return (*pglob->gl_lstat)(buf, sb);
- return lstat(buf, sb);
-}
-
-static int
-g_stat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
-{
- char buf[MAXPATHLEN];
-
- _DIAGASSERT(fn != NULL);
- _DIAGASSERT(sb != NULL);
- _DIAGASSERT(pglob != NULL);
-
- if (g_Ctoc(fn, buf, sizeof(buf)))
- return -1;
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return (*pglob->gl_stat)(buf, sb);
- return stat(buf, sb);
-}
-
-static Char *
-g_strchr(const Char *str, int ch)
-{
-
- _DIAGASSERT(str != NULL);
-
- do {
- if (*str == ch)
- /* isaacs - added explicit cast */
- return (Char *)__UNCONST(str);
- } while (*str++);
- return NULL;
-}
-
-static int
-g_Ctoc(const Char *str, char *buf, size_t len)
-{
- char *dc;
-
- _DIAGASSERT(str != NULL);
- _DIAGASSERT(buf != NULL);
-
- if (len == 0)
- return 1;
-
- for (dc = buf; len && (*dc++ = *str++) != EOS; len--)
- continue;
-
- return len == 0;
-}
-
-#ifdef DEBUG
-static void
-qprintf(const char *str, Char *s)
-{
- Char *p;
-
- _DIAGASSERT(str != NULL);
- _DIAGASSERT(s != NULL);
-
- (void)printf("%s:\n", str);
- for (p = s; *p; p++)
- (void)printf("%c", CHAR(*p));
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", ismeta(*p) ? '_' : ' ');
- (void)printf("\n");
-}
-#endif
-
-#ifdef GLOB_STANDALONE
-int main (int argc, char **argv) {
- glob_t g;
- int i;
-
- g.gl_offs = 2;
- myglob("**", GLOB_DOOFFS|GLOB_STAR, NULL, &g);
-
- for (i = 0; i < g.gl_pathc; i ++) {
- fprintf(stderr, "glob found:%s\n", g.gl_pathv[i]);
- }
-}
-#endif
-
-/* isaacs */
-#ifdef __cplusplus
-}
-#endif
diff --git a/deps/glob/glob.h b/deps/glob/glob.h
deleted file mode 100644
index bf7ac19..0000000
--- a/deps/glob/glob.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* $NetBSD: glob.h,v 1.25.2.1 2010/10/22 07:11:52 uebayasi Exp $ */
-
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)glob.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _GLOB_H_
-#define _GLOB_H_
-
-/*
-#include <sys/cdefs.h>
-//#include <sys/featuretest.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-*/
-#include <stdlib.h>
-#include <stddef.h>
-
-#ifndef __gl_size_t
-#define __gl_size_t size_t
-#endif
-#ifndef __gl_stat_t
-#define __gl_stat_t struct stat
-#endif
-
-typedef struct {
- __gl_size_t gl_pathc; /* Count of total paths so far. */
- __gl_size_t gl_matchc; /* Count of paths matching pattern. */
- __gl_size_t gl_offs; /* Reserved at beginning of gl_pathv. */
- int gl_flags; /* Copy of flags parameter to glob. */
- char **gl_pathv; /* List of paths matching pattern. */
- /* Copy of errfunc parameter to glob. */
- int (*gl_errfunc)(const char *, int);
-
- /*
- * Alternate filesystem access methods for glob; replacement
- * versions of closedir(3), readdir(3), opendir(3), stat(2)
- * and lstat(2).
- */
- void (*gl_closedir)(void *);
- struct dirent *(*gl_readdir)(void *);
- void *(*gl_opendir)(const char *);
- int (*gl_lstat)(const char *, __gl_stat_t *);
- int (*gl_stat)(const char *, __gl_stat_t *);
-} glob_t;
-
-#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
-#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
-#define GLOB_ERR 0x0004 /* Return on error. */
-#define GLOB_MARK 0x0008 /* Append / to matching directories. */
-#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
-#define GLOB_NOSORT 0x0020 /* Don't sort. */
-#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */
-
-#define GLOB_NOSPACE (-1) /* Malloc call failed. */
-#define GLOB_ABORTED (-2) /* Unignored error. */
-#define GLOB_NOMATCH (-3) /* No match, and GLOB_NOCHECK was not set. */
-#define GLOB_NOSYS (-4) /* Implementation does not support function. */
-
-#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
-#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
-#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
-#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
-#define GLOB_LIMIT 0x0400 /* Limit memory used by matches to ARG_MAX */
-#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
-/* GLOB_NOESCAPE 0x1000 above */
-#define GLOB_PERIOD 0x2000 /* Allow metachars to match leading periods. */
-#define GLOB_NO_DOTDIRS 0x4000 /* Make . and .. vanish from wildcards. */
-#define GLOB_STAR 0x8000 /* Use glob ** to recurse directories */
-#define GLOB_QUOTE 0 /* source compatibility */
-
-#define GLOB_ABEND GLOB_ABORTED /* source compatibility */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-int myglob(const char * __restrict, int,
- int (*)(const char *, int), glob_t * __restrict);
-void myglobfree(glob_t *);
-int myglob_pattern_p(const char *, int);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_GLOB_H_ */
diff --git a/examples/g.js b/examples/g.js
new file mode 100644
index 0000000..be122df
--- /dev/null
+++ b/examples/g.js
@@ -0,0 +1,9 @@
+var Glob = require("../").Glob
+
+var pattern = "test/a/**/[cg]/../[cg]"
+console.log(pattern)
+
+var mg = new Glob(pattern, {mark: true, sync:true}, function (er, matches) {
+ console.log("matches", matches)
+})
+console.log("after")
diff --git a/examples/usr-local.js b/examples/usr-local.js
new file mode 100644
index 0000000..327a425
--- /dev/null
+++ b/examples/usr-local.js
@@ -0,0 +1,9 @@
+var Glob = require("../").Glob
+
+var pattern = "{./*/*,/*,/usr/local/*}"
+console.log(pattern)
+
+var mg = new Glob(pattern, {mark: true}, function (er, matches) {
+ console.log("matches", matches)
+})
+console.log("after")
diff --git a/glob.js b/glob.js
new file mode 100644
index 0000000..48262b5
--- /dev/null
+++ b/glob.js
@@ -0,0 +1,542 @@
+// Approach:
+//
+// 1. Get the minimatch set
+// 2. For each pattern in the set, PROCESS(pattern)
+// 3. Store matches per-set, then uniq them
+//
+// PROCESS(pattern)
+// Get the first [n] items from pattern that are all strings
+// Join these together. This is PREFIX.
+// If there is no more remaining, then stat(PREFIX) and
+// add to matches if it succeeds. END.
+// readdir(PREFIX) as ENTRIES
+// If fails, END
+// If pattern[n] is GLOBSTAR
+// // handle the case where the globstar match is empty
+// // by pruning it out, and testing the resulting pattern
+// PROCESS(pattern[0..n] + pattern[n+1 .. $])
+// // handle other cases.
+// for ENTRY in ENTRIES (not dotfiles)
+// // attach globstar + tail onto the entry
+// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $])
+//
+// else // not globstar
+// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
+// Test ENTRY against pattern[n+1]
+// If fails, continue
+// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
+//
+// Caveat:
+// Cache all stats and readdirs results to minimize syscall. Since all
+// we ever care about is existence and directory-ness, we can just keep
+// `true` for files, and [children,...] for directories, or `false` for
+// things that don't exist.
+
+
+
+module.exports = glob
+
+var fs = require("graceful-fs")
+, minimatch = require("minimatch")
+, Minimatch = minimatch.Minimatch
+, inherits = require("inherits")
+, EE = require("events").EventEmitter
+, path = require("path")
+, isDir = {}
+, assert = require("assert").ok
+
+function glob (pattern, options, cb) {
+ if (typeof options === "function") cb = options, options = {}
+ if (!options) options = {}
+
+ if (typeof options === "number") {
+ deprecated()
+ return
+ }
+
+ var g = new Glob(pattern, options, cb)
+ return g.sync ? g.found : g
+}
+
+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) {
+ // console.error("cb with matches", matches)
+ cb(null, matches)
+ })
+ }
+
+ options = options || {}
+
+ this.maxDepth = options.maxDepth || 1000
+ this.maxLength = options.maxLength || Infinity
+ this.statCache = options.statCache || {}
+
+ this.changedCwd = false
+ var cwd = process.cwd()
+ if (!options.hasOwnProperty("cwd")) this.cwd = cwd
+ else {
+ this.cwd = options.cwd
+ this.changedCwd = path.resolve(options.cwd) !== cwd
+ }
+
+ this.root = options.root || path.resolve(this.cwd, "/")
+ this.root = path.resolve(this.root)
+
+ this.nomount = !!options.nomount
+
+ if (!pattern) {
+ throw new Error("must provide pattern")
+ }
+
+ // base-matching: just use globstar for that.
+ if (options.matchBase && -1 === pattern.indexOf("/")) {
+ if (options.noglobstar) {
+ throw new Error("base matching requires globstar")
+ }
+ pattern = "**/" + pattern
+ }
+
+ this.dot = !!options.dot
+ this.mark = !!options.mark
+ this.sync = !!options.sync
+ this.nounique = !!options.nounique
+ this.nonull = !!options.nonull
+ this.nosort = !!options.nosort
+ this.nocase = !!options.nocase
+ this.stat = !!options.stat
+ this.debug = !!options.debug || !!options.globDebug
+ this.silent = !!options.silent
+
+ var mm = this.minimatch = new Minimatch(pattern, options)
+ this.options = mm.options
+ pattern = this.pattern = mm.pattern
+
+ this.error = null
+ this.aborted = false
+
+ EE.call(this)
+
+ // process each pattern in the minimatch set
+ var n = this.minimatch.set.length
+
+ // The matches are stored as {<filename>: true,...} so that
+ // duplicates are automagically pruned.
+ // Later, we do an Object.keys() on these.
+ // Keep them as a list so we can fill in when nonull is set.
+ this.matches = new Array(n)
+
+ this.minimatch.set.forEach(iterator.bind(this))
+ function iterator (pattern, i, set) {
+ this._process(pattern, 0, i, function (er) {
+ if (er) this.emit("error", er)
+ if (-- n <= 0) this._finish()
+ }.bind(this))
+ }
+}
+
+Glob.prototype._finish = function () {
+ assert(this instanceof Glob)
+
+ var nou = this.nounique
+ , all = nou ? [] : {}
+
+ for (var i = 0, l = this.matches.length; i < l; i ++) {
+ var matches = this.matches[i]
+ if (this.debug) console.error("matches[%d] =", i, matches)
+ // do like the shell, and spit out the literal glob
+ if (!matches) {
+ if (this.nonull) {
+ var literal = this.minimatch.globSet[i]
+ if (nou) all.push(literal)
+ else nou[literal] = true
+ }
+ } else {
+ // had matches
+ var m = Object.keys(matches)
+ if (nou) all.push.apply(all, m)
+ else m.forEach(function (m) {
+ all[m] = true
+ })
+ }
+ }
+
+ if (!nou) all = Object.keys(all)
+
+ if (!this.nosort) {
+ all = all.sort(this.nocase ? alphasorti : alphasort)
+ }
+
+ if (this.mark) {
+ // at *some* point we statted all of these
+ all = all.map(function (m) {
+ var sc = this.statCache[m]
+ if (!sc) return m
+ if (m.slice(-1) !== "/" && (Array.isArray(sc) || sc === 2)) {
+ return m + "/"
+ }
+ if (m.slice(-1) === "/") {
+ return m.replace(/\/$/, "")
+ }
+ return m
+ })
+ }
+
+ if (this.debug) console.error("emitting end", all)
+
+ this.found = all
+ this.emit("end", all)
+}
+
+function alphasorti (a, b) {
+ a = a.toLowerCase()
+ b = b.toLowerCase()
+ return alphasort(a, b)
+}
+
+function alphasort (a, b) {
+ return a > b ? 1 : a < b ? -1 : 0
+}
+
+Glob.prototype.abort = function () {
+ this.aborted = true
+ this.emit("abort")
+}
+
+
+Glob.prototype._process = function (pattern, depth, index, cb) {
+ assert(this instanceof Glob)
+ cb = cb.bind(this)
+ if (this.aborted) return cb()
+
+ if (depth > this.maxDepth) return cb()
+
+ // Get the first [n] parts of pattern that are all strings.
+ var n = 0
+ while (typeof pattern[n] === "string") {
+ n ++
+ }
+ // now n is the index of the first one that is *not* a string.
+
+ // see if there's anything else
+ var prefix
+ switch (n) {
+ // if not, then this is rather simple
+ case pattern.length:
+ prefix = pattern.join("/")
+ this._stat(prefix, function (exists, isDir) {
+ // either it's there, or it isn't.
+ // nothing more to do, either way.
+ if (exists) {
+ if (prefix.charAt(0) === "/" && !this.nomount) {
+ prefix = path.join(this.root, prefix)
+ }
+ this.matches[index] = this.matches[index] || {}
+ this.matches[index][prefix] = true
+ this.emit("match", prefix)
+ }
+ return cb()
+ })
+ return
+
+ case 0:
+ // pattern *starts* with some non-trivial item.
+ // going to readdir(cwd), but not include the prefix in matches.
+ prefix = null
+ break
+
+ default:
+ // pattern has some string bits in the front.
+ // whatever it starts with, whether that's "absolute" like /foo/bar,
+ // or "relative" like "../baz"
+ prefix = pattern.slice(0, n)
+ prefix = prefix.join("/")
+ break
+ }
+
+ // get the list of entries.
+ var read
+ if (prefix === null) read = "."
+ else if (isAbsolute(prefix)) {
+ read = prefix = path.join("/", prefix)
+ if (this.debug) console.error('absolute: ', prefix, this.root, pattern)
+ } else read = prefix
+
+ if (this.debug) console.error('readdir(%j)', read, this.cwd, this.root)
+ return this._readdir(read, function (er, entries) {
+ if (er) {
+ // not a directory!
+ // this means that, whatever else comes after this, it can never match
+ return cb()
+ }
+
+ // globstar is special
+ if (pattern[n] === minimatch.GLOBSTAR) {
+ // test without the globstar, and with every child both below
+ // and replacing the globstar.
+ var s = [ pattern.slice(0, n).concat(pattern.slice(n + 1)) ]
+ entries.forEach(function (e) {
+ if (e.charAt(0) === "." && !this.dot) return
+ // instead of the globstar
+ s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1)))
+ // below the globstar
+ s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n)))
+ }, this)
+
+ // now asyncForEach over this
+ var l = s.length
+ , errState = null
+ s.forEach(function (gsPattern) {
+ this._process(gsPattern, depth + 1, index, function (er) {
+ if (errState) return
+ if (er) return cb(errState = er)
+ if (--l <= 0) return cb()
+ })
+ }, this)
+
+ return
+ }
+
+ // not a globstar
+ // It will only match dot entries if it starts with a dot, or if
+ // dot is set. Stuff like @(.foo|.bar) isn't allowed.
+ var pn = pattern[n]
+ if (typeof pn === "string") {
+ var found = entries.indexOf(pn) !== -1
+ entries = found ? entries[pn] : []
+ } else {
+ var rawGlob = pattern[n]._glob
+ , dotOk = this.dot || rawGlob.charAt(0) === "."
+
+ entries = entries.filter(function (e) {
+ return (e.charAt(0) !== "." || dotOk) &&
+ (typeof pattern[n] === "string" && e === pattern[n] ||
+ e.match(pattern[n]))
+ })
+ }
+
+ // If n === pattern.length - 1, then there's no need for the extra stat
+ // *unless* the user has specified "mark" or "stat" explicitly.
+ // We know that they exist, since the readdir returned them.
+ if (n === pattern.length - 1 &&
+ !this.mark &&
+ !this.stat) {
+ entries.forEach(function (e) {
+ if (prefix) {
+ if (prefix !== "/") e = prefix + "/" + e
+ else e = prefix + e
+ }
+ if (e.charAt(0) === "/" && !this.nomount) {
+ e = path.join(this.root, e)
+ }
+
+ this.matches[index] = this.matches[index] || {}
+ this.matches[index][e] = true
+ this.emit("match", e)
+ }, this)
+ return cb.call(this)
+ }
+
+
+ // now test all the remaining entries as stand-ins for that part
+ // of the pattern.
+ var l = entries.length
+ , errState = null
+ if (l === 0) return cb() // no matches possible
+ entries.forEach(function (e) {
+ var p = pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1))
+ this._process(p, depth + 1, index, function (er) {
+ if (errState) return
+ if (er) return cb(errState = er)
+ if (--l === 0) return cb.call(this)
+ }.bind(this))
+ }, this)
+ })
+
+}
+
+Glob.prototype._stat = function (f, cb) {
+ assert(this instanceof Glob)
+ var abs = f
+ if (f.charAt(0) === "/") {
+ abs = path.join(this.root, f)
+ } else if (this.changedCwd) {
+ abs = path.resolve(this.cwd, f)
+ }
+ if (this.debug) console.error('stat', [this.cwd, f, '=', abs])
+ if (f.length > this.maxLength) {
+ var er = new Error("Path name too long")
+ er.code = "ENAMETOOLONG"
+ er.path = f
+ return this._afterStat(f, abs, cb, er)
+ }
+
+ if (this.statCache.hasOwnProperty(f)) {
+ var exists = this.statCache[f]
+ , isDir = exists && (Array.isArray(exists) || exists === 2)
+ if (this.sync) return cb.call(this, !!exists, isDir)
+ return process.nextTick(cb.bind(this, !!exists, isDir))
+ }
+
+ if (this.sync) {
+ var er, stat
+ try {
+ stat = fs.statSync(abs)
+ } catch (e) {
+ er = e
+ }
+ this._afterStat(f, abs, cb, er, stat)
+ } else {
+ fs.stat(abs, this._afterStat.bind(this, f, abs, cb))
+ }
+}
+
+Glob.prototype._afterStat = function (f, abs, cb, er, stat) {
+ assert(this instanceof Glob)
+ if (er || !stat) {
+ exists = false
+ } else {
+ exists = stat.isDirectory() ? 2 : 1
+ }
+ this.statCache[f] = this.statCache[f] || exists
+ cb.call(this, !!exists, exists === 2)
+}
+
+Glob.prototype._readdir = function (f, cb) {
+ assert(this instanceof Glob)
+ var abs = f
+ if (f.charAt(0) === "/") {
+ abs = path.join(this.root, f)
+ } else if (isAbsolute(f)) {
+ abs = f
+ } else if (this.changedCwd) {
+ abs = path.resolve(this.cwd, f)
+ }
+
+ if (this.debug) console.error('readdir', [this.cwd, f, abs])
+ if (f.length > this.maxLength) {
+ var er = new Error("Path name too long")
+ er.code = "ENAMETOOLONG"
+ er.path = f
+ return this._afterReaddir(f, abs, cb, er)
+ }
+
+ if (this.statCache.hasOwnProperty(f)) {
+ var c = this.statCache[f]
+ if (Array.isArray(c)) {
+ if (this.sync) return cb.call(this, null, c)
+ return process.nextTick(cb.bind(this, null, c))
+ }
+
+ if (!c || c === 1) {
+ // either ENOENT or ENOTDIR
+ var code = c ? "ENOTDIR" : "ENOENT"
+ , er = new Error((c ? "Not a directory" : "Not found") + ": " + f)
+ er.path = f
+ er.code = code
+ if (this.debug) console.error(f, er)
+ if (this.sync) return cb.call(this, er)
+ return process.nextTick(cb.bind(this, er))
+ }
+
+ // at this point, c === 2, meaning it's a dir, but we haven't
+ // had to read it yet, or c === true, meaning it's *something*
+ // but we don't have any idea what. Need to read it, either way.
+ }
+
+ if (this.sync) {
+ var er, entries
+ try {
+ entries = fs.readdirSync(abs)
+ } catch (e) {
+ er = e
+ }
+ return this._afterReaddir(f, abs, cb, er, entries)
+ }
+
+ fs.readdir(abs, this._afterReaddir.bind(this, f, abs, cb))
+}
+
+Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) {
+ assert(this instanceof Glob)
+ if (entries && !er) {
+ this.statCache[f] = entries
+ // if we haven't asked to stat everything for suresies, then just
+ // assume that everything in there exists, so we can avoid
+ // having to stat it a second time. This also gets us one step
+ // further into ELOOP territory.
+ if (!this.mark && !this.stat) {
+ entries.forEach(function (e) {
+ if (f === "/") e = f + e
+ else e = f + "/" + e
+ this.statCache[e] = true
+ }, this)
+ }
+
+ return cb.call(this, er, entries)
+ }
+
+ // now handle errors, and cache the information
+ if (er) switch (er.code) {
+ case "ENOTDIR": // totally normal. means it *does* exist.
+ this.statCache[f] = 1
+ return cb.call(this, er)
+ case "ENOENT": // not terribly unusual
+ case "ELOOP":
+ case "ENAMETOOLONG":
+ case "UNKNOWN":
+ this.statCache[f] = false
+ return cb.call(this, er)
+ default: // some unusual error. Treat as failure.
+ this.statCache[f] = false
+ if (this.strict) this.emit("error", er)
+ if (!this.silent) console.error("glob error", er)
+ return cb.call(this, er)
+ }
+}
+
+var isAbsolute = process.platform === "win32" ? absWin : absUnix
+
+function absWin (p) {
+ if (absUnix(p)) return true
+ // pull off the device/UNC bit from a windows path.
+ // from node's lib/path.js
+ var splitDeviceRe =
+ /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
+ , result = splitDeviceRe.exec(p)
+ , device = result[1] || ''
+ , isUnc = device && device.charAt(1) !== ':'
+ , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
+
+ return isAbsolute
+}
+
+function absUnix (p) {
+ return p.charAt(0) === "/" || p === ""
+}
diff --git a/lib/glob.js b/lib/glob.js
deleted file mode 100644
index 07de722..0000000
--- a/lib/glob.js
+++ /dev/null
@@ -1,81 +0,0 @@
-// the nice wrapper around the raw C++ binding.
-
-var binding = require(process.env.GLOB_DEBUG != undefined
- ? "../build/default/glob_g"
- : "../build/default/glob")
-
-module.exports = glob
-glob.glob = glob
-glob.globSync = glob.sync = globSync
-glob.fnmatch = fnmatch
-
-Object.keys(binding)
- .filter(function (k) { return k.match(/^GLOB_/) })
- .forEach(function (k) {
- glob[k] = globSync[k] = binding[k]
- globSync[binding[k]] = glob[binding[k]] = k
- })
-
-Object.keys(binding)
- .filter(function (k) { return k.match(/^FNM_/) })
- .forEach(function (k) {
- fnmatch[k] = glob[k] = binding[k]
- fnmatch[binding[k]] = k
- })
-
-// sane defaults.
-glob.FNM_DEFAULT = binding.FNM_PATHNAME | binding.FNM_PERIOD
-fnmatch.FNM_DEFAULT = glob.FNM_DEFAULT
-fnmatch[fnmatch.FNM_DEFAULT] = "FNM_DEFAULT"
-
-glob.GLOB_DEFAULT = binding.GLOB_BRACE
- | binding.GLOB_STAR
- | binding.GLOB_MARK
- | binding.GLOB_TILDE
-globSync.GLOB_DEFAULT = glob.GLOB_DEFAULT
-glob[glob.GLOB_DEFAULT] = globSync[glob.GLOB_DEFAULT] = "GLOB_DEFAULT"
-
-function glob (pattern, flags, cb) {
- // console.log("glob", pattern, flags, cb)
- if (typeof cb !== "function") cb = flags, flags = null
- if (typeof cb !== "function") throw new Error(
- "usage: glob(pattern, [flags,] cb)")
-
- if (!flags) flags = glob.GLOB_DEFAULT
-
- // console.log("glob", pattern, flags, cb)
- return binding.glob(pattern, flags, function (er, matches) {
- // console.log("back from binding", er, matches)
- // swallow this error, since it's really not such a big deal.
- if (er && er.message === "GLOB_NOMATCH") matches = [], er = null
- if (er && glob.hasOwnProperty(er.message)) {
- er.errno = glob[er.message]
- }
- cb(er, matches)
- })
-}
-
-function globSync (pattern, flags) {
- if (!flags) flags = glob.GLOB_DEFAULT
- if (typeof pattern !== "string") throw new Error(
- "usage: globSync(pattern [, flags])")
- try {
- return binding.globSync(pattern, flags)
- } catch (er) {
- if (er.message === "GLOB_NOMATCH") return []
- if (glob.hasOwnProperty(er.message)) {
- er.errno = glob[er.message]
- }
- throw er
- }
-}
-
-function fnmatch (pattern, str, flags) {
- if (typeof flags !== "number") {
- flags = glob.FNM_DEFAULT
- }
- var res = binding.fnmatch(pattern, str, flags)
- if (res === 0) return true
- if (res === binding.FNM_NOMATCH) return false
- throw new Error("fnmatch error "+res)
-}
diff --git a/package.json b/package.json
index 2f44041..349644d 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,27 @@
-{ "name" : "glob"
-, "description" : "glob/fnmatch binding for node"
-, "author" : "Isaac Z. Schlueter <i at izs.me> (http://blog.izs.me/)"
-, "version" : "2.0.9"
-, "main" : "./lib/glob"
-, "repository" : "git://github.com/isaacs/node-glob.git"
-, "homepage" : "https://github.com/isaacs/node-glob"
-, "keywords" : ["glob", "pattern", "match", "filesystem", "posix", "fnmatch"]
-, "bugs" : { "web" : "https://github.com/isaacs/node-glob/issues" }
-, "engines": { "node": "0.4" }
+{
+ "author": "Isaac Z. Schlueter <i at izs.me> (http://blog.izs.me/)",
+ "name": "glob",
+ "description": "a little globber",
+ "version": "3.1.6",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/isaacs/node-glob.git"
+ },
+ "main": "glob.js",
+ "engines": {
+ "node": "*"
+ },
+ "dependencies": {
+ "minimatch": "0.2",
+ "graceful-fs": "~1.1.2",
+ "inherits": "1"
+ },
+ "devDependencies": {
+ "tap": "~0.2.3",
+ "mkdirp":"0",
+ "rimraf":"1"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ }
}
diff --git a/src/glob.cc b/src/glob.cc
deleted file mode 100644
index 17ba568..0000000
--- a/src/glob.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// exposes the glob function to node.
-
-// int
-// myglob(const char *restrict pattern, int flags,
-// int (*errfunc)(const char *epath, int errno), glob_t *restrict pglob);
-
-#include "glob_constants.h"
-#include <glob.h>
-#include <v8.h>
-#include <node.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-using namespace std;
-using namespace node;
-using namespace v8;
-
-#ifdef DEBUG
-# define debug_p(a,b) ((NULL != (void *)b) ? fprintf(stderr, a, b) : fprintf(stderr, a, ""))
-# define ASSERT(x) assert(x)
-#else
-# define debug_p(a,b)
-# define ASSERT(x)
-#endif
-
-
-static Handle<String>
-GlobError (int er) {
- switch (er) {
- case GLOB_ABORTED: return String::New("GLOB_ABORTED"); break;
- case GLOB_NOMATCH: return String::New("GLOB_NOMATCH"); break;
- case GLOB_NOSPACE: return String::New("GLOB_NOSPACE"); break;
- }
-
- return String::New("undefined glob error");
-}
-
-
-static Handle<Value> Throw (int);
-static Handle<Value> Throw (const char*);
-static Handle<Value> Throw (Handle<String>);
-
-static Handle<Value>
-Throw (int msg) {
- return Throw(GlobError(msg));
-}
-static Handle<Value>
-Throw (const char* msg) {
- return Throw(String::New(msg));
-}
-static Handle<Value>
-Throw (Handle<String> msg) {
- ThrowException(Exception::Error(msg));
-}
-
-
-// binding to fnmatch
-// Not really glob-specific, but useful if you're doing globbing.
-// int fnmatch(const char *pattern, const char *string, int flags);
-static Handle<Value> FNMatch (const Arguments& args) {
- if (args.Length() != 3) return Throw(
- "usage: fnmatch(pattern, string, flags)");
-
- String::Utf8Value pattern(args[0]);
- String::Utf8Value str(args[1]);
- int flags = args[2]->Int32Value();
-
- int res = fnmatch(*pattern, *str, flags);
-
- return Integer::New(res);
-}
-
-
-// async EIO globbing
-struct glob_request {
- Persistent<Function> cb;
- glob_t *g;
- int retval;
- int flags;
- char pattern[1];
-};
-static int EIO_Glob (eio_req *req) {
- glob_request *gr = (glob_request *)req->data;
- debug_p("EIO_Glob pattern=%s\n", gr->pattern);
- gr->retval = myglob(gr->pattern, gr->flags, NULL, gr->g);
- debug_p("EIO_Glob retval=%i\n", gr->retval);
- return 0;
-}
-static int EIO_GlobAfter (eio_req *req) {
- HandleScope scope;
- ev_unref(EV_DEFAULT_UC);
- glob_request *gr = (glob_request *)req->data;
- glob_t *g = gr->g;
-
- Local<Value> argv[2];
- debug_p("EIO_GlobAfter pattern=%s\n", gr->pattern);
- if (gr->retval != 0) {
- argv[0] = Exception::Error(GlobError(gr->retval));
- argv[1] = String::New(gr->pattern);
- debug_p("EIO_GlobAfter error=%i\n", gr->retval);
- } else {
- Local<Array> pathv = Array::New(g->gl_pathc);
- for (int i = 0; i < g->gl_pathc; i ++) {
- debug_p("EIO_GlobAfter path=%s\n", g->gl_pathv[i]);
- pathv->Set(Integer::New(i), String::New(g->gl_pathv[i]));
- }
- argv[0] = Local<Value>::New(Null());
- argv[1] = pathv;
- }
-
- TryCatch try_catch;
- debug_p("EIO_GlobAfter calling cb%s\n", "");
- gr->cb->Call(Context::GetCurrent()->Global(), 2, argv);
- if (try_catch.HasCaught()) {
- debug_p("EIO_GlobAfter cb threw%s\n", "");
- FatalException(try_catch);
- }
- gr->cb.Dispose();
- debug_p("EIO_GlobAfter globfreeing %i\n", g);
- myglobfree(g);
- debug_p("EIO_GlobAfter freeing %i\n", gr);
- free(gr);
- return 0;
-}
-static Handle<Value> GlobAsync (const Arguments& args) {
- HandleScope scope;
- const char *usage = "usage: glob(pattern, flags, cb)";
-
- if (args.Length() != 3) {
- Throw(usage);
- }
-
- String::Utf8Value pattern(args[0]);
-
- int flags = args[1]->Int32Value();
- Local<Function> cb = Local<Function>::Cast(args[2]);
-
- glob_request *gr = (glob_request *)
- calloc(1, sizeof(struct glob_request) + pattern.length() + 1);
-
- debug_p("GlobAsync gr=%i\n", gr);
-
- ASSERT(gr != NULL);
-
- gr->cb = Persistent<Function>::New(cb);
- strncpy(gr->pattern, *pattern, pattern.length() + 1);
- gr->flags = flags;
- gr->g = new glob_t;
- eio_req* eioret = eio_custom(EIO_Glob, EIO_PRI_DEFAULT, EIO_GlobAfter, gr);
- debug_p("GlobAsync eioret=%i\n", eioret);
- ev_ref(EV_DEFAULT_UC);
-
- return Undefined();
-}
-
-// synchronous globbing.
-static Handle<Value> GlobSync (const Arguments& args) {
- HandleScope scope;
- const char * usage = "usage: globSync(pattern, flags)";
- if (args.Length() != 2) {
- return Throw(usage);
- }
-
- String::Utf8Value pattern(args[0]);
-
- int flags = args[1]->Int32Value();
-
- debug_p("GlobSync pattern=%s\n", *pattern);
- debug_p("GlobSync flags=%i\n", flags);
- glob_t g;
- int retval = myglob(*pattern, flags, NULL, &g);
-
- if (retval != 0) {
- debug_p("GlobSync fail: %i", retval);
- if (retval != GLOB_NOSPACE) myglobfree(&g);
- return Throw(retval);
- }
-
- // create a JS array
- // loop through the g.gl_pathv adding JS strings to the JS array.
- // then return the JS array.
- Handle<Array> pathv = Array::New(g.gl_pathc);
- for (int i = 0; i < g.gl_pathc; i ++) {
- debug_p("GlobSync path=%s\n", g.gl_pathv[i]);
- pathv->Set(Integer::New(i), String::New(g.gl_pathv[i]));
- }
-
- debug_p("GlobSync freeing%s\n", "");
- myglobfree(&g);
- return scope.Close(pathv);
-}
-
-
-extern "C" void
-init (Handle<Object> target)
-{
- HandleScope scope;
- GlobConstants(target);
- NODE_SET_METHOD(target, "glob", GlobAsync);
- NODE_SET_METHOD(target, "globSync", GlobSync);
- NODE_SET_METHOD(target, "fnmatch", FNMatch);
-}
-
diff --git a/src/glob_constants.h b/src/glob_constants.h
deleted file mode 100644
index 71ef667..0000000
--- a/src/glob_constants.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <glob.h>
-#include <fnmatch.h>
-#include <v8.h>
-#include <node.h>
-
-using namespace node;
-using namespace v8;
-
-void
-GlobConstants (Handle<Object> target) {
- // flags
- // These are defined in deps/fnmatch/fnmatch.h and deps/glob/glob.h
-
-// these are actually useless, because the glob_t object isn't exposed
-// to the javascript layer. Since it's so trivial to concatenate
-// arrays in JS anyway, it's a bit silly to even bother with this.
-// NODE_DEFINE_CONSTANT(target, GLOB_APPEND);
-// NODE_DEFINE_CONSTANT(target, GLOB_DOOFFS);
-
-// this is useless as well, because there is no way to supply the errfunc
-// function to glob(). It's just handled like the rest of node, passing
-// an Error() obj to the cb.
-// NODE_DEFINE_CONSTANT(target, GLOB_ERR);
-
-// Not supported, since the glob_t object isn't exposed directly.
-// NODE_DEFINE_CONSTANT(target, GLOB_ALTDIRFUNC);
-
-NODE_DEFINE_CONSTANT(target, GLOB_MARK);
-NODE_DEFINE_CONSTANT(target, GLOB_NOCHECK);
-NODE_DEFINE_CONSTANT(target, GLOB_NOSORT);
-NODE_DEFINE_CONSTANT(target, GLOB_NOESCAPE);
-
-NODE_DEFINE_CONSTANT(target, GLOB_NOSPACE);
-NODE_DEFINE_CONSTANT(target, GLOB_ABORTED);
-NODE_DEFINE_CONSTANT(target, GLOB_NOMATCH);
-NODE_DEFINE_CONSTANT(target, GLOB_NOSYS);
-
-NODE_DEFINE_CONSTANT(target, GLOB_BRACE);
-NODE_DEFINE_CONSTANT(target, GLOB_MAGCHAR);
-NODE_DEFINE_CONSTANT(target, GLOB_NOMAGIC);
-NODE_DEFINE_CONSTANT(target, GLOB_LIMIT);
-NODE_DEFINE_CONSTANT(target, GLOB_TILDE);
-
-NODE_DEFINE_CONSTANT(target, GLOB_PERIOD);
-NODE_DEFINE_CONSTANT(target, GLOB_NO_DOTDIRS);
-NODE_DEFINE_CONSTANT(target, GLOB_STAR);
-NODE_DEFINE_CONSTANT(target, GLOB_QUOTE);
-NODE_DEFINE_CONSTANT(target, GLOB_ABEND);
-
-// the fnmatch stuff
-NODE_DEFINE_CONSTANT(target, FNM_NOMATCH);
-NODE_DEFINE_CONSTANT(target, FNM_NOSYS);
-NODE_DEFINE_CONSTANT(target, FNM_NORES);
-NODE_DEFINE_CONSTANT(target, FNM_NOESCAPE);
-NODE_DEFINE_CONSTANT(target, FNM_PATHNAME);
-NODE_DEFINE_CONSTANT(target, FNM_PERIOD);
-NODE_DEFINE_CONSTANT(target, FNM_CASEFOLD);
-NODE_DEFINE_CONSTANT(target, FNM_LEADING_DIR);
-
-}
diff --git a/test/00-setup.js b/test/00-setup.js
new file mode 100644
index 0000000..2b60643
--- /dev/null
+++ b/test/00-setup.js
@@ -0,0 +1,61 @@
+// 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()
+ })
+ })
+})
diff --git a/test/bash-comparison.js b/test/bash-comparison.js
new file mode 100644
index 0000000..86a3d8b
--- /dev/null
+++ b/test/bash-comparison.js
@@ -0,0 +1,119 @@
+// 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/**"
+ ,"{./*/*,/usr/local/*}"
+ ,"{/*,*}" // evil owl face! how you taunt me!
+ ]
+, 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
+ }, []).sort(alphasort)
+ }
+ next()
+ })
+
+ glob(pattern, function (er, matches) {
+ // sort and unpark, just to match the shell results
+ matches = matches.map(function (m) {
+ return m.replace(/\/+/g, "/").replace(/\/$/, "")
+ }).sort(alphasort).reduce(function (set, f) {
+ if (f !== set[set.length - 1]) set.push(f)
+ return set
+ }, []).sort(alphasort)
+
+ 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) {
+ var matches = glob.sync(pattern).map(function (m) {
+ return m.replace(/\/+/g, "/").replace(/\/$/, "")
+ }).sort(alphasort).reduce(function (set, f) {
+ if (f !== set[set.length - 1]) set.push(f)
+ return set
+ }, []).sort(alphasort)
+
+ t.deepEqual(matches, 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()
+}
diff --git a/test/cwd-test.js b/test/cwd-test.js
new file mode 100644
index 0000000..352c27e
--- /dev/null
+++ b/test/cwd-test.js
@@ -0,0 +1,55 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing cwd and searching for **/d", function (t) {
+ var glob = require('../')
+ var path = require('path')
+ t.test('.', function (t) {
+ glob('**/d', function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
+ t.end()
+ })
+ })
+
+ t.test('a', function (t) {
+ glob('**/d', {cwd:path.resolve('a')}, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ 'b/c/d', 'c/d' ])
+ t.end()
+ })
+ })
+
+ t.test('a/b', function (t) {
+ glob('**/d', {cwd:path.resolve('a/b')}, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ 'c/d' ])
+ t.end()
+ })
+ })
+
+ t.test('a/b/', function (t) {
+ glob('**/d', {cwd:path.resolve('a/b/')}, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ 'c/d' ])
+ t.end()
+ })
+ })
+
+ t.test('.', function (t) {
+ glob('**/d', {cwd: process.cwd()}, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
+ t.end()
+ })
+ })
+
+ t.test('cd -', function (t) {
+ process.chdir(origCwd)
+ t.end()
+ })
+
+ t.end()
+})
diff --git a/test/foo/bar b/test/foo/bar
deleted file mode 100644
index e69de29..0000000
diff --git a/test/foo/baz/bar b/test/foo/baz/bar
deleted file mode 100644
index e69de29..0000000
diff --git a/test/foo/baz/quux/bar b/test/foo/baz/quux/bar
deleted file mode 100644
index e69de29..0000000
diff --git a/test/root-nomount.js b/test/root-nomount.js
new file mode 100644
index 0000000..3ac5979
--- /dev/null
+++ b/test/root-nomount.js
@@ -0,0 +1,39 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing root and searching for /b*/**", function (t) {
+ var glob = require('../')
+ var path = require('path')
+ t.test('.', function (t) {
+ glob('/b*/**', { globDebug: true, root: '.', nomount: true }, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [])
+ t.end()
+ })
+ })
+
+ t.test('a', function (t) {
+ glob('/b*/**', { globDebug: true, root: path.resolve('a'), nomount: true }, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
+ t.end()
+ })
+ })
+
+ t.test('root=a, cwd=a/b', function (t) {
+ glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b'), nomount: true }, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
+ t.end()
+ })
+ })
+
+ t.test('cd -', function (t) {
+ process.chdir(origCwd)
+ t.end()
+ })
+
+ t.end()
+})
diff --git a/test/root.js b/test/root.js
new file mode 100644
index 0000000..5ccdd0e
--- /dev/null
+++ b/test/root.js
@@ -0,0 +1,43 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing root and searching for /b*/**", function (t) {
+ var glob = require('../')
+ var path = require('path')
+ t.test('.', function (t) {
+ glob('/b*/**', { globDebug: true, root: '.' }, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [])
+ t.end()
+ })
+ })
+
+ t.test('a', function (t) {
+ glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
+ return path.join(path.resolve('a'), m)
+ }))
+ t.end()
+ })
+ })
+
+ t.test('root=a, cwd=a/b', function (t) {
+ glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b') }, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
+ return path.join(path.resolve('a'), m)
+ }))
+ t.end()
+ })
+ })
+
+ t.test('cd -', function (t) {
+ process.chdir(origCwd)
+ t.end()
+ })
+
+ t.end()
+})
diff --git a/test/test.js b/test/test.js
deleted file mode 100644
index a39470b..0000000
--- a/test/test.js
+++ /dev/null
@@ -1,83 +0,0 @@
-var g = require("../lib/glob")
-
-process.chdir(__dirname)
-
-var failures = 0
-
-function testSync(pattern, flags) {
- console.error("testing: %j %j", pattern, flags)
- console.error(g.globSync(pattern, flags))
-}
-try {
- testSync("*", 0)
- testSync("*/*.js", 0)
- testSync("lib/*", 0)
- testSync("~/*", g.GLOB_TILDE)
- testSync("foo/**/bar")
-} catch (ex) {
- console.error(ex.stack)
- failures ++
-}
-
-function testAsync (pattern, flags, cb) {
- if (!cb) cb = flags, flags = undefined
- console.error("testing async: %j %j", pattern, flags)
- g.glob(pattern, flags, function (er, m) {
- if (er) {
- console.error(" FAIL: "+(er.stack||er.message))
- failures ++
- } else console.error(" %j", m)
- cb()
- })
-}
-
-function testAsyncList (list, cb) {
- next()
- function next (er, m) {
- var test = list.shift()
- if (!test) return cb()
- test.push(cb)
- testAsync.apply(null, test)
- }
-}
-
-testAsyncList
- ([["*", 0]
- ,["../*/*.js", 0]
- ,["../lib/*", 0]
- ,["~/*", g.GLOB_DEFAULT | g.GLOB_TILDE]
- ,["foo/**/bar"]
- ]
- ,testFnmatch)
-
-function f (pattern, str, flags, expect) {
- if (arguments.length === 3) expect = flags, flags = undefined
- var actual = g.fnmatch(pattern, str, flags)
- if (actual !== expect) {
- console.error("Fail: "+JSON.stringify([pattern,str,flags]) + " expected "+expect + " actual "+actual)
- failures ++
- }
- console.error("%s, %s, %s => %j", pattern, str, flags, expect)
-}
-
-function testFnmatch () {
- f("*", "foo", true)
- f(".*", "foo", false)
- f("*", ".foo", false)
- f("*", "foo/bar", false)
- f("*/*", "foo/bar", true)
- f("*", ".foo", g.FNM_DEFAULT & ~g.FNM_PERIOD, true)
- f("*/*", "foo/bar", g.FNM_DEFAULT & ~g.FNM_PATHNAME, true)
- f("**/bar", "foo/bar", true)
- f("**/bar", "foo/baz/bar", true)
- f("foo/**/bar", "foo/bar/baz/quux/bar", true)
- done()
-}
-
-function done () {
- if (failures === 0) console.log("ok")
- else {
- console.error("Failures: %j", failures)
- process.exit(failures)
- }
-}
diff --git a/test/zz-cleanup.js b/test/zz-cleanup.js
new file mode 100644
index 0000000..e085f0f
--- /dev/null
+++ b/test/zz-cleanup.js
@@ -0,0 +1,11 @@
+// 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()
+ })
+})
diff --git a/wscript b/wscript
deleted file mode 100644
index 0d46a3a..0000000
--- a/wscript
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python
-srcdir = "."
-blddir = "build"
-VERSION = "0.0.1"
-
-def set_options(opt):
- opt.tool_options("compiler_cxx")
-
-def configure(conf):
- conf.check_tool("compiler_cxx")
- conf.check_tool("node_addon")
-
-def build(bld):
- ### bsd_glob
- bsd_glob = bld.new_task_gen("cxx")
- bsd_glob.source = "deps/glob/glob.c"
- bsd_glob.includes = "deps/glob/"
- bsd_glob.name = "bsd_glob"
- bsd_glob.target = "bsd_glob"
- bsd_glob.install_path = None
- bsd_glob.cxxflags = ["-fPIC"]
-
- ### bsd_fnmatch
- bsd_fnmatch = bld.new_task_gen("cxx")
- bsd_fnmatch.source = "deps/fnmatch/fnmatch.c"
- bsd_fnmatch.includes = "deps/fnmatch/"
- bsd_fnmatch.name = "bsd_fnmatch"
- bsd_fnmatch.target = "bsd_fnmatch"
- bsd_fnmatch.install_path = None
- bsd_fnmatch.cxxflags = ["-fPIC"]
-
- obj = bld.new_task_gen("cxx", "shlib", "node_addon")
- obj.add_objects = "bsd_glob bsd_fnmatch"
- obj.includes = """
- src/
- deps/glob/
- deps/fnmatch/
- """
- obj.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE"]
- obj.target = "glob"
- obj.source = "src/glob.cc"
-
- ### debug versions
- bsd_glob_debug = bld.new_task_gen("cxx")
- bsd_glob_debug.source = bsd_glob.source
- bsd_glob_debug.includes = bsd_glob.includes
- bsd_glob_debug.name = "bsd_glob_debug"
- bsd_glob_debug.target = "bsd_glob_debug"
- bsd_glob_debug.install_path = None
- bsd_glob_debug.cxxflags = ["-fPIC", "-DDEBUG"]
-
- bsd_fnmatch_debug = bld.new_task_gen("cxx")
- bsd_fnmatch_debug.source = bsd_fnmatch.source
- bsd_fnmatch_debug.includes = bsd_fnmatch.includes
- bsd_fnmatch_debug.name = "bsd_fnmatch_debug"
- bsd_fnmatch_debug.target = "bsd_fnmatch_debug"
- bsd_fnmatch_debug.install_path = None
- bsd_fnmatch_debug.cxxflags = ["-fPIC", "-DDEBUG"]
-
- obj_debug = bld.new_task_gen("cxx", "shlib", "node_addon")
- obj_debug.add_objects = "bsd_glob_debug bsd_fnmatch_debug"
- obj_debug.includes = obj.includes
- obj_debug.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-DDEBUG"]
- obj_debug.target = "glob_g"
- obj_debug.source = obj.source
--
glob/fnmatch binding for NodeJS
More information about the Pkg-javascript-commits
mailing list