diff --git a/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_unix.txt b/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_unix.txt index 552d7d1e..d2a054e3 100644 --- a/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_unix.txt +++ b/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_unix.txt @@ -1,6 +1,12 @@ -SourceFilePath: "src/a.txt" +IndexerCommandCustom + SourceFilePath: "src/a.txt" Custom Command: "echo "Hello World"" -SourceFilePath: "src/b.txt" + Arguments: +IndexerCommandCustom + SourceFilePath: "src/b.txt" Custom Command: "echo "Hello World"" -SourceFilePath: "src/included/a.txt" + Arguments: +IndexerCommandCustom + SourceFilePath: "src/included/a.txt" Custom Command: "echo "Hello World"" + Arguments: diff --git a/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_windows.txt b/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_windows.txt index 552d7d1e..d2a054e3 100644 --- a/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_windows.txt +++ b/bin/test/data/SourceGroupTestSuite/custom_command/expected_output/output_windows.txt @@ -1,6 +1,12 @@ -SourceFilePath: "src/a.txt" +IndexerCommandCustom + SourceFilePath: "src/a.txt" Custom Command: "echo "Hello World"" -SourceFilePath: "src/b.txt" + Arguments: +IndexerCommandCustom + SourceFilePath: "src/b.txt" Custom Command: "echo "Hello World"" -SourceFilePath: "src/included/a.txt" + Arguments: +IndexerCommandCustom + SourceFilePath: "src/included/a.txt" Custom Command: "echo "Hello World"" + Arguments: diff --git a/script/download_python_indexer.sh b/script/download_python_indexer.sh index d637494f..16e3be56 100755 --- a/script/download_python_indexer.sh +++ b/script/download_python_indexer.sh @@ -94,6 +94,7 @@ fi echo -e $INFO "clearing $TARGET_PATH" rm -rf $TARGET_PATH mkdir -p $TARGET_PATH +echo -e $INFO "copying downloaded data to $TARGET_PATH" cp -r $TEMP_PATH/$PACKAGE_NAME/* $TARGET_PATH diff --git a/src/app/main.cpp b/src/app/main.cpp index 9705bcdc..4ae66d6c 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -93,6 +93,11 @@ void addLanguagePackages() int main(int argc, char* argv[]) { + // auto p = utility::executeProcessBoost(utility::searchPath(L"mvn") + L" --version", FilePath("/Users/ebsi/Documents/boost_1_67_0"), 3000); + // std::wcout << p.first << " " << p.second << std::endl; + // return 0; + + QCoreApplication::addLibraryPath(QStringLiteral(".")); #pragma warning(push) diff --git a/src/lib/app/paths/ResourcePaths.cpp b/src/lib/app/paths/ResourcePaths.cpp index 593a8f75..acb8489c 100644 --- a/src/lib/app/paths/ResourcePaths.cpp +++ b/src/lib/app/paths/ResourcePaths.cpp @@ -1,6 +1,7 @@ #include "ResourcePaths.h" #include "AppPath.h" +#include "utilityApp.h" FilePath ResourcePaths::getColorSchemesPath() { @@ -37,7 +38,7 @@ FilePath ResourcePaths::getJavaPath() return AppPath::getSharedDataPath().concatenate(L"data/java/"); } -FilePath ResourcePaths::getPythonPath() +FilePath ResourcePaths::getPythonDirectoryPath() { return AppPath::getSharedDataPath().concatenate(L"data/python/"); } @@ -46,3 +47,12 @@ FilePath ResourcePaths::getCxxCompilerHeaderPath() { return AppPath::getSharedDataPath().concatenate(L"data/cxx/include/").getCanonical(); } + +FilePath ResourcePaths::getPythonIndexerFilePath() +{ + if (utility::getOsType() == OS_WINDOWS) + { + return getPythonDirectoryPath().concatenate(L"SourcetrailPythonIndexer.exe"); + } + return getPythonDirectoryPath().concatenate(L"SourcetrailPythonIndexer"); +} diff --git a/src/lib/app/paths/ResourcePaths.h b/src/lib/app/paths/ResourcePaths.h index a7fa351d..79b1617f 100644 --- a/src/lib/app/paths/ResourcePaths.h +++ b/src/lib/app/paths/ResourcePaths.h @@ -15,8 +15,9 @@ public: static FilePath getGuiPath(); static FilePath getLicensePath(); static FilePath getJavaPath(); - static FilePath getPythonPath(); + static FilePath getPythonDirectoryPath(); static FilePath getCxxCompilerHeaderPath(); + static FilePath getPythonIndexerFilePath(); }; #endif // RESOURCE_PATHS_H diff --git a/src/lib/data/indexer/IndexerCommandCustom.cpp b/src/lib/data/indexer/IndexerCommandCustom.cpp index bf9759a1..fc131439 100644 --- a/src/lib/data/indexer/IndexerCommandCustom.cpp +++ b/src/lib/data/indexer/IndexerCommandCustom.cpp @@ -11,7 +11,8 @@ IndexerCommandType IndexerCommandCustom::getStaticIndexerCommandType() } IndexerCommandCustom::IndexerCommandCustom( - const std::wstring& customCommand, + const std::wstring& command, + const std::vector& arguments, const FilePath& projectFilePath, const FilePath& databaseFilePath, const std::wstring& databaseVersion, @@ -19,7 +20,8 @@ IndexerCommandCustom::IndexerCommandCustom( bool runInParallel) : IndexerCommand(sourceFilePath) , m_type(getStaticIndexerCommandType()) - , m_customCommand(customCommand) + , m_command(command) + , m_arguments(arguments) , m_projectFilePath(projectFilePath) , m_databaseFilePath(databaseFilePath) , m_databaseVersion(databaseVersion) @@ -29,7 +31,8 @@ IndexerCommandCustom::IndexerCommandCustom( IndexerCommandCustom::IndexerCommandCustom( IndexerCommandType type, - const std::wstring& customCommand, + const std::wstring& command, + const std::vector& arguments, const FilePath& projectFilePath, const FilePath& databaseFilePath, const std::wstring& databaseVersion, @@ -37,7 +40,8 @@ IndexerCommandCustom::IndexerCommandCustom( bool runInParallel) : IndexerCommand(sourceFilePath) , m_type(type) - , m_customCommand(customCommand) + , m_command(command) + , m_arguments(arguments) , m_projectFilePath(projectFilePath) , m_databaseFilePath(databaseFilePath) , m_databaseVersion(databaseVersion) @@ -67,19 +71,19 @@ void IndexerCommandCustom::setDatabaseFilePath(const FilePath& databaseFilePath) m_databaseFilePath = databaseFilePath; } -std::wstring IndexerCommandCustom::getCustomCommand() const +std::wstring IndexerCommandCustom::getCommand() const { - std::wstring command = m_customCommand; + return replaceVariables(m_command); +} - command = utility::replace( - command, L"%{PROJECT_FILE_PATH}", L'\"' + m_projectFilePath.wstr() + L'\"'); - command = utility::replace( - command, L"%{DATABASE_FILE_PATH}", L'\"' + m_databaseFilePath.wstr() + L'\"'); - command = utility::replace(command, L"%{DATABASE_VERSION}", L'\"' + m_databaseVersion + L'\"'); - command = utility::replace( - command, L"%{SOURCE_FILE_PATH}", L'\"' + getSourceFilePath().wstr() + L'\"'); - - return command; +std::vector IndexerCommandCustom::getArguments() const +{ + std::vector args; + for (const std::wstring& argument: m_arguments) + { + args.push_back(replaceVariables(argument)); + } + return args; } bool IndexerCommandCustom::getRunInParallel() const @@ -92,7 +96,15 @@ QJsonObject IndexerCommandCustom::doSerialize() const QJsonObject jsonObject = IndexerCommand::doSerialize(); { - jsonObject["custom_command"] = QString::fromStdWString(m_customCommand); + jsonObject["command"] = QString::fromStdWString(m_command); + } + { + QJsonArray argumentsArray; + for (const std::wstring& argument: m_arguments) + { + argumentsArray.append(QString::fromStdWString(argument)); + } + jsonObject["arguments"] = argumentsArray; } { jsonObject["run_in_parallel"] = m_runInParallel; @@ -100,3 +112,12 @@ QJsonObject IndexerCommandCustom::doSerialize() const return jsonObject; } + +std::wstring IndexerCommandCustom::replaceVariables(std::wstring s) const +{ + s = utility::replace(s, L"%{PROJECT_FILE_PATH}", m_projectFilePath.wstr()); + s = utility::replace(s, L"%{DATABASE_FILE_PATH}", m_databaseFilePath.wstr()); + s = utility::replace(s, L"%{DATABASE_VERSION}", m_databaseVersion); + s = utility::replace(s, L"%{SOURCE_FILE_PATH}", getSourceFilePath().wstr()); + return s; +} diff --git a/src/lib/data/indexer/IndexerCommandCustom.h b/src/lib/data/indexer/IndexerCommandCustom.h index c0a007be..6b8c4032 100644 --- a/src/lib/data/indexer/IndexerCommandCustom.h +++ b/src/lib/data/indexer/IndexerCommandCustom.h @@ -12,7 +12,8 @@ public: static IndexerCommandType getStaticIndexerCommandType(); IndexerCommandCustom( - const std::wstring& customCommand, + const std::wstring& command, + const std::vector& arguments, const FilePath& projectFilePath, const FilePath& databaseFilePath, const std::wstring& databaseVersion, @@ -21,7 +22,8 @@ public: IndexerCommandCustom( IndexerCommandType type, - const std::wstring& customCommand, + const std::wstring& command, + const std::vector& arguments, const FilePath& projectFilePath, const FilePath& databaseFilePath, const std::wstring& databaseVersion, @@ -34,15 +36,19 @@ public: FilePath getDatabaseFilePath() const; void setDatabaseFilePath(const FilePath& databaseFilePath); - std::wstring getCustomCommand() const; + std::wstring getCommand() const; + std::vector getArguments() const; bool getRunInParallel() const; protected: QJsonObject doSerialize() const override; private: + std::wstring replaceVariables(std::wstring s) const; + IndexerCommandType m_type; - std::wstring m_customCommand; + std::wstring m_command; + std::vector m_arguments; FilePath m_projectFilePath; FilePath m_databaseFilePath; std::wstring m_databaseVersion; diff --git a/src/lib/data/indexer/TaskBuildIndex.cpp b/src/lib/data/indexer/TaskBuildIndex.cpp index 55f597c0..15026ced 100644 --- a/src/lib/data/indexer/TaskBuildIndex.cpp +++ b/src/lib/data/indexer/TaskBuildIndex.cpp @@ -188,22 +188,23 @@ void TaskBuildIndex::runIndexerProcess(int processId, const std::wstring& logFil return; } - const std::wstring commandPath = L"\"" + indexerProcessPath.wstr() + L"\""; std::vector commandArguments; commandArguments.push_back(std::to_wstring(processId)); commandArguments.push_back(utility::decodeFromUtf8(m_appUUID)); - commandArguments.push_back(L"\"" + AppPath::getSharedDataPath().getAbsolute().wstr() + L"\""); - commandArguments.push_back(L"\"" + UserPaths::getUserDataPath().getAbsolute().wstr() + L"\""); + commandArguments.push_back(AppPath::getSharedDataPath().getAbsolute().wstr()); + commandArguments.push_back(UserPaths::getUserDataPath().getAbsolute().wstr()); if (!logFilePath.empty()) { - commandArguments.push_back(L"\"" + logFilePath + L"\""); + commandArguments.push_back(logFilePath); } int result = 1; while ((!m_indexerCommandQueueStopped || result != 0) && !m_interrupted) { - result = utility::executeProcessAndGetExitCode(commandPath, commandArguments, FilePath(), -1); + result = utility::executeProcess( + indexerProcessPath.wstr(), commandArguments, FilePath(), false, -1) + .exitCode; LOG_INFO_STREAM(<< "Indexer process " << processId << " returned with " + std::to_string(result)); } diff --git a/src/lib/data/indexer/TaskExecuteCustomCommands.cpp b/src/lib/data/indexer/TaskExecuteCustomCommands.cpp index 0ad359e4..7ca9356e 100644 --- a/src/lib/data/indexer/TaskExecuteCustomCommands.cpp +++ b/src/lib/data/indexer/TaskExecuteCustomCommands.cpp @@ -465,17 +465,19 @@ void TaskExecuteCustomCommands::runIndexerCommand( indexedSourceFileCount + 1, indexedSourceFileCount, m_indexerCommandCount, {sourcePath}); MessageIndexingStatus(true, indexedSourceFileCount * 100 / m_indexerCommandCount).dispatch(); - const std::wstring command = indexerCommand->getCustomCommand(); + const std::wstring command = indexerCommand->getCommand(); + const std::vector arguments = indexerCommand->getArguments(); - LOG_INFO("Start processing command \"" + utility::encodeToUtf8(command) + "\""); + LOG_INFO( + "Start processing command \"" + + utility::encodeToUtf8(command + L" " + utility::join(arguments, L" ")) + "\""); const ErrorCountInfo previousErrorCount = storage ? storage->getErrorCount() : ErrorCountInfo(); LOG_INFO("Starting to index"); - std::wstring errorMessage; - const int result = utility::executeProcessAndGetExitCode( - command, {}, m_projectDirectory, -1, true, &errorMessage); + const utility::ProcessOutput out = utility::executeProcess( + command, arguments, m_projectDirectory, false, -1, true); LOG_INFO("Finished indexing"); if (storage) @@ -501,22 +503,22 @@ void TaskExecuteCustomCommands::runIndexerCommand( } } - if (result == 0 && errorMessage.empty()) + if (out.exitCode == 0 && out.error.empty()) { std::wstring message = L"Process returned successfully.\n"; LOG_INFO(message); } else { - std::wstring statusText = L"command \"" + indexerCommand->getCustomCommand() + - L"\" returned"; - if (result != 0) + std::wstring statusText = L"command \"" + indexerCommand->getCommand() + L" " + + utility::join(arguments, L" ") + L"\" returned"; + if (out.exitCode != 0) { - statusText += L" code \"" + std::to_wstring(result) + L"\""; + statusText += L" code \"" + std::to_wstring(out.exitCode) + L"\""; } - if (!errorMessage.empty()) + if (!out.error.empty()) { - statusText += L" with message \"" + errorMessage + L"\""; + statusText += L" with message \"" + out.error + L"\""; } statusText += L"."; diff --git a/src/lib/project/SourceGroupCustomCommand.cpp b/src/lib/project/SourceGroupCustomCommand.cpp index 27abf4b8..2dc3bc15 100644 --- a/src/lib/project/SourceGroupCustomCommand.cpp +++ b/src/lib/project/SourceGroupCustomCommand.cpp @@ -42,7 +42,6 @@ std::set SourceGroupCustomCommand::getAllSourceFilePaths() const std::vector> SourceGroupCustomCommand::getIndexerCommands( const RefreshInfo& info) const { - const std::wstring customCommand = m_settings->getCustomCommand(); const bool runInParallel = m_settings->getRunInParallel(); std::vector> indexerCommands; @@ -51,7 +50,8 @@ std::vector> SourceGroupCustomCommand::getIndexe if (info.filesToIndex.find(sourcePath) != info.filesToIndex.end()) { indexerCommands.push_back(std::make_shared( - customCommand, + m_settings->getCustomCommand(), + std::vector {}, m_settings->getProjectSettings()->getProjectFilePath(), m_settings->getProjectSettings()->getTempDBFilePath(), std::to_wstring(SqliteIndexStorage::getStorageVersion()), diff --git a/src/lib_gui/qt/project_wizard/content/QtProjectWizardContentSelect.cpp b/src/lib_gui/qt/project_wizard/content/QtProjectWizardContentSelect.cpp index 7b119896..2f93091a 100644 --- a/src/lib_gui/qt/project_wizard/content/QtProjectWizardContentSelect.cpp +++ b/src/lib_gui/qt/project_wizard/content/QtProjectWizardContentSelect.cpp @@ -24,20 +24,19 @@ void QtProjectWizardContentSelect::populate(QGridLayout* layout, int& row) { std::string pythonIndexerVersion = " "; { - std::string str = - utility::executeProcess( - ResourcePaths::getPythonPath().wstr().append(L"SourcetrailPythonIndexer"), - std::vector {L"--version"}, - FilePath(), - 5000) - .second; - std::regex regex( - "v\\d*\\.db\\d*\\.p\\d*"); // "\\d" matches any digit; "\\." matches the "." character - std::smatch matches; - std::regex_search(str, matches, regex); - if (!matches.empty()) + utility::ProcessOutput output = utility::executeProcess( + ResourcePaths::getPythonIndexerFilePath().wstr(), {L"--version"}, FilePath(), false, 5000); + if (output.exitCode == 0) { - pythonIndexerVersion = matches.str(0) + " "; + std::string str = utility::encodeToUtf8(output.output); + std::regex regex("v\\d*\\.db\\d*\\.p\\d*"); // "\\d" matches any digit; "\\." matches + // the "." character + std::smatch matches; + std::regex_search(str, matches, regex); + if (!matches.empty()) + { + pythonIndexerVersion = matches.str(0) + " "; + } } } diff --git a/src/lib_gui/qt/project_wizard/content/path/QtProjectWizardContentPathPythonEnvironment.cpp b/src/lib_gui/qt/project_wizard/content/path/QtProjectWizardContentPathPythonEnvironment.cpp index deed2011..0a67eda8 100644 --- a/src/lib_gui/qt/project_wizard/content/path/QtProjectWizardContentPathPythonEnvironment.cpp +++ b/src/lib_gui/qt/project_wizard/content/path/QtProjectWizardContentPathPythonEnvironment.cpp @@ -62,20 +62,20 @@ void QtProjectWizardContentPathPythonEnvironment::onTextChanged(const QString& t { m_resultLabel->setText("Checking validity of Python environment..."); std::thread([=]() { - std::pair out = utility::executeProcess( - ResourcePaths::getPythonPath().wstr().append(L"SourcetrailPythonIndexer"), - std::vector{ - L"check-environment", - L"--environment-path " + utility::getExpandedAndAbsolutePath( - FilePath(text.toStdWString()), m_settings->getProjectDirectoryPath()) - .wstr() - }, + const utility::ProcessOutput out = utility::executeProcess( + ResourcePaths::getPythonIndexerFilePath().wstr(), + {L"check-environment", + L"--environment-path", + utility::getExpandedAndAbsolutePath( + FilePath(text.toStdWString()), m_settings->getProjectDirectoryPath()) + .wstr()}, FilePath(), + false, 5000); m_onQtThread([=]() { - if (out.first == 0) + if (out.exitCode == 0) { - m_resultLabel->setText(QString::fromStdString(out.second)); + m_resultLabel->setText(QString::fromStdWString(out.output)); } else { diff --git a/src/lib_gui/utility/path_detector/cxx_header/CxxFrameworkPathDetector.cpp b/src/lib_gui/utility/path_detector/cxx_header/CxxFrameworkPathDetector.cpp index db7a7b9d..778527b1 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/CxxFrameworkPathDetector.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/CxxFrameworkPathDetector.cpp @@ -11,14 +11,14 @@ CxxFrameworkPathDetector::CxxFrameworkPathDetector(const std::string& compilerNa std::vector CxxFrameworkPathDetector::doGetPaths() const { - std::vector paths = utility::getCxxHeaderPaths(m_compilerName); + std::vector paths = utility::getCxxHeaderPaths(m_compilerName); std::vector frameworkPaths; - for (const std::string& path: paths) + for (const std::wstring& path: paths) { - if (utility::isPostfix(" (framework directory)", path)) + if (utility::isPostfix(L" (framework directory)", path)) { FilePath p = - FilePath(utility::replace(path, " (framework directory)", "")).makeCanonical(); + FilePath(utility::replace(path, L" (framework directory)", L"")).makeCanonical(); if (p.exists()) { frameworkPaths.push_back(p); diff --git a/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp b/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp index dfb0a56c..71a8f8d5 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp @@ -11,12 +11,12 @@ CxxHeaderPathDetector::CxxHeaderPathDetector(const std::string& compilerName) std::vector CxxHeaderPathDetector::doGetPaths() const { - std::vector paths = utility::getCxxHeaderPaths(m_compilerName); + std::vector paths = utility::getCxxHeaderPaths(m_compilerName); std::vector headerSearchPaths; - for (const std::string& path: paths) + for (const std::wstring& path: paths) { - if (!utility::isPostfix(" (framework directory)", path) && + if (!utility::isPostfix(L" (framework directory)", path) && FilePath(path).getCanonical().exists() && !FilePath(path).getCanonical().getConcatenated(L"/stdarg.h").exists()) { diff --git a/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp b/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp index 89459917..b08c60c1 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp @@ -20,27 +20,32 @@ std::vector CxxVs15HeaderPathDetector::doGetPaths() const .expandEnvironmentVariables(); if (!expandedPaths.empty()) { - const std::string output = - utility::executeProcess( - expandedPaths[0].wstr(), std::vector {L"-latest", L"-property installationPath"}, FilePath(), 10000) - .second; - - const FilePath vsInstallPath(output); - if (vsInstallPath.exists()) + const utility::ProcessOutput out = utility::executeProcess( + expandedPaths.front().wstr(), + {L"-latest", L"-property", L"installationPath"}, + FilePath(), + false, + 10000); + if (out.exitCode == 0) { - for (const FilePath& versionPath: FileSystem::getDirectSubDirectories( - vsInstallPath.getConcatenated(L"VC/Tools/MSVC"))) + const FilePath vsInstallPath(out.output); + if (vsInstallPath.exists()) { - if (versionPath.exists()) + for (const FilePath& versionPath: FileSystem::getDirectSubDirectories( + vsInstallPath.getConcatenated(L"VC/Tools/MSVC"))) { - headerSearchPaths.push_back(versionPath.getConcatenated(L"include")); - headerSearchPaths.push_back(versionPath.getConcatenated(L"atlmfc/include")); + if (versionPath.exists()) + { + headerSearchPaths.push_back(versionPath.getConcatenated(L"include")); + headerSearchPaths.push_back( + versionPath.getConcatenated(L"atlmfc/include")); + } } + headerSearchPaths.push_back( + vsInstallPath.getConcatenated(L"VC/Auxiliary/VS/include")); + headerSearchPaths.push_back( + vsInstallPath.getConcatenated(L"VC/Auxiliary/VS/UnitTest/include")); } - headerSearchPaths.push_back( - vsInstallPath.getConcatenated(L"VC/Auxiliary/VS/include")); - headerSearchPaths.push_back( - vsInstallPath.getConcatenated(L"VC/Auxiliary/VS/UnitTest/include")); } } } diff --git a/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp b/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp index 7f1d36c1..b0a1d810 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp @@ -9,22 +9,23 @@ namespace utility { -std::vector getCxxHeaderPaths(const std::string& compilerName) +std::vector getCxxHeaderPaths(const std::string& compilerName) { - std::string command = compilerName + " -x c++ -v -E /dev/null"; - std::string clangOutput = utility::executeProcess( - utility::decodeFromUtf8(compilerName), - std::vector {L"-x c++", L"-v", L"-E /dev/null"}) - .second; - std::string standardHeaders = utility::substrBetween( - clangOutput, "#include <...> search starts here:\n", "\nEnd of search list"); - std::vector paths; + std::vector paths; - if (!standardHeaders.empty()) + const utility::ProcessOutput out = utility::executeProcess( + utility::decodeFromUtf8(compilerName), {L"-x", L"c++", L"-v", L"-E", L"/dev/null"}); + if (out.exitCode == 0) { - for (const std::string& s: utility::splitToVector(standardHeaders, '\n')) + std::wstring standardHeaders = utility::substrBetween( + out.output, L"#include <...> search starts here:\n", L"\nEnd of search list"); + + if (!standardHeaders.empty()) { - paths.push_back(utility::trim(s)); + for (const std::wstring& s: utility::splitToVector(standardHeaders, L'\n')) + { + paths.push_back(utility::trim(s)); + } } } diff --git a/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.h b/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.h index e958864f..921c322d 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.h +++ b/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.h @@ -9,7 +9,7 @@ namespace utility { -std::vector getCxxHeaderPaths(const std::string& compilerName); +std::vector getCxxHeaderPaths(const std::string& compilerName); std::vector getWindowsSdkHeaderSearchPaths(ApplicationArchitectureType architectureType); FilePath getWindowsSdkRootPathUsingRegistry( diff --git a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp index a2491574..b945a52a 100644 --- a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp +++ b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp @@ -54,28 +54,28 @@ std::vector JavaPathDetectorLinux::doGetPaths() const FilePath JavaPathDetectorLinux::getJavaInPath() const { - std::string output = utility::executeProcess(L"which", std::vector{L"java"}).second; - - if (!output.empty()) + bool ok; + FilePath javaPath(utility::searchPath(L"java", ok)); + if (ok && !javaPath.empty() && javaPath.exists()) { - output = utility::trim(output); - - FilePath javaPath(output); - if (!javaPath.empty() && javaPath.exists()) - { - return javaPath; - } + return javaPath; } - return FilePath(); } FilePath JavaPathDetectorLinux::readLink(const FilePath& path) const { - FilePath javaPath(utility::executeProcess(L"readlink", std::vector{L"-f", path.wstr()}).second); - if (!javaPath.empty()) + const utility::ProcessOutput out = utility::executeProcess( + L"readlink", std::vector {L"-f", path.wstr()}); + + if (out.exitCode == 0 && !out.output.empty()) { - return javaPath; + FilePath javaPath(utility::trim(out.output)); + + if (!javaPath.empty()) + { + return javaPath; + } } return FilePath(); } @@ -113,7 +113,9 @@ FilePath JavaPathDetectorLinux::getJavaInJavaHome() const bool JavaPathDetectorLinux::checkVersion(const FilePath& path) const { - std::string output = utility::executeProcess(path.wstr(), std::vector{L"-version"}).second; + const utility::ProcessOutput out = utility::executeProcess(path.wstr(), {L"-version"}); - return output.find(m_javaVersion) != std::string::npos; + return ( + (out.exitCode == 0) && + (out.output.find(utility::decodeFromUtf8(m_javaVersion)) != std::string::npos)); } diff --git a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp index 33c19d40..3f9bb54b 100644 --- a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp +++ b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp @@ -14,21 +14,22 @@ std::vector JavaPathDetectorMac::doGetPaths() const std::vector paths; FilePath javaPath; - std::string output = utility::executeProcess(L"/usr/libexec/java_home", std::vector{}).second; + const utility::ProcessOutput out = utility::executeProcess(L"/usr/libexec/java_home", {}); + const std::wstring output = out.exitCode == 0 ? utility::trim(out.output) : L""; if (!output.empty()) { - javaPath = FilePath(utility::trim(output) + "/../MacOS/libjli.dylib").makeCanonical(); + javaPath = FilePath(output + L"/../MacOS/libjli.dylib").makeCanonical(); } - if (!javaPath.exists() && output.size()) + if (!javaPath.exists() && !output.empty()) { - javaPath = FilePath(utility::trim(output) + "/lib/libjli.dylib"); + javaPath = FilePath(output + L"/lib/libjli.dylib"); } - if (!javaPath.exists() && output.size()) + if (!javaPath.exists() && !output.empty()) { - javaPath = FilePath(utility::trim(output) + "/jre/lib/jli/libjli.dylib"); + javaPath = FilePath(output + L"/jre/lib/jli/libjli.dylib"); } if (!javaPath.exists()) @@ -36,9 +37,9 @@ std::vector JavaPathDetectorMac::doGetPaths() const javaPath = FilePath(L"/usr/lib/libjli.dylib"); } - if (!javaPath.exists() && output.size()) + if (!javaPath.exists() && !output.empty()) { - javaPath = FilePath(utility::trim(output) + "/jre/lib/server/libjvm.dylib"); + javaPath = FilePath(output + L"/jre/lib/server/libjvm.dylib"); } if (!javaPath.exists()) diff --git a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp index ca8af480..2460d6cf 100644 --- a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp +++ b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp @@ -7,12 +7,17 @@ MavenPathDetectorUnix::MavenPathDetectorUnix(): PathDetector("Maven for Unix") { std::vector MavenPathDetectorUnix::doGetPaths() const { - FilePath mavenPath(utility::executeProcess(L"which", std::vector{L"mvn"}).second); - std::vector paths; - if (mavenPath.exists()) + + const utility::ProcessOutput out = utility::executeProcess(L"which", {L"mvn"}); + + if (out.exitCode == 0) { - paths.push_back(mavenPath); + FilePath mavenPath(out.output); + if (mavenPath.exists()) + { + paths.push_back(mavenPath); + } } return paths; } diff --git a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp index ac8bf996..c43b21be 100644 --- a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp +++ b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp @@ -7,10 +7,11 @@ MavenPathDetectorWindows::MavenPathDetectorWindows(): PathDetector("Maven for Wi std::vector MavenPathDetectorWindows::doGetPaths() const { - FilePath mavenPath(utility::executeProcess(L"cmd", std::vector{L"/c where mvn.cmd && exit"}).second); - std::vector paths; - if (mavenPath.exists()) + + bool ok; + FilePath mavenPath(utility::searchPath(L"mvn.cmd", ok)); + if (ok && !mavenPath.empty() && mavenPath.exists()) { paths.push_back(mavenPath); } diff --git a/src/lib_gui/utility/utilityApp.cpp b/src/lib_gui/utility/utilityApp.cpp index e6c2a2e4..175e67a0 100644 --- a/src/lib_gui/utility/utilityApp.cpp +++ b/src/lib_gui/utility/utilityApp.cpp @@ -1,284 +1,215 @@ #include "utilityApp.h" +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "AppPath.h" -#include "ApplicationSettings.h" -#include "UserPaths.h" +#include + +#include "ScopedFunctor.h" #include "logging.h" #include "utilityString.h" -namespace -{ -void logProcessStreams(QProcess& process, std::wstring& outputBuffer, std::wstring& errorBuffer) -{ - { - outputBuffer += QString(process.readAllStandardOutput()).toStdWString(); - std::vector outputLines = utility::split>( - outputBuffer, L"\n"); - for (size_t i = 0; i < outputLines.size() - 1; i++) - { - if (outputLines[i].back() == L'\r') - { - outputLines[i].pop_back(); - } - LOG_INFO_BARE(L"Process output: " + outputLines[i]); - } - outputBuffer = outputLines.back(); - } - { - errorBuffer += QString(process.readAllStandardError()).toStdWString(); - std::vector errorLines = utility::split>( - errorBuffer, L"\n"); - for (size_t i = 0; i < errorLines.size() - 1; i++) - { - if (errorLines[i].back() == L'\r') - { - errorLines[i].pop_back(); - } - LOG_ERROR_BARE(L"Process error: " + errorLines[i]); - } - errorBuffer = errorLines.back(); - } -} -} // namespace - namespace utility { std::mutex s_runningProcessesMutex; -std::set s_runningProcesses; +std::set> s_runningProcesses; } // namespace utility -std::pair utility::executeProcess( - const std::wstring& commandPath, - const std::vector& commandArguments, - const FilePath& workingDirectory, - const int timeout) +std::wstring utility::searchPath(const std::wstring& bin, bool& ok) { - QProcess process; - process.setProcessChannelMode(QProcess::MergedChannels); - - if (!workingDirectory.empty()) + ok = false; + std::wstring r = boost::process::search_path(bin).generic_wstring(); + if (!r.empty()) { - process.setWorkingDirectory(QString::fromStdWString(workingDirectory.wstr())); + ok = true; + return r; } - - QString command = QString::fromStdWString(commandPath); - for (const std::wstring& commandArgument: commandArguments) - { - command += QString::fromStdWString(L" " + commandArgument); - } - - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QStringList envlist = env.toStringList(); - envlist.replaceInStrings( - QRegularExpression(QStringLiteral("^(?i)PATH=(.*)")), - QStringLiteral("PATH=/opt/local/bin:/usr/local/bin:$HOME/bin:\\1")); - process.setEnvironment(envlist); - - { - std::lock_guard lock(s_runningProcessesMutex); - process.start(command); - s_runningProcesses.insert(&process); - } - - process.waitForFinished(timeout); - { - std::lock_guard lock(s_runningProcessesMutex); - s_runningProcesses.erase(&process); - } - - // QProcess::ProcessError error = process.error(); - - const std::string processoutput = process.readAll().toStdString(); - const int exitCode = process.exitCode(); - process.close(); - - return std::make_pair(exitCode, utility::trim(processoutput)); + return bin; } -std::string utility::executeProcessUntilNoOutput( - const std::wstring& commandPath, - const std::vector& commandArguments, - const FilePath& workingDirectory, - const int waitTime) +std::wstring utility::searchPath(const std::wstring& bin) { - QProcess process; - process.setProcessChannelMode(QProcess::MergedChannels); + bool ok; + return searchPath(bin, ok); +} - if (!workingDirectory.empty()) +utility::ProcessOutput utility::executeProcess( + const std::wstring& command, + const std::vector& arguments, + const FilePath& workingDirectory, + const bool waitUntilNoOutput, + const int timeout, + bool logProcessOutput) +{ + std::string output = ""; + int exitCode = 255; + try { - process.setWorkingDirectory(QString::fromStdWString(workingDirectory.wstr())); - } + boost::asio::io_service ios; + boost::process::async_pipe ap(ios); - QString command = QString::fromStdWString(commandPath); - for (const std::wstring& commandArgument: commandArguments) - { - command += QString::fromStdWString(L" " + commandArgument); - } + std::shared_ptr process; - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QStringList envlist = env.toStringList(); - envlist.replaceInStrings( - QRegularExpression(QStringLiteral("^(?i)PATH=(.*)")), - QStringLiteral("PATH=/opt/local/bin:/usr/local/bin:$HOME/bin:\\1")); - process.setEnvironment(envlist); - - { - std::lock_guard lock(s_runningProcessesMutex); - process.start(command); - s_runningProcesses.insert(&process); - } - - std::string processoutput = ""; - while (!process.waitForFinished(waitTime)) - { - const std::string currentOutput = process.readAll().toStdString(); - if (currentOutput.empty()) + boost::process::environment env = boost::this_process::environment(); + std::vector previousPath = env["PATH"].to_vector(); + env["PATH"] = {"/opt/local/bin", "/usr/local/bin", "$HOME/bin"}; + for (const std::string& entry: previousPath) { - LOG_WARNING( - "Canceling process because it did not generate any output during the last " + - std::to_string(waitTime / 1000) + " seconds."); - break; + env["PATH"].append(entry); + } + + if (workingDirectory.empty()) + { + process = std::make_shared( + searchPath(command), + boost::process::args(arguments), + env, + boost::process::std_in.close(), + (boost::process::std_out & boost::process::std_err) > ap); } else { - processoutput += currentOutput; + process = std::make_shared( + searchPath(command), + boost::process::args(arguments), + boost::process::start_dir(workingDirectory.wstr()), + env, + boost::process::std_in.close(), + (boost::process::std_out & boost::process::std_err) > ap); } - } - { - std::lock_guard lock(s_runningProcessesMutex); - s_runningProcesses.erase(&process); - } + { + std::lock_guard lock(s_runningProcessesMutex); + s_runningProcesses.insert(process); + } - processoutput += process.readAll().toStdString(); - process.close(); - processoutput = utility::trim(processoutput); - - return processoutput; -} - -int utility::executeProcessAndGetExitCode( - const std::wstring& commandPath, - const std::vector& commandArguments, - const FilePath& workingDirectory, - const int timeout, - bool logProcessOutput, - std::wstring* errorMessage) -{ - bool finished = false; - - QProcess process; - - QObject::connect( - &process, &QProcess::errorOccurred, [&finished, errorMessage](QProcess::ProcessError error) { - finished = true; - if (errorMessage != nullptr) - { - switch (error) - { - case QProcess::FailedToStart: - *errorMessage = L"File not found or resource error occurred."; - break; - case QProcess::Crashed: - *errorMessage = L"Process crashed."; - break; - case QProcess::Timedout: - *errorMessage = L"Process timed out."; - break; - case QProcess::ReadError: - *errorMessage = L"A read error occurred while executing process."; - break; - case QProcess::WriteError: - *errorMessage = L"A write error occurred while executing process."; - break; - case QProcess::UnknownError: - *errorMessage = L"An unknown error occurred while executing process."; - break; - } - }; + ScopedFunctor remover([process]() { + std::lock_guard lock(s_runningProcessesMutex); + s_runningProcesses.erase(process); }); - QObject::connect( - &process, - static_cast(&QProcess::finished), - [&finished](int exitCode, QProcess::ExitStatus exitStatus) { finished = true; }); + bool outputReceived = false; + std::vector buf(128); + auto stdOutBuffer = boost::asio::buffer(buf); + std::string logBuffer; + std::function onStdOut = + [&output, &buf, &stdOutBuffer, &ap, &onStdOut, &outputReceived, &logBuffer, logProcessOutput]( + const boost::system::error_code& ec, std::size_t size) { + std::string text; + text.reserve(size); + text.insert(text.end(), buf.begin(), buf.begin() + size); - if (!workingDirectory.empty()) - { - process.setWorkingDirectory(QString::fromStdWString(workingDirectory.wstr())); - } + if (!text.empty()) + { + outputReceived = true; + } - QString command = QString::fromStdWString(commandPath); - for (const std::wstring& commandArgument: commandArguments) - { - command += QString::fromStdWString(L" " + commandArgument); - } - - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QStringList envlist = env.toStringList(); - envlist.replaceInStrings( - QRegularExpression(QStringLiteral("^(?i)PATH=(.*)")), - QStringLiteral("PATH=/opt/local/bin:/usr/local/bin:$HOME/bin:\\1")); - process.setEnvironment(envlist); - - { - std::lock_guard lock(s_runningProcessesMutex); - process.start(command); - s_runningProcesses.insert(&process); - } - - { - std::wstring outputBuffer; - std::wstring errorBuffer; - if (timeout == -1) - { - while (!finished && !process.waitForFinished(1000)) - { + output += text; if (logProcessOutput) { - logProcessStreams(process, outputBuffer, errorBuffer); + logBuffer += text; + const bool isEndOfLine = (logBuffer.back() == '\n'); + const std::vector lines = utility::splitToVector(logBuffer, "\n"); + for (size_t i = 0; i < lines.size() - (isEndOfLine ? 0 : 1); i++) + { + LOG_INFO_BARE("Process output: " + lines[i]); + } + if (isEndOfLine) + { + logBuffer.clear(); + } + else + { + logBuffer = lines.back(); + } + } + if (!ec) + { + boost::asio::async_read(ap, stdOutBuffer, onStdOut); + } + }; + + boost::asio::async_read(ap, stdOutBuffer, onStdOut); + ios.run(); + + if (timeout > 0) + { + if (waitUntilNoOutput) + { + while (!process->wait_for(std::chrono::milliseconds(timeout))) + { + if (!outputReceived) + { + LOG_WARNING( + "Canceling process because it did not generate any output during the " + "last " + + std::to_string(timeout / 1000) + " seconds."); + process->terminate(); + break; + } + outputReceived = false; + } + } + else + { + if (!process->wait_for(std::chrono::milliseconds(timeout))) + { + LOG_WARNING( + "Canceling process because it timed out after " + + std::to_string(timeout / 1000) + " seconds."); + process->terminate(); } } } else { - if (!finished) - { - process.waitForFinished(timeout); - } + process->wait(); } if (logProcessOutput) { - logProcessStreams(process, outputBuffer, errorBuffer); + for (const std::string& line: utility::splitToVector(logBuffer, "\n")) + { + LOG_INFO_BARE("Process output: " + line); + } } + + exitCode = process->exit_code(); } + catch (const boost::process::process_error& e) { - std::lock_guard lock(s_runningProcessesMutex); - s_runningProcesses.erase(&process); + ProcessOutput ret; + ret.error = utility::decodeFromUtf8(e.code().message()); + ret.exitCode = e.code().value(); + LOG_ERROR_BARE(L"Process error: " + ret.error); + + return ret; } - const int exitCode = process.exitCode(); - process.close(); - return exitCode; + ProcessOutput ret; + ret.output = utility::trim(utility::decodeFromUtf8(output)); + ret.exitCode = exitCode; + return ret; } void utility::killRunningProcesses() { std::lock_guard lock(s_runningProcessesMutex); - for (QProcess* process: s_runningProcesses) + for (std::shared_ptr process: s_runningProcesses) { - process->kill(); + process->terminate(); } } @@ -307,4 +238,4 @@ std::string utility::getOsTypeString() break; } return "unknown"; -} \ No newline at end of file +} diff --git a/src/lib_gui/utility/utilityApp.h b/src/lib_gui/utility/utilityApp.h index 9835b814..d46bbf48 100644 --- a/src/lib_gui/utility/utilityApp.h +++ b/src/lib_gui/utility/utilityApp.h @@ -9,25 +9,27 @@ namespace utility { -std::pair executeProcess( - const std::wstring& commandPath, - const std::vector& commandArguments, - const FilePath& workingDirectory = FilePath(), - const int timeout = 30000); -std::string executeProcessUntilNoOutput( - const std::wstring& commandPath, - const std::vector& commandArguments, - const FilePath& workingDirectory, - int waitTime = 10000); -int executeProcessAndGetExitCode( - const std::wstring& commandPath, - const std::vector& commandArguments, +struct ProcessOutput +{ + std::wstring output; + std::wstring error; + int exitCode; +}; + +std::wstring searchPath(const std::wstring& bin, bool& ok); + +std::wstring searchPath(const std::wstring& bin); + +ProcessOutput executeProcess( + const std::wstring& command, + const std::vector& arguments, const FilePath& workingDirectory = FilePath(), + const bool waitUntilNoOutput = false, const int timeout = 30000, - bool logProcessOutput = false, - std::wstring* errorMessage = nullptr); + bool logProcessOutput = false); void killRunningProcesses(); + int getIdealThreadCount(); constexpr OsType getOsType() diff --git a/src/lib_java/utility/utilityMaven.cpp b/src/lib_java/utility/utilityMaven.cpp index 0403db80..acd8b16f 100644 --- a/src/lib_java/utility/utilityMaven.cpp +++ b/src/lib_java/utility/utilityMaven.cpp @@ -104,12 +104,8 @@ std::wstring mavenGenerateSources( auto args = getMavenArgs(settingsFilePath); args.push_back(L"generate-sources"); - std::shared_ptr outputAccess = TextAccess::createFromString( - utility::executeProcessUntilNoOutput( - mavenPath.wstr(), - args, - projectDirectoryPath, - 60000)); + std::shared_ptr outputAccess = TextAccess::createFromString(utility::encodeToUtf8( + utility::executeProcess(mavenPath.wstr(), args, projectDirectoryPath, true, 60000).output)); if (outputAccess->isEmpty()) { @@ -132,12 +128,8 @@ bool mavenCopyDependencies( args.push_back(L"dependency:copy-dependencies"); args.push_back(L"-DoutputDirectory=" + outputDirectoryPath.wstr()); - std::shared_ptr outputAccess = TextAccess::createFromString( - utility::executeProcessUntilNoOutput( - mavenPath.wstr(), - args, - projectDirectoryPath, - 60000)); + std::shared_ptr outputAccess = TextAccess::createFromString(utility::encodeToUtf8( + utility::executeProcess(mavenPath.wstr(), args, projectDirectoryPath, true, 60000).output)); const std::wstring errorMessage = getErrorMessageFromMavenOutput(outputAccess); if (!errorMessage.empty()) @@ -165,12 +157,8 @@ std::vector mavenGetAllDirectoriesFromEffectivePom( args.push_back(L"help:effective-pom"); args.push_back(L"-Doutput=" + outputPath.wstr()); - std::shared_ptr outputAccess = TextAccess::createFromString( - utility::executeProcessUntilNoOutput( - mavenPath.wstr(), - args, - projectDirectoryPath, - 60000)); + std::shared_ptr outputAccess = TextAccess::createFromString(utility::encodeToUtf8( + utility::executeProcess(mavenPath.wstr(), args, projectDirectoryPath, true, 60000).output)); const std::wstring errorMessage = getErrorMessageFromMavenOutput(outputAccess); if (!errorMessage.empty()) diff --git a/src/lib_python/project/SourceGroupPythonEmpty.cpp b/src/lib_python/project/SourceGroupPythonEmpty.cpp index dfe7a498..42156a16 100644 --- a/src/lib_python/project/SourceGroupPythonEmpty.cpp +++ b/src/lib_python/project/SourceGroupPythonEmpty.cpp @@ -49,25 +49,28 @@ std::set SourceGroupPythonEmpty::getAllSourceFilePaths() const std::vector> SourceGroupPythonEmpty::getIndexerCommands( const RefreshInfo& info) const { - std::wstring args = L""; + std::vector args; + args.push_back(L"index"); - args += L" --source-file-path=%{SOURCE_FILE_PATH}"; - args += L" --database-file-path=%{DATABASE_FILE_PATH}"; + args.push_back(L"--source-file-path"); + args.push_back(L"%{SOURCE_FILE_PATH}"); + args.push_back(L"--database-file-path"); + args.push_back(L"%{DATABASE_FILE_PATH}"); if (!m_settings->getEnvironmentPath().empty()) { - args += L" --environment-path=\"" + - m_settings->getEnvironmentPathExpandedAndAbsolute().wstr() + L"\""; + args.push_back(L"--environment-path"); + args.push_back(m_settings->getEnvironmentPathExpandedAndAbsolute().wstr()); } if (ApplicationSettings::getInstance()->getVerboseIndexerLoggingEnabled()) { - args += L" --verbose"; + args.push_back(L"--verbose"); } if (info.shallow) { - args += L" --shallow"; + args.push_back(L"--shallow"); } std::vector> indexerCommands; @@ -77,8 +80,8 @@ std::vector> SourceGroupPythonEmpty::getIndexerC { indexerCommands.push_back(std::make_shared( INDEXER_COMMAND_PYTHON, - L"\"" + ResourcePaths::getPythonPath().wstr() + - L"SourcetrailPythonIndexer\" index" + args, + ResourcePaths::getPythonIndexerFilePath().wstr(), + args, m_settings->getProjectSettings()->getProjectFilePath(), m_settings->getProjectSettings()->getTempDBFilePath(), std::to_wstring(SqliteIndexStorage::getStorageVersion()), diff --git a/src/test/PythonIndexerTestSuite.cpp b/src/test/PythonIndexerTestSuite.cpp index c97d387b..7666e38c 100644 --- a/src/test/PythonIndexerTestSuite.cpp +++ b/src/test/PythonIndexerTestSuite.cpp @@ -56,28 +56,38 @@ std::shared_ptr parseCode(std::string code) const std::set includeFilters; const FilePath workingDirectory(L"."); - std::wstring args = L""; - args += L" --source-file-path=%{SOURCE_FILE_PATH}"; - args += L" --database-file-path=%{DATABASE_FILE_PATH}"; - args += L" --shallow"; + std::vector args; + args.push_back(L"index"); + args.push_back(L"--source-file-path"); + args.push_back(L"%{SOURCE_FILE_PATH}"); + args.push_back(L"--database-file-path"); + args.push_back(L"%{DATABASE_FILE_PATH}"); + args.push_back(L"--shallow"); std::shared_ptr indexerCommand = std::make_shared( INDEXER_COMMAND_PYTHON, - L"\"" + - FilePath("../app").getConcatenated(ResourcePaths::getPythonPath()).makeAbsolute().wstr() + - L"SourcetrailPythonIndexer\" index" + args, + FilePath("../app") + .getConcatenated(ResourcePaths::getPythonIndexerFilePath()) + .makeAbsolute() + .makeCanonical() + .wstr(), + args, rootPath, tempDbPath, std::to_wstring(SqliteIndexStorage::getStorageVersion()), sourceFilePath, true); - std::wstring errorMessage; - const int result = utility::executeProcessAndGetExitCode( - indexerCommand->getCustomCommand(), {}, rootPath, -1, true, &errorMessage); + const utility::ProcessOutput out = utility::executeProcess( + indexerCommand->getCommand(), indexerCommand->getArguments(), rootPath, false, -1, true); - REQUIRE(result == 0); - REQUIRE(errorMessage.empty()); + if (!out.error.empty()) + { + FAIL( + "Error occurred while running the indexer: \"" + utility::encodeToUtf8(out.error) + + "\". Process output was: \"" + utility::encodeToUtf8(out.output) + "\""); + } + REQUIRE(out.exitCode == 0); } std::shared_ptr testStorage; diff --git a/src/test/SourceGroupTestSuite.cpp b/src/test/SourceGroupTestSuite.cpp index b5c5562a..6c64c25e 100644 --- a/src/test/SourceGroupTestSuite.cpp +++ b/src/test/SourceGroupTestSuite.cpp @@ -148,9 +148,15 @@ std::wstring indexerCommandCustomToString( std::shared_ptr indexerCommand, const FilePath& baseDirectory) { std::wstring result; - result += L"SourceFilePath: \"" + + result += L"IndexerCommandCustom\n"; + result += L"\tSourceFilePath: \"" + indexerCommand->getSourceFilePath().getRelativeTo(baseDirectory).wstr() + L"\"\n"; - result += L"\tCustom Command: \"" + indexerCommand->getCustomCommand() + L"\"\n"; + result += L"\tCustom Command: \"" + indexerCommand->getCommand() + L"\"\n"; + result += L"\tArguments:\n"; + for (const std::wstring& argument: indexerCommand->getArguments()) + { + result += L"\t\t\"" + argument + L"\"\n"; + } return result; }