CLI: Tweak execution of python addons
This commit is contained in:
parent
330e634937
commit
65e9f6210c
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in New Issue