]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore/ignore.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / node_modules / fstream-npm / node_modules / fstream-ignore / ignore.js
1 // Essentially, this is a fstream.DirReader class, but with a
2 // bit of special logic to read the specified sort of ignore files,
3 // and a filter that prevents it from picking up anything excluded
4 // by those files.
5
6 var Minimatch = require("minimatch").Minimatch
7 , fstream = require("fstream")
8 , DirReader = fstream.DirReader
9 , inherits = require("inherits")
10 , path = require("path")
11 , fs = require("fs")
12
13 module.exports = IgnoreReader
14
15 inherits(IgnoreReader, DirReader)
16
17 function IgnoreReader (props) {
18   if (!(this instanceof IgnoreReader)) {
19     return new IgnoreReader(props)
20   }
21
22   // must be a Directory type
23   if (typeof props === "string") {
24     props = { path: path.resolve(props) }
25   }
26
27   props.type = "Directory"
28   props.Directory = true
29
30   if (!props.ignoreFiles) props.ignoreFiles = [".ignore"]
31   this.ignoreFiles = props.ignoreFiles
32
33   this.ignoreRules = null
34
35   // ensure that .ignore files always show up at the top of the list
36   // that way, they can be read before proceeding to handle other
37   // entries in that same folder
38   if (props.sort) {
39     this._sort = props.sort === "alpha" ? alphasort : props.sort
40     props.sort = null
41   }
42
43   this.on("entries", function () {
44     // if there are any ignore files in the list, then
45     // pause and add them.
46     // then, filter the list based on our ignoreRules
47
48     var hasIg = this.entries.some(this.isIgnoreFile, this)
49
50     if (!hasIg) return this.filterEntries()
51
52     this.addIgnoreFiles()
53   })
54
55   // we filter entries before we know what they are.
56   // however, directories have to be re-tested against
57   // rules with a "/" appended, because "a/b/" will only
58   // match if "a/b" is a dir, and not otherwise.
59   this.on("_entryStat", function (entry, props) {
60     var t = entry.basename
61     if (!this.applyIgnores(entry.basename,
62                            entry.type === "Directory",
63                            entry)) {
64       entry.abort()
65     }
66   }.bind(this))
67
68   DirReader.call(this, props)
69 }
70
71
72 IgnoreReader.prototype.addIgnoreFiles = function () {
73   if (this._paused) {
74     this.once("resume", this.addIgnoreFiles)
75     return
76   }
77   if (this._ignoreFilesAdded) return
78   this._ignoreFilesAdded = true
79
80   var newIg = this.entries.filter(this.isIgnoreFile, this)
81   , count = newIg.length
82   , errState = null
83
84   if (!count) return
85
86   this.pause()
87
88   var then = function (er) {
89     if (errState) return
90     if (er) return this.emit("error", errState = er)
91     if (-- count === 0) {
92       this.filterEntries()
93       this.resume()
94     } else {
95       this.addIgnoreFile(newIg[newIg.length - count], then)
96     }
97   }.bind(this)
98
99   this.addIgnoreFile(newIg[0], then)
100 }
101
102
103 IgnoreReader.prototype.isIgnoreFile = function (e) {
104   return e !== "." &&
105          e !== ".." &&
106          -1 !== this.ignoreFiles.indexOf(e)
107 }
108
109
110 IgnoreReader.prototype.getChildProps = function (stat) {
111   var props = DirReader.prototype.getChildProps.call(this, stat)
112   props.ignoreFiles = this.ignoreFiles
113
114   // Directories have to be read as IgnoreReaders
115   // otherwise fstream.Reader will create a DirReader instead.
116   if (stat.isDirectory()) {
117     props.type = this.constructor
118   }
119   return props
120 }
121
122
123 IgnoreReader.prototype.addIgnoreFile = function (e, cb) {
124   // read the file, and then call addIgnoreRules
125   // if there's an error, then tell the cb about it.
126
127   var ig = path.resolve(this.path, e)
128   fs.readFile(ig, function (er, data) {
129     if (er) return cb(er)
130
131     this.emit("ignoreFile", e, data)
132     var rules = this.readRules(data, e)
133     this.addIgnoreRules(rules, e)
134     cb()
135   }.bind(this))
136 }
137
138
139 IgnoreReader.prototype.readRules = function (buf, e) {
140   return buf.toString().split(/\r?\n/)
141 }
142
143
144 // Override this to do fancier things, like read the
145 // "files" array from a package.json file or something.
146 IgnoreReader.prototype.addIgnoreRules = function (set, e) {
147   // filter out anything obvious
148   set = set.filter(function (s) {
149     s = s.trim()
150     return s && !s.match(/^#/)
151   })
152
153   // no rules to add!
154   if (!set.length) return
155
156   // now get a minimatch object for each one of these.
157   // Note that we need to allow dot files by default, and
158   // not switch the meaning of their exclusion
159   var mmopt = { matchBase: true, dot: true, flipNegate: true }
160   , mm = set.map(function (s) {
161     var m = new Minimatch(s, mmopt)
162     m.ignoreFile = e
163     return m
164   })
165
166   if (!this.ignoreRules) this.ignoreRules = []
167   this.ignoreRules.push.apply(this.ignoreRules, mm)
168 }
169
170
171 IgnoreReader.prototype.filterEntries = function () {
172   // this exclusion is at the point where we know the list of
173   // entries in the dir, but don't know what they are.  since
174   // some of them *might* be directories, we have to run the
175   // match in dir-mode as well, so that we'll pick up partials
176   // of files that will be included later.  Anything included
177   // at this point will be checked again later once we know
178   // what it is.
179   this.entries = this.entries.filter(function (entry) {
180     // at this point, we don't know if it's a dir or not.
181     return this.applyIgnores(entry) || this.applyIgnores(entry, true)
182   }, this)
183 }
184
185
186 IgnoreReader.prototype.applyIgnores = function (entry, partial, obj) {
187   var included = true
188
189   // this = /a/b/c
190   // entry = d
191   // parent /a/b sees c/d
192   if (this.parent && this.parent.applyIgnores) {
193     var pt = this.basename + "/" + entry
194     included = this.parent.applyIgnores(pt, partial)
195   }
196
197   // Negated Rules
198   // Since we're *ignoring* things here, negating means that a file
199   // is re-included, if it would have been excluded by a previous
200   // rule.  So, negated rules are only relevant if the file
201   // has been excluded.
202   //
203   // Similarly, if a file has been excluded, then there's no point
204   // trying it against rules that have already been applied
205   //
206   // We're using the "flipnegate" flag here, which tells minimatch
207   // to set the "negate" for our information, but still report
208   // whether the core pattern was a hit or a miss.
209
210   if (!this.ignoreRules) {
211     return included
212   }
213
214   this.ignoreRules.forEach(function (rule) {
215     // negation means inclusion
216     if (rule.negate && included ||
217         !rule.negate && !included) {
218       // unnecessary
219       return
220     }
221
222     // first, match against /foo/bar
223     var match = rule.match("/" + entry)
224
225     if (!match) {
226       // try with the leading / trimmed off the test
227       // eg: foo/bar instead of /foo/bar
228       match = rule.match(entry)
229     }
230
231     // if the entry is a directory, then it will match
232     // with a trailing slash. eg: /foo/bar/ or foo/bar/
233     if (!match && partial) {
234       match = rule.match("/" + entry + "/") ||
235               rule.match(entry + "/")
236     }
237
238     // When including a file with a negated rule, it's
239     // relevant if a directory partially matches, since
240     // it may then match a file within it.
241     // Eg, if you ignore /a, but !/a/b/c
242     if (!match && rule.negate && partial) {
243       match = rule.match("/" + entry, true) ||
244               rule.match(entry, true)
245     }
246
247     if (match) {
248       included = rule.negate
249     }
250   }, this)
251
252   return included
253 }
254
255
256 IgnoreReader.prototype.sort = function (a, b) {
257   var aig = this.ignoreFiles.indexOf(a) !== -1
258   , big = this.ignoreFiles.indexOf(b) !== -1
259
260   if (aig && !big) return -1
261   if (big && !aig) return 1
262   return this._sort(a, b)
263 }
264
265 IgnoreReader.prototype._sort = function (a, b) {
266   return 0
267 }
268
269 function alphasort (a, b) {
270   return a === b ? 0
271        : a.toLowerCase() > b.toLowerCase() ? 1
272        : a.toLowerCase() < b.toLowerCase() ? -1
273        : a > b ? 1
274        : -1
275 }