Initial commit
commit
6d791ba1e1
@ -0,0 +1 @@
|
||||
node_modules
|
@ -0,0 +1,163 @@
|
||||
'use strict';
|
||||
|
||||
const split = require("split");
|
||||
const through2 = require("through2");
|
||||
const path = require("path");
|
||||
const rightPad = require("right-pad");
|
||||
const defaultValue = require("default-value");
|
||||
|
||||
let unfound = {};
|
||||
let found = {};
|
||||
let foundBase = {};
|
||||
let probablyNotReallyMissing = {};
|
||||
let ceaseProcessing = false;
|
||||
|
||||
let bannedPrefixes = [
|
||||
"/dev/",
|
||||
"/sys/",
|
||||
"/run/"
|
||||
]
|
||||
|
||||
function isLibrary(name) {
|
||||
return (name.match(/\.so(?:\.[0-9]+)?$/) && !name.match(/\.so(?:\.[0-9]+)\.so$/));
|
||||
}
|
||||
|
||||
function getLibraryName(name) {
|
||||
let match = /^(.+)\.so(?:\.[0-9]+)?$/.exec(name);
|
||||
|
||||
if (match == null) {
|
||||
throw new Error(`Library name regex failed for library: ${name}`);
|
||||
} else {
|
||||
return match[1];
|
||||
}
|
||||
}
|
||||
|
||||
process.stdin
|
||||
.pipe(split())
|
||||
.pipe(through2.obj(function(item, enc, cb) {
|
||||
if (item.trim().length === 0) {
|
||||
cb();
|
||||
} else {
|
||||
let match = /^\s*(?:\[pid\s*[0-9]+\] )?(?:open|stat)\("([^"]+)", ([A-Z_|]+|0x[0-9a-f]+|\{[^\}]+\})\) = (-?[0-9]+)(?: ([A-Z]+))?/.exec(item.toString());
|
||||
|
||||
if (match != null) {
|
||||
let path = match[1];
|
||||
|
||||
if (!bannedPrefixes.some(prefix => path.indexOf(prefix) === 0)) {
|
||||
this.push({
|
||||
path: match[1],
|
||||
flags: match[2].split("|"),
|
||||
status: parseInt(match[3]),
|
||||
error: match[4]
|
||||
});
|
||||
}
|
||||
}
|
||||
cb();
|
||||
}
|
||||
}))
|
||||
.pipe(through2.obj(function(item, enc, cb) {
|
||||
let basename = path.basename(item.path);
|
||||
|
||||
if (basename === "gdb") {
|
||||
ceaseProcessing = true;
|
||||
found["-- GDB ENCOUNTERED --"] = "";
|
||||
unfound["-- GDB ENCOUNTERED --"] = "";
|
||||
}
|
||||
|
||||
if (ceaseProcessing === false) {
|
||||
if (item.status === -1) {
|
||||
unfound[basename] = item.path;
|
||||
} else {
|
||||
delete unfound[basename];
|
||||
found[basename] = item.path;
|
||||
|
||||
if (isLibrary(basename)) {
|
||||
foundBase[getLibraryName(basename)] = item.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb();
|
||||
}))
|
||||
.on("finish", () => {
|
||||
Object.keys(unfound).forEach((basename) => {
|
||||
function markNotMissing(reason) {
|
||||
delete unfound[basename];
|
||||
probablyNotReallyMissing[basename] = reason;
|
||||
}
|
||||
|
||||
if (basename.match(/\.dll.so$/) && found[basename.slice(0, -3)]) {
|
||||
markNotMissing("mono: is actually a DLL");
|
||||
} else if (basename.match(/\.dll.so.la$/) && found[basename.slice(0, -6)]) {
|
||||
markNotMissing("mono: is actually a DLL");
|
||||
} else if (basename.match(/\.res(?:G|S)?$/)) {
|
||||
markNotMissing("unity: .res / .resG / .resS file");
|
||||
} else if (unfound[basename].match(/\/aot-cache\/[^\/]+\/[^\/]+$/)) {
|
||||
markNotMissing("mono: is an AOT cache path");
|
||||
} else if (isLibrary(basename) && foundBase[getLibraryName(basename)]) {
|
||||
markNotMissing("other library version was already found")
|
||||
}
|
||||
});
|
||||
|
||||
function toArray(obj) {
|
||||
return Object.keys(obj).map((key) => {
|
||||
let value = obj[key];
|
||||
|
||||
return {
|
||||
basename: key,
|
||||
path: value
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
let foundItems = toArray(found);
|
||||
let missingItems = toArray(unfound);
|
||||
let probablyNotReallyMissingItems = toArray(probablyNotReallyMissing);
|
||||
|
||||
let missingLibraries = [];
|
||||
let missingOther = [];
|
||||
|
||||
missingItems.forEach((item) => {
|
||||
if (isLibrary(item.basename)) {
|
||||
missingLibraries.push(item);
|
||||
} else {
|
||||
missingOther.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
function printCategory(name, items, options = {}) {
|
||||
let maxWidth = Math.max.apply(null, items.map(item => item.basename.length));
|
||||
let cutoff = defaultValue(options.cutoff, 30);
|
||||
let pathFormat = defaultValue(options.pathFormat, "%");
|
||||
|
||||
console.log(`\n${name}:`);
|
||||
|
||||
if (items.length === 0) {
|
||||
console.log(" (none)");
|
||||
} else {
|
||||
items.slice(0, cutoff).forEach((item) => {
|
||||
console.log(` ${rightPad(item.basename, maxWidth + 5)}${pathFormat.replace("%", item.path)}`);
|
||||
});
|
||||
|
||||
if (items.length > cutoff) {
|
||||
console.log(` (... ${items.length - cutoff} more ...)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printCategory("Found", foundItems);
|
||||
|
||||
printCategory("Probably found", probablyNotReallyMissingItems, {
|
||||
pathFormat: "reason: %"
|
||||
});
|
||||
|
||||
printCategory("Missing miscellaneous", missingOther, {
|
||||
pathFormat: "(last attempted path: %)"
|
||||
});
|
||||
|
||||
printCategory("MISSING LIBRARIES", missingLibraries, {
|
||||
pathFormat: "(last attempted path: %)"
|
||||
});
|
||||
})
|
||||
.pipe(process.stdout);
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "find-missing-files",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Sven Slootweg",
|
||||
"license": "WTFPL",
|
||||
"dependencies": {
|
||||
"default-value": "^1.0.0",
|
||||
"right-pad": "^1.0.1",
|
||||
"split": "^1.0.0",
|
||||
"through2": "^2.0.3"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue