mirror of
https://github.com/linuxserver/core.git
synced 2026-02-20 05:07:19 +08:00
126 lines
3.4 KiB
JavaScript
126 lines
3.4 KiB
JavaScript
// gutted from walkdir: https://github.com/soldair/node-walkdir
|
|
// speed up a bunch.
|
|
|
|
var fs = require("fs");
|
|
var PathFilter = require("./path-filter");
|
|
var path = require("path");
|
|
// weird, but keeping these outside of walkdir makes it faster
|
|
var finalizer,
|
|
allPaths = Object.create(null),
|
|
allStats = Object.create(null),
|
|
allLinks = Object.create(null),
|
|
ended = 0,
|
|
jobs = 0,
|
|
// since windows handles well paths with forward slashes
|
|
// and we need .nakignore files to work the same on all platforms
|
|
// we always use /
|
|
DIR_SEP = "/",
|
|
|
|
// makes sure we're asynching right
|
|
job = function(value) {
|
|
jobs += value;
|
|
|
|
if(value < 1 && !tick) {
|
|
tick = 1;
|
|
process.nextTick(function(){
|
|
tick = 0;
|
|
if(jobs <= 0 && !ended) {
|
|
ended = 1;
|
|
finalizer();
|
|
}
|
|
});
|
|
}
|
|
}, tick = 0;
|
|
|
|
exports.walkdir = function(fpath, options, printCb, done) {
|
|
var maxFiles = options.limit || -1;
|
|
// if there are ignore rules, properly set them up
|
|
var pathFilter = new PathFilter(options.inclusions, options.exclusions, options.hidden);
|
|
|
|
// called at the end of the walk
|
|
finalizer = function() {
|
|
require('./finalizer')(fpath, options, allPaths, allStats, printCb, done);
|
|
};
|
|
|
|
var follow = options.follow;
|
|
var list = options.list;
|
|
var statAction = function(stat, parent, filepath) {
|
|
// job(-1);
|
|
if (!stat) return;
|
|
|
|
// TODO: this could probably be cleaned up
|
|
if (stat.isFile() && pathFilter.isPathAccepted(filepath)) {
|
|
if (!list)
|
|
allStats[filepath] = stat;
|
|
if (allPaths[parent] === undefined)
|
|
allPaths[parent] = [];
|
|
|
|
allPaths[parent].push(filepath);
|
|
}
|
|
else if (stat.isDirectory() && pathFilter.isPathAccepted(filepath + DIR_SEP)) {
|
|
maxFiles && readdir(filepath + DIR_SEP);
|
|
}
|
|
};
|
|
var statter = function (parent, filepath) {
|
|
// job(1); // statAction is sync
|
|
// lstat is SLOW, but what other way to determine if something is a directory or file ?
|
|
// also, sync is about 200ms faster than async...
|
|
statAction(getStat(fpath + filepath), parent, filepath);
|
|
};
|
|
|
|
var getStat = function(filepath) {
|
|
try {
|
|
var stat = fs.lstatSync(filepath);
|
|
if (follow && stat.isSymbolicLink()) {
|
|
stat = fs.statSync(filepath);
|
|
var fullPath = fs.realpathSync(filepath);
|
|
if (allLinks[fullPath]) {
|
|
return;
|
|
}
|
|
allLinks[fullPath] = true;
|
|
}
|
|
return stat;
|
|
} catch (e) {
|
|
// console.error(e);
|
|
}
|
|
};
|
|
|
|
var readdirAction = function(files, filepath) {
|
|
job(-1);
|
|
if (!files) { return; }
|
|
var fileCount = files.length, prefix = filepath;
|
|
if (maxFiles >= 0) {
|
|
if (maxFiles === 0) {
|
|
return;
|
|
}
|
|
maxFiles -= fileCount;
|
|
if (maxFiles <= 0) {
|
|
maxFiles = 0;
|
|
console.error("reached file number limit");
|
|
}
|
|
}
|
|
while (fileCount--) {
|
|
var file = files.shift(), filename = prefix + file;
|
|
statter(filepath, filename);
|
|
}
|
|
};
|
|
|
|
var readdir = function(filepath) {
|
|
job(1);
|
|
// async doesn't matter, we sort results at end anyway
|
|
fs.readdir(fpath + filepath, function(err, files) {
|
|
readdirAction(files, filepath);
|
|
});
|
|
};
|
|
|
|
if (options.startPaths) {
|
|
job(1);
|
|
options.startPaths.forEach(function(p) {
|
|
statter(path.dirname(p), p);
|
|
});
|
|
job(-1);
|
|
}
|
|
else
|
|
readdir(DIR_SEP);
|
|
};
|