You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.1 KiB
JavaScript
197 lines
5.1 KiB
JavaScript
'use strict';
|
|
|
|
const regexExecAll = require("./regex/exec-all");
|
|
|
|
function isMissingBuildEnvironment(code) {
|
|
return /Windows SDK version [0-9.]+ was not found/.test(code);
|
|
}
|
|
|
|
function isBrokenBuildEnvironment(code) {
|
|
// ex. https://stackoverflow.com/questions/31936170/npm-the-ld-library-not-found-for-lgcc-s-10-5-on-on-os-x-el-capitain
|
|
return (code.indexOf("library not found for -lgcc_s.10.5") !== -1);
|
|
}
|
|
|
|
function isMissingPython(code) {
|
|
// testcases/1.txt
|
|
return (
|
|
code.indexOf("Can't find Python executable") !== -1 ||
|
|
/Command failed:.+python\.exe/i.test(code)
|
|
);
|
|
}
|
|
|
|
function isWrongPython(code) {
|
|
return /Python executable "[^"]*" is v[^,]+, which is not supported by gyp./.test(code);
|
|
}
|
|
|
|
function isBindingSyntaxError(code) {
|
|
// ex. https://github.com/nodejs/node-gyp/issues/979
|
|
return /File "binding.gyp",[\s\S]+SyntaxError: invalid syntax/.test(code);
|
|
}
|
|
|
|
function isMissingNodeHeaders(code) {
|
|
return (code.indexOf("common.gypi not found") !== -1);
|
|
}
|
|
|
|
function isGCCVersionError(code) {
|
|
// ex. https://github.com/nodejs/node-gyp/issues/233#issuecomment-181912859
|
|
return (code.indexOf("requires a C++11 compiler") !== -1);
|
|
}
|
|
|
|
function isNanError(code) {
|
|
// ex. http://pastebin.com/SzdS5YBa
|
|
return (code.indexOf("NanNew") !== -1) || /Nan::[a-zA-Z]+/.test(code);
|
|
}
|
|
|
|
function isV8Error(code) {
|
|
return /V8::[a-zA-Z]+/i.test(code);
|
|
}
|
|
|
|
function isSymlinkIssue(code) {
|
|
// ex. http://pastebin.com/ASxGthw2
|
|
return /npm ERR\!.+\.bin'/.test(code);
|
|
}
|
|
|
|
function isNPMBug(code) {
|
|
return (code.indexOf("file already exists, mkdir") !== -1);
|
|
}
|
|
|
|
function isUnmetDependency(code) {
|
|
// ex. http://pastebin.com/ASxGthw2
|
|
return (code.indexOf("UNMET DEPENDENCY") !== -1);
|
|
}
|
|
|
|
function isUnmetPeerDependency(code) {
|
|
// ex. http://pastebin.com/ASxGthw2
|
|
return (code.indexOf("UNMET PEER DEPENDENCY") !== -1);
|
|
}
|
|
|
|
let missingLibraryRegex = /(?:(?:fatal error|warning): ([^\.]+\.h): No such file or directory|Package (.+) was not found in the pkg-config search path)/g
|
|
let missingDependencyRegex = /UNMET DEPENDENCY ([^@]+)@(.+)/g
|
|
let missingPeerDependencyRegex = /UNMET PEER DEPENDENCY ([^@]+)@(.+)/g
|
|
|
|
function isLibraryMissingError(code) {
|
|
// ex. https://github.com/JustinTulloss/zeromq.node/issues/456
|
|
// ex. https://github.com/Automattic/node-canvas/issues/246
|
|
return missingLibraryRegex.test(code);
|
|
}
|
|
|
|
function getMissingLibraries(code) {
|
|
// alternatively: include <([^>]+)>
|
|
return regexExecAll(missingLibraryRegex, code).map((match) => match[1] || match[2]);
|
|
}
|
|
|
|
function getMissingDependencies(code) {
|
|
// ex. http://pastebin.com/ASxGthw2
|
|
return regexExecAll(missingDependencyRegex, code).map((match) => {
|
|
return {
|
|
name: match[1],
|
|
version: match[2]
|
|
};
|
|
});
|
|
}
|
|
|
|
function getMissingPeerDependencies(code) {
|
|
// ex. http://pastebin.com/ASxGthw2
|
|
return regexExecAll(missingPeerDependencyRegex, code).map((match) => {
|
|
return {
|
|
name: match[1],
|
|
version: match[2]
|
|
};
|
|
});
|
|
}
|
|
|
|
function isLibraryVersionError(code) {
|
|
return /binding.cc:[0-9]+: error/.test(code);
|
|
}
|
|
|
|
function getOffendingModule(code) {
|
|
let match = /Failed at the ([^@]+)@[^\s]+ install script '.+'.\n/.exec(code);
|
|
|
|
if (match != null) {
|
|
return match[1];
|
|
} else {
|
|
// Try to determine the offending module from the node-gyp working directory.
|
|
// This is useful if eg. the user only copied the `gyp` part of the output.
|
|
let match = /gyp ERR! cwd .+[\/\\]node_modules[\/\\]([^\/\\\n]+).*\n/.exec(code);
|
|
|
|
if (match != null) {
|
|
return match[1];
|
|
} else {
|
|
throw new Error("Could not determine the offending module");
|
|
}
|
|
}
|
|
}
|
|
|
|
function getErrorType(code) {
|
|
if (isMissingBuildEnvironment(code)) {
|
|
return "missingEnvironment";
|
|
} else if (isBrokenBuildEnvironment(code)) {
|
|
return "brokenEnvironment";
|
|
} else if (isMissingPython(code)) {
|
|
return "missingPython";
|
|
} else if (isWrongPython(code)) {
|
|
return "wrongPython";
|
|
} else if (isBindingSyntaxError(code)) {
|
|
return "bindingSyntax";
|
|
} else if (isMissingNodeHeaders(code)) {
|
|
return "headers";
|
|
} else if (isGCCVersionError(code)) {
|
|
return "gcc";
|
|
} else if (isLibraryMissingError(code)) {
|
|
return "missingLibrary";
|
|
} else if (isNanError(code)) {
|
|
return "nan";
|
|
} else if (isV8Error(code)) {
|
|
return "v8";
|
|
} else if (isLibraryVersionError(code)) {
|
|
return "libraryVersion";
|
|
} else if (isSymlinkIssue(code)) {
|
|
return "symlinkIssue";
|
|
} else if (isNPMBug(code)) {
|
|
return "npmBug";
|
|
} else if (isUnmetDependency(code)) {
|
|
return "unmetDependency";
|
|
} else if (isUnmetPeerDependency(code)) {
|
|
return "unmetPeerDependency";
|
|
} else {
|
|
throw new Error("Unknown error");
|
|
}
|
|
}
|
|
|
|
module.exports = function(code) {
|
|
let type = getErrorType(code);
|
|
|
|
let errorObject = {
|
|
type: type,
|
|
data: {}
|
|
}
|
|
|
|
if (type === "missingLibrary") {
|
|
Object.assign(errorObject.data, {
|
|
missingLibraries: getMissingLibraries(code)
|
|
});
|
|
}
|
|
|
|
if (type === "unmetDependency") {
|
|
Object.assign(errorObject.data, {
|
|
missingModules: getMissingDependencies(code)
|
|
});
|
|
}
|
|
|
|
if (type === "unmetPeerDependency") {
|
|
Object.assign(errorObject.data, {
|
|
missingModules: getMissingPeerDependencies(code)
|
|
});
|
|
}
|
|
|
|
try {
|
|
Object.assign(errorObject.data, {
|
|
offendingModule: getOffendingModule(code)
|
|
});
|
|
} catch (err) {
|
|
// do nothing...
|
|
}
|
|
|
|
return errorObject;
|
|
}
|