CLI: Tweak execution of python addons

This commit is contained in:
Daniel Marjamäki 2020-05-19 08:14:56 +02:00
parent 330e634937
commit 65e9f6210c
2 changed files with 42 additions and 47 deletions

86
lib/cppcheck.cpp Normal file → Executable file
View File

@ -158,76 +158,72 @@ namespace {
static std::string cmdFileName(std::string f) static std::string cmdFileName(std::string f)
{ {
//f = Path::toNativeSeparators(f); f = Path::toNativeSeparators(f);
if (f.find(" ") != std::string::npos) if (f.find(" ") != std::string::npos)
return "\"" + f + "\""; return "\"" + f + "\"";
return f; return f;
} }
static bool executeShellCommand(std::string exe, const std::string &args, std::string *output)
{
output->clear();
#ifdef _WIN32
// Extra quoutes are needed in windows if filename has space
if (exe.find(" ") != std::string::npos)
exe = "\"" + exe + "\"";
const std::string cmd = exe + " " + args + " 2>&1";
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd.c_str(), "r"), _pclose);
#else
const std::string cmd = exe + " " + args + " 2>&1";
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
#endif
if (!pipe)
return false;
char buffer[1024];
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
*output += buffer;
return true;
}
static std::string executeAddon(const AddonInfo &addonInfo, static std::string executeAddon(const AddonInfo &addonInfo,
const std::string &defaultPythonExe, const std::string &defaultPythonExe,
const std::string &dumpFile) const std::string &dumpFile)
{ {
std::string pythonExe; std::string pythonExe;
// Can python be executed? if (!addonInfo.python.empty())
const int lastTest = 3; pythonExe = cmdFileName(addonInfo.python);
for (int test = 1; test <= lastTest; ++test) { else if (!defaultPythonExe.empty())
if (test == 1 || test == lastTest) pythonExe = cmdFileName(defaultPythonExe);
pythonExe = cmdFileName((addonInfo.python != "") ? addonInfo.python : defaultPythonExe); else {
else
pythonExe = "python3";
const std::string cmd = pythonExe + " --version 2>&1";
#ifdef _WIN32 #ifdef _WIN32
if (pythonExe.find(" ") != std::string::npos) { const char *p[] = { "python3.exe", "python.exe" };
// popen strips the first quote. Needs 2 sets to fully quote.
pythonExe = "\"" + pythonExe + "\"";
}
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd.c_str(), "r"), _pclose);
#else #else
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose); const char *p[] = { "python3", "python" };
#endif #endif
if (!pipe) { for (int i = 0; i < 2; ++i) {
if (test < lastTest) std::string out;
continue; if (executeShellCommand(p[i], "--version", &out) && out.compare(0, 7, "Python ") == 0 && std::isdigit(out[7])) {
throw InternalError(nullptr, "popen failed (command: '" + cmd + "')"); pythonExe = p[i];
break;
} }
char buffer[1024];
std::string result;
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
result += buffer;
if (result.compare(0, 7, "Python ", 0, 7) != 0 || result.size() > 50) {
if (test < lastTest)
continue;
throw InternalError(nullptr, "Failed to execute '" + cmd + "' (" + result + ")");
} }
if (pythonExe.empty())
throw InternalError(nullptr, "Failed to auto detect python");
} }
const std::string cmd = pythonExe + " " + cmdFileName(addonInfo.scriptFile) + " --cli" + addonInfo.args + " " + cmdFileName(dumpFile) + " 2>&1"; const std::string args = cmdFileName(addonInfo.scriptFile) + " --cli" + addonInfo.args + " " + cmdFileName(dumpFile);
#ifdef _WIN32
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd.c_str(), "r"), _pclose);
#else
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
#endif
if (!pipe)
throw InternalError(nullptr, "popen failed (command: '" + cmd + "')");
char buffer[1024];
std::string result; std::string result;
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) { if (!executeShellCommand(pythonExe, args, &result))
result += buffer; throw InternalError(nullptr, "Failed to execute addon (command: '" + pythonExe + " " + args + "')");
}
// Validate output.. // Validate output..
std::istringstream istr(result); std::istringstream istr(result);
std::string line; std::string line;
while (std::getline(istr, line)) { while (std::getline(istr, line)) {
if (line.compare(0,9,"Checking ", 0, 9) != 0 && !line.empty() && line[0] != '{') if (line.compare(0,9,"Checking ", 0, 9) != 0 && !line.empty() && line[0] != '{')
throw InternalError(nullptr, "Failed to execute '" + cmd + "'. " + result); throw InternalError(nullptr, "Failed to execute '" + pythonExe + " " + args + "'. " + result);
} }
// Valid results // Valid results

1
lib/settings.cpp Normal file → Executable file
View File

@ -30,7 +30,6 @@ const char Settings::SafeChecks::XmlExternalVariables[] = "external-variables";
Settings::Settings() Settings::Settings()
: mEnabled(0), : mEnabled(0),
addonPython("python"),
bugHunting(false), bugHunting(false),
checkAllConfigurations(true), checkAllConfigurations(true),
checkConfiguration(false), checkConfiguration(false),