"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/fstream-ignore/ignore.js" (7 Feb 2017, 7500 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    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 }