Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / readdirp / readdirp.js
1 'use strict';
2
3 var fs        =  require('graceful-fs')
4   , path      =  require('path')
5   , minimatch =  require('minimatch')
6   , toString  =  Object.prototype.toString
7   , si        =  require('set-immediate-shim')
8   ;
9
10
11 // Standard helpers
12 function isFunction (obj) {
13   return toString.call(obj) === '[object Function]';
14 }
15
16 function isString (obj) {
17   return toString.call(obj) === '[object String]';
18 }
19
20 function isRegExp (obj) {
21   return toString.call(obj) === '[object RegExp]';
22 }
23
24 function isUndefined (obj) {
25   return obj === void 0;
26 }
27
28 /** 
29  * Main function which ends up calling readdirRec and reads all files and directories in given root recursively.
30  * @param { Object }   opts     Options to specify root (start directory), filters and recursion depth
31  * @param { function } callback1  When callback2 is given calls back for each processed file - function (fileInfo) { ... },
32  *                                when callback2 is not given, it behaves like explained in callback2
33  * @param { function } callback2  Calls back once all files have been processed with an array of errors and file infos
34  *                                function (err, fileInfos) { ... }
35  */
36 function readdir(opts, callback1, callback2) {
37   var stream
38     , handleError
39     , handleFatalError
40     , pending = 0
41     , errors = []
42     , readdirResult = {
43         directories: []
44       , files: []
45     }
46     , fileProcessed
47     , allProcessed
48     , realRoot
49     , aborted = false
50     , paused = false
51     ;
52
53   // If no callbacks were given we will use a streaming interface
54   if (isUndefined(callback1)) {
55     var api          =  require('./stream-api')();
56     stream           =  api.stream;
57     callback1        =  api.processEntry;
58     callback2        =  api.done;
59     handleError      =  api.handleError;
60     handleFatalError =  api.handleFatalError;
61
62     stream.on('close', function () { aborted = true; });
63     stream.on('pause', function () { paused = true; });
64     stream.on('resume', function () { paused = false; });
65   } else {
66     handleError      =  function (err) { errors.push(err); };
67     handleFatalError =  function (err) {
68       handleError(err);
69       allProcessed(errors, null);
70     };
71   }
72
73   if (isUndefined(opts)){
74     handleFatalError(new Error (
75       'Need to pass at least one argument: opts! \n' +
76       'https://github.com/thlorenz/readdirp#options'
77       )
78     );
79     return stream;
80   }
81
82   opts.root            =  opts.root            || '.';
83   opts.fileFilter      =  opts.fileFilter      || function() { return true; };
84   opts.directoryFilter =  opts.directoryFilter || function() { return true; };
85   opts.depth           =  typeof opts.depth === 'undefined' ? 999999999 : opts.depth;
86   opts.entryType       =  opts.entryType       || 'files';
87
88   var statfn = opts.lstat === true ? fs.lstat.bind(fs) : fs.stat.bind(fs);
89
90   if (isUndefined(callback2)) {
91     fileProcessed = function() { };
92     allProcessed = callback1;
93   } else {
94     fileProcessed = callback1;
95     allProcessed = callback2;
96   }
97
98   function normalizeFilter (filter) {
99
100     if (isUndefined(filter)) return undefined;
101
102     function isNegated (filters) {
103
104       function negated(f) { 
105         return f.indexOf('!') === 0; 
106       }
107
108       var some = filters.some(negated);
109       if (!some) {
110         return false;
111       } else {
112         if (filters.every(negated)) {
113           return true;
114         } else {
115           // if we detect illegal filters, bail out immediately
116           throw new Error(
117             'Cannot mix negated with non negated glob filters: ' + filters + '\n' +
118             'https://github.com/thlorenz/readdirp#filters'
119           );
120         }
121       }
122     }
123
124     // Turn all filters into a function
125     if (isFunction(filter)) {
126
127       return filter;
128
129     } else if (isString(filter)) {
130
131       return function (entryInfo) {
132         return minimatch(entryInfo.name, filter.trim());
133       };
134
135     } else if (filter && Array.isArray(filter)) {
136
137       if (filter) filter = filter.map(function (f) {
138         return f.trim();
139       });
140
141       return isNegated(filter) ?
142         // use AND to concat multiple negated filters
143         function (entryInfo) {
144           return filter.every(function (f) {
145             return minimatch(entryInfo.name, f);
146           });
147         }
148         :
149         // use OR to concat multiple inclusive filters
150         function (entryInfo) {
151           return filter.some(function (f) {
152             return minimatch(entryInfo.name, f);
153           });
154         };
155     }
156   }
157
158   function processDir(currentDir, entries, callProcessed) {
159     if (aborted) return;
160     var total = entries.length
161       , processed = 0
162       , entryInfos = []
163       ;
164
165     fs.realpath(currentDir, function(err, realCurrentDir) {
166       if (aborted) return;
167       if (err) {
168         handleError(err);
169         callProcessed(entryInfos);
170         return;
171       }
172
173       var relDir = path.relative(realRoot, realCurrentDir);
174
175       if (entries.length === 0) {
176         callProcessed([]);
177       } else {
178         entries.forEach(function (entry) { 
179
180           var fullPath = path.join(realCurrentDir, entry)
181             , relPath  = path.join(relDir, entry);
182
183           statfn(fullPath, function (err, stat) {
184             if (err) {
185               handleError(err);
186             } else {
187               entryInfos.push({
188                   name          :  entry
189                 , path          :  relPath   // relative to root
190                 , fullPath      :  fullPath
191
192                 , parentDir     :  relDir    // relative to root
193                 , fullParentDir :  realCurrentDir
194
195                 , stat          :  stat
196               });
197             }
198             processed++;
199             if (processed === total) callProcessed(entryInfos);
200           });
201         });
202       }
203     });
204   }
205
206   function readdirRec(currentDir, depth, callCurrentDirProcessed) {
207     var args = arguments;
208     if (aborted) return;
209     if (paused) {
210       si(function () {
211         readdirRec.apply(null, args);
212       })
213       return;
214     } 
215
216     fs.readdir(currentDir, function (err, entries) {
217       if (err) {
218         handleError(err);
219         callCurrentDirProcessed();
220         return;
221       }
222
223       processDir(currentDir, entries, function(entryInfos) {
224
225         var subdirs = entryInfos
226           .filter(function (ei) { return ei.stat.isDirectory() && opts.directoryFilter(ei); });
227
228         subdirs.forEach(function (di) {
229           if(opts.entryType === 'directories' || opts.entryType === 'both' || opts.entryType === 'all') {
230             fileProcessed(di);
231           }
232           readdirResult.directories.push(di); 
233         });
234
235         entryInfos
236           .filter(function(ei) {
237             var isCorrectType = opts.entryType === 'all' ?
238               !ei.stat.isDirectory() : ei.stat.isFile() || ei.stat.isSymbolicLink();
239             return isCorrectType && opts.fileFilter(ei);
240           })
241           .forEach(function (fi) {
242             if(opts.entryType === 'files' || opts.entryType === 'both' || opts.entryType === 'all') {
243               fileProcessed(fi);
244             }
245             readdirResult.files.push(fi); 
246           });
247
248         var pendingSubdirs = subdirs.length;
249
250         // Be done if no more subfolders exist or we reached the maximum desired depth
251         if(pendingSubdirs === 0 || depth === opts.depth) {
252           callCurrentDirProcessed();
253         } else {
254           // recurse into subdirs, keeping track of which ones are done 
255           // and call back once all are processed
256           subdirs.forEach(function (subdir) {
257             readdirRec(subdir.fullPath, depth + 1, function () {
258               pendingSubdirs = pendingSubdirs - 1;
259               if(pendingSubdirs === 0) { 
260                 callCurrentDirProcessed();
261               }
262             });
263           });
264         }
265       });
266     });
267   }
268
269   // Validate and normalize filters
270   try {
271     opts.fileFilter = normalizeFilter(opts.fileFilter);
272     opts.directoryFilter = normalizeFilter(opts.directoryFilter);
273   } catch (err) {
274     // if we detect illegal filters, bail out immediately
275     handleFatalError(err);
276     return stream;
277   }
278
279   // If filters were valid get on with the show
280   fs.realpath(opts.root, function(err, res) {
281     if (err) {
282       handleFatalError(err);
283       return stream;
284     }
285
286     realRoot = res;
287     readdirRec(opts.root, 0, function () { 
288       // All errors are collected into the errors array
289       if (errors.length > 0) {
290         allProcessed(errors, readdirResult); 
291       } else {
292         allProcessed(null, readdirResult);
293       }
294     });
295   });
296
297   return stream;
298 }
299
300 module.exports = readdir;