From 802153883e1d9952bfade67af35e07ec58faddaa Mon Sep 17 00:00:00 2001 From: Andreas Stallinger Date: Wed, 9 Aug 2017 12:33:43 +0200 Subject: [PATCH] logic: commandline indexing and configuration --- .gitlab-ci.yml | 2 +- CMakeLists.txt | 26 +- cmake/CLANGConfig.cmake | 5 - cmake/external.cmake | 17 -- cmake/pre_install_linux.cmake | 8 +- src/app/main.cpp | 166 ++++++----- src/lib/Application.cpp | 20 +- src/lib/CMakeLists.txt | 19 +- src/lib/LicenseChecker.cpp | 18 +- src/lib/data/TaskFinishParsing.cpp | 11 + src/lib/data/graph/Token.h | 2 +- src/lib/data/indexer/TaskBuildIndex.cpp | 11 + src/lib/data/parser/TaskParseWrapper.cpp | 2 +- src/lib/project/Project.cpp | 18 +- src/lib/settings/ApplicationSettings.cpp | 4 +- src/lib/settings/ApplicationSettings.h | 2 +- .../utility/commandline/CommandLineParser.cpp | 279 +++++++++++------- .../utility/commandline/CommandLineParser.h | 48 ++- .../utility/commandline/CommandlineHelper.cpp | 60 ++++ .../utility/commandline/CommandlineHelper.h | 35 +++ .../commands/CommandlineCommand.cpp | 36 +++ .../commandline/commands/CommandlineCommand.h | 72 +++++ .../commands/CommandlineCommandConfig.cpp | 257 ++++++++++++++++ .../commands/CommandlineCommandConfig.h | 31 ++ .../commands/CommandlineCommandIndex.cpp | 63 ++++ .../commands/CommandlineCommandIndex.h | 28 ++ .../CommandlineSourceGroupOptions.cpp | 6 + .../commands/CommandlineSourceGroupOptions.h | 19 ++ .../CommandlineSourceGroupOptionsC.cpp | 6 + .../commands/CommandlineSourceGroupOptionsC.h | 12 + .../CommandlineSourceGroupOptionsCxx.cpp | 6 + .../CommandlineSourceGroupOptionsCxx.h | 12 + .../CommandlineSourceGroupOptionsJava.cpp | 42 +++ .../CommandlineSourceGroupOptionsJava.h | 17 ++ src/lib_cxx/data/parser/cxx/ASTAction.h | 1 + src/lib_cxx/utility/CompilationDatabase.cpp | 1 + src/lib_gui/CMakeLists.txt | 28 ++ src/lib_gui/qt/QtApplication.cpp | 1 + src/lib_gui/qt/QtApplication.h | 1 - src/lib_gui/qt/QtCoreApplication.cpp | 33 +-- src/lib_gui/qt/QtCoreApplication.h | 11 +- src/lib_gui/qt/view/QtDialogView.cpp | 9 - src/lib_gui/qt/window/QtStartScreen.cpp | 2 +- .../QtProjectWizzardContentPreferences.cpp | 2 +- src/lib_gui/utility/utilityApp.cpp | 35 +++ src/lib_gui/utility/utilityApp.h | 3 + src/lib_license/License.cpp | 23 ++ src/lib_license/License.h | 8 +- src/license_generator/Generator.cpp | 11 +- src/test/CMakeLists.txt | 1 + src/test/CommandlineTestSuite.h | 139 +++++++++ src/test/GeneratorTestSuite.h | 11 +- src/test/JavaParserTestSuite.h | 2 +- 53 files changed, 1384 insertions(+), 298 deletions(-) delete mode 100644 cmake/external.cmake create mode 100644 src/lib/utility/commandline/CommandlineHelper.cpp create mode 100644 src/lib/utility/commandline/CommandlineHelper.h create mode 100644 src/lib/utility/commandline/commands/CommandlineCommand.cpp create mode 100644 src/lib/utility/commandline/commands/CommandlineCommand.h create mode 100644 src/lib/utility/commandline/commands/CommandlineCommandConfig.cpp create mode 100644 src/lib/utility/commandline/commands/CommandlineCommandConfig.h create mode 100644 src/lib/utility/commandline/commands/CommandlineCommandIndex.cpp create mode 100644 src/lib/utility/commandline/commands/CommandlineCommandIndex.h create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.cpp create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.h create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.cpp create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.h create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.cpp create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.cpp create mode 100644 src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.h create mode 100644 src/test/CommandlineTestSuite.h diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 45a240ef..89c5c8d4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ - ./script/setup.sh - ./script/buildonly.sh all - ./script/buildonly.sh package - - ./build/Release/app/Sourcetrail --licenseFile ./setup/license.txt + - ./build/Release/app/Sourcetrail config -z ./setup/license.txt - cd ./bin/test - ../../build/Release/test/Sourcetrail_test diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c432805..13735637 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,14 @@ include(cmake/create_source_groups.cmake) include(cmake/version.cmake) include(cmake/version_setup.cmake) include(cmake/licenses.cmake) -include(cmake/setWinXxBits.cmake) + + +# prohibit in-source-builds +IF(${CMAKE_BINARY_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) + MESSAGE(STATUS "In-source-builds are not allowed") + MESSAGE(STATUS "Clean your source directory (e.g. delete the CMakeCache.txt file)") + MESSAGE(FATAL_ERROR "Please create a separate build directory and call CMake again") +ENDIF(${CMAKE_BINARY_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) # Variables -------------------------------------------------------------------- @@ -28,6 +35,7 @@ set(TEST_PROJECT_NAME "${PROJECT_NAME}_test") set (APP_INDEXER_NAME "${PROJECT_NAME_LOWER_CASE}_indexer") if (WIN32) + include(cmake/setWinXxBits.cmake) set(PLATFORM_INCLUDE "includesWindows.h") # this adds the library path for VLD, must be done before the project target is created if(${WINXXBITS} STREQUAL "Win32") @@ -53,7 +61,6 @@ if(UNIX AND NOT APPLE) set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib/:$$ORIGIN/lib/") - include(cmake/external.cmake) endif() set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -183,14 +190,13 @@ endif () add_subdirectory(src/lib_license) -add_library(${LIB_LICENSE_PROJECT_NAME} ${LIB_LICENSE_FILES}) +add_library(${LIB_LICENSE_PROJECT_NAME} STATIC ${LIB_LICENSE_FILES}) create_source_groups(${LIB_LICENSE_FILES}) -set_property( - TARGET ${LIB_LICENSE_PROJECT_NAME} - PROPERTY INCLUDE_DIRECTORIES - "${CMAKE_SOURCE_DIR}/src/lib_license" +target_include_directories( ${LIB_LICENSE_PROJECT_NAME} PUBLIC + "${CMAKE_SOURCE_DIR}/src/lib_license" + "${CMAKE_BINARY_DIR}/src/lib_license" ) target_include_directories(${LIB_LICENSE_PROJECT_NAME} SYSTEM @@ -358,6 +364,8 @@ add_custom_target( add_library(${LIB_GUI_PROJECT_NAME} ${LIB_GUI_FILES} ${CMAKE_BINARY_DIR}/src/lib_gui/version.h) +target_link_libraries(${LIB_GUI_PROJECT_NAME} Qt5::Widgets Qt5::Network) + # command for versioning script add_custom_command( TARGET versionnumber @@ -391,8 +399,8 @@ target_include_directories(${LIB_GUI_PROJECT_NAME} SYSTEM ) # Use the Widgets module from Qt 5. -qt5_use_modules(${LIB_GUI_PROJECT_NAME} Widgets) -qt5_use_modules(${LIB_GUI_PROJECT_NAME} Network) +#qt5_use_modules(${LIB_GUI_PROJECT_NAME} Widgets) +#qt5_use_modules(${LIB_GUI_PROJECT_NAME} Network) # configure platform specific include file configure_file( diff --git a/cmake/CLANGConfig.cmake b/cmake/CLANGConfig.cmake index c65cbce2..08467f0a 100644 --- a/cmake/CLANGConfig.cmake +++ b/cmake/CLANGConfig.cmake @@ -1,4 +1,3 @@ -include(cmake/external.cmake) if (UNIX AND APPLE) if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") @@ -50,10 +49,6 @@ if(UNIX AND NOT APPLE) OUTPUT_VARIABLE CLANG_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE ) - #set(CLANG_INCLUDE_DIRS - #"${EXTERNAL_SRC}/clang/include" - #"${CLANG_BUILD_PATH}/tools/clang/include" - #) else() set(CLANG_INCLUDE_DIRS "$ENV{CLANG_DIR}/llvm/tools/clang/include" diff --git a/cmake/external.cmake b/cmake/external.cmake deleted file mode 100644 index 55ed97ae..00000000 --- a/cmake/external.cmake +++ /dev/null @@ -1,17 +0,0 @@ - -find_package(PythonInterp REQUIRED) - -execute_process( - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_SOURCE_DIR}/script/getSystemString.py" - OUTPUT_VARIABLE SYSSTRING - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -set(EXTERNAL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../Sourcetrail_External") -set(EXTERNAL_SRC "${EXTERNAL_ROOT}/src") -if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(EXTERNAL_BUILD "${EXTERNAL_ROOT}/${SYSSTRING}/Debug") -else() - set(EXTERNAL_BUILD "${EXTERNAL_ROOT}/${SYSSTRING}/Release") -endif() - diff --git a/cmake/pre_install_linux.cmake b/cmake/pre_install_linux.cmake index e5b192c6..f6fb21ac 100644 --- a/cmake/pre_install_linux.cmake +++ b/cmake/pre_install_linux.cmake @@ -15,18 +15,18 @@ set(binPath ${CMAKE_CURRENT_LIST_DIR}/../build/Release/app/Sourcetrail) set(projPath ${CMAKE_CURRENT_LIST_DIR}/../bin/app/user/projects) execute_process( - COMMAND ${binPath} -z ${CMAKE_CURRENT_LIST_DIR}/../setup/license.txt + COMMAND ${binPath} config -z ${CMAKE_CURRENT_LIST_DIR}/../setup/license.txt ) execute_process( - COMMAND ${binPath} -f -d ${projPath}/tictactoe/tictactoe.srctrlprj + COMMAND ${binPath} index --full ${projPath}/tictactoe/tictactoe.srctrlprj ) execute_process( - COMMAND ${binPath} -f -d ${projPath}/tutorial/tutorial.srctrlprj + COMMAND ${binPath} index --full ${projPath}/tutorial/tutorial.srctrlprj ) execute_process( - COMMAND ${binPath} -f -d ${projPath}/javaparser/javaparser.srctrlprj + COMMAND ${binPath} index --full ${projPath}/javaparser/javaparser.srctrlprj ) diff --git a/src/app/main.cpp b/src/app/main.cpp index ff4bb9ec..28b35c3b 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -1,5 +1,7 @@ #include "includes.h" // defines 'void setup(int argc, char *argv[])' +#include + #include "Application.h" #include "data/indexer/IndexerFactory.h" #include "data/indexer/IndexerFactoryModuleJava.h" @@ -11,6 +13,7 @@ #include "project/SourceGroupFactoryModuleCpp.h" #include "project/SourceGroupFactoryModuleJava.h" #include "qt/network/QtNetworkFactory.h" +#include #include "qt/QtApplication.h" #include "qt/QtCoreApplication.h" #include "qt/utility/utilityQt.h" @@ -33,6 +36,19 @@ #include "utility/Version.h" #include "version.h" +void signalHandler( int signum ) +{ + std::string s; + std::cout << "interrupt are you sure(Y/n):" << std::flush; + std::cin >> s; + std::cout << "\n*******\n" << s << "\n*******\n" << std::endl; + if (s == "Y" || s == "y") + { + std::cout << "quit()" << std::endl; + QCoreApplication::quit(); + } +} + void setupLogging() { LogManager* logManager = LogManager::getInstance().get(); @@ -60,7 +76,7 @@ void prefillJavaRuntimePath() { MessageStatus("Ran Java runtime path detection, found: " + paths.front().str()); - settings->setJavaPath(paths.front().str()); + settings->setJavaPath(paths.front()); settings->save(); } else @@ -166,6 +182,18 @@ void addLanguageModules() IndexerFactory::getInstance()->addModule(std::make_shared()); } +QCoreApplication* createApplication(int &argc, char *argv[], bool noGUI = false) +{ + if (noGUI) + { + return new QtCoreApplication(argc, argv); + } + else + { + return new QtApplication(argc, argv); + } +} + int main(int argc, char *argv[]) { QApplication::setApplicationName("Sourcetrail"); @@ -175,48 +203,70 @@ int main(int argc, char *argv[]) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); } - Version version( + Version version( VERSION_YEAR, VERSION_MINOR, - VERSION_COMMIT, - GIT_COMMIT_HASH - ); + VERSION_COMMIT, + GIT_COMMIT_HASH + ); QApplication::setApplicationVersion(version.toDisplayString().c_str()); MessageStatus("Starting Sourcetrail " + version.toDisplayString()).dispatch(); - CommandLineParser commandLineParser(argc, argv, version.toString()); + commandline::CommandLineParser commandLineParser(version.toString()); + commandLineParser.preparse(argc, argv); if (commandLineParser.exitApplication()) { return 0; } + setupPlatform(argc, argv); + + QScopedPointer qtApp(createApplication(argc, argv, commandLineParser.runWithoutGUI())); + setupApp(argc, argv); + setupLogging(); + + QScopedPointer networkFactory; + QScopedPointer viewFactory; + + if (commandLineParser.runWithoutGUI()) { - setupPlatform(argc, argv); - - // headless Sourcetrail - QtCoreApplication qtApp(argc, argv); - - setupApp(argc, argv); - - setupLogging(); - - Application::createInstance(version, nullptr, nullptr); - ScopedFunctor f([](){ - Application::destroyInstance(); - }); - - prefillPaths(); - addLanguageModules(); - - std::shared_ptr checker = LicenseChecker::getInstance(); + commandLineParser.parse(); if (commandLineParser.startedWithLicense()) { - qtApp.saveLicense(commandLineParser.getLicense()); + qobject_cast(qtApp.data())->saveLicense(commandLineParser.getLicense()); + } + if (commandLineParser.exitApplication()) + { return 0; } + } + else + { + qtApp->setAttribute(Qt::AA_UseHighDpiPixmaps); + + utility::loadFontsFromDirectory(ResourcePaths::getFontsPath(), ".otf"); + utility::loadFontsFromDirectory(ResourcePaths::getFontsPath(), ".ttf"); + + networkFactory.reset(new QtNetworkFactory()); + viewFactory.reset(new QtViewFactory()); + } + + + Application::createInstance(version, viewFactory.data(), networkFactory.data()); + + ScopedFunctor f([](){ + Application::destroyInstance(); + }); + + prefillPaths(); + addLanguageModules(); + + if (commandLineParser.runWithoutGUI()) + { + std::shared_ptr checker = LicenseChecker::getInstance(); if (!checker->isCurrentLicenseValid()) // this works because the user cannot enter a license string while running the app in headless more. { @@ -228,58 +278,38 @@ int main(int argc, char *argv[]) { MessageEnteredLicense(checker->getCurrentLicenseType()).dispatch(); } + struct sigaction sa; + sa.sa_handler = signalHandler; + sa.sa_flags = 0; + ::sigemptyset(&sa.sa_mask); + // sa.sa_flags |= SA_RESTART; + if(::sigaction(SIGINT, &sa, NULL)) + { + } + } - if (commandLineParser.hasError() ) + if (commandLineParser.hasError() ) + { + if (commandLineParser.runWithoutGUI()) { std::cout << commandLineParser.getError() << std::endl; } else { - MessageLoadProject( - commandLineParser.getProjectFilePath(), - commandLineParser.getFullProjectRefresh() - ).dispatch(); + Application::getInstance()->handleDialog(commandLineParser.getError()); } - return qtApp.exec(); } else { - setupPlatform(argc, argv); - - QtApplication qtApp(argc, argv); - - setupApp(argc, argv); - - setupLogging(); - - qtApp.setAttribute(Qt::AA_UseHighDpiPixmaps); - - QtViewFactory viewFactory; - QtNetworkFactory networkFactory; - - Application::createInstance(version, &viewFactory, &networkFactory); - ScopedFunctor f([](){ - Application::destroyInstance(); - }); - - prefillPaths(); - addLanguageModules(); - - utility::loadFontsFromDirectory(ResourcePaths::getFontsPath(), ".otf"); - utility::loadFontsFromDirectory(ResourcePaths::getFontsPath(), ".ttf"); - - if (commandLineParser.hasError()) - { - Application::getInstance()->handleDialog(commandLineParser.getError()); - } - else - { - MessageLoadProject( - commandLineParser.getProjectFilePath(), - commandLineParser.getFullProjectRefresh() - ).dispatch(); - } - - return qtApp.exec(); + MessageLoadProject( + commandLineParser.getProjectFilePath(), + commandLineParser.getFullProjectRefresh() + ).dispatch(); } + + + int exitcode = qtApp->exec(); + + return exitcode; + } diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index 9e64399e..40f8bdfa 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -6,6 +6,7 @@ #include "utility/messaging/filter_types/MessageFilterFocusInOut.h" #include "utility/messaging/filter_types/MessageFilterSearchAutocomplete.h" #include "utility/messaging/MessageQueue.h" +#include "utility/messaging/type/MessageQuitApplication.h" #include "utility/messaging/type/MessageStatus.h" #include "utility/scheduling/TaskScheduler.h" #include "utility/tracing.h" @@ -230,6 +231,10 @@ void Application::refreshProject(bool force) m_componentManager->refreshViews(); } } + else if (!m_hasGUI) + { + MessageQuitApplication().dispatch(); + } } } @@ -270,18 +275,17 @@ void Application::handleMessage(MessageLoadProject* message) return; } - if (m_project && projectSettingsFilePath == m_project->getProjectSettingsFilePath()) + if (!m_project || projectSettingsFilePath != m_project->getProjectSettingsFilePath()) { - if (message->forceRefresh) - { - m_project->setStateSettingsUpdated(); - refreshProject(false); - } + createAndLoadProject(projectSettingsFilePath); + } - return; + if (message->forceRefresh) + { + m_project->setStateSettingsUpdated(); + refreshProject(false); } - createAndLoadProject(projectSettingsFilePath); } void Application::handleMessage(MessageRefresh* message) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 4ba55b5c..988003d5 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -21,8 +21,9 @@ add_files( component/controller/BookmarkController.h component/controller/CodeController.cpp component/controller/CodeController.h - component/controller/Controller.cpp - component/controller/Controller.h + #component/controller/Controller.cpp + component/controller/Controller + #component/controller/Controller.h component/controller/ErrorController.cpp component/controller/ErrorController.h component/controller/GraphController.cpp @@ -299,10 +300,23 @@ add_files( settings/SourceGroupSettingsJava.cpp settings/SourceGroupSettingsJava.h settings/SourceGroupType.cpp + settings/SourceGroupType.h + utility/commandline/CommandlineHelper.cpp + utility/commandline/CommandlineHelper.h utility/commandline/CommandLineParser.cpp utility/commandline/CommandLineParser.h + utility/commandline/commands/CommandlineCommand + utility/commandline/commands/CommandlineCommandConfig + utility/commandline/commands/CommandlineCommandIndex + # utility/commandline/commands/CommandlineSourceGroupOptions.h + # utility/commandline/commands/CommandlineSourceGroupOptionsC.cpp + # utility/commandline/commands/CommandlineSourceGroupOptionsC.h + # utility/commandline/commands/CommandlineSourceGroupOptionsCxx.cpp + # utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h + # utility/commandline/commands/CommandlineSourceGroupOptionsJava.cpp + # utility/commandline/commands/CommandlineSourceGroupOptionsJava.h utility/file/FileInfo.cpp utility/file/FileInfo.h @@ -399,6 +413,7 @@ add_files( utility/messaging/type/MessagePluginPortChange.h utility/messaging/type/MessageProjectEdit.h utility/messaging/type/MessageProjectNew.h + utility/messaging/type/MessageQuitApplication.h utility/messaging/type/MessageRedo.h utility/messaging/type/MessageRefresh.h utility/messaging/type/MessageResetZoom.h diff --git a/src/lib/LicenseChecker.cpp b/src/lib/LicenseChecker.cpp index a052c277..06151710 100644 --- a/src/lib/LicenseChecker.cpp +++ b/src/lib/LicenseChecker.cpp @@ -2,6 +2,7 @@ #include "utility/AppPath.h" #include "utility/logging/logging.h" +#include "utility/utilityApp.h" #include "utility/messaging/type/MessageForceEnterLicense.h" #include "License.h" @@ -44,25 +45,14 @@ std::string LicenseChecker::getCurrentLicenseString() const void LicenseChecker::saveCurrentLicenseString(const std::string& licenseString) const { License license; +// license.loadPublicKeyFromString(PUBLIC_KEY); bool isLoaded = license.loadFromString(licenseString); if (!isLoaded) { return; } - ApplicationSettings* appSettings = ApplicationSettings::getInstance().get(); - - if (appSettings == NULL) - { - LOG_ERROR_STREAM(<< "Unable to retrieve app settings"); - return; - } - - std::string appPath(AppPath::getAppPath()); - - appSettings->setLicenseString(license.getLicenseEncodedString(appPath)); - appSettings->setLicenseCheck(license.hashLocation(FilePath(appPath).absolute().str())); - appSettings->save(); + utility::saveLicense(&license); } bool LicenseChecker::isCurrentLicenseValid() @@ -194,7 +184,7 @@ void LicenseChecker::handleMessage(MessageEnteredLicense* message) LicenseChecker::LicenseState LicenseChecker::checkLicense(License& license) const { - license.loadPublicKeyFromString(PUBLIC_KEY); +// license.loadPublicKeyFromString(PUBLIC_KEY); if (license.isExpired()) { diff --git a/src/lib/data/TaskFinishParsing.cpp b/src/lib/data/TaskFinishParsing.cpp index 1eeac33f..f6b6762a 100644 --- a/src/lib/data/TaskFinishParsing.cpp +++ b/src/lib/data/TaskFinishParsing.cpp @@ -3,6 +3,7 @@ #include "component/view/DialogView.h" #include "data/storage/PersistentStorage.h" #include "utility/messaging/type/MessageFinishedParsing.h" +#include "utility/messaging/type/MessageQuitApplication.h" #include "utility/messaging/type/MessageStatus.h" #include "utility/scheduling/Blackboard.h" #include "utility/utility.h" @@ -41,6 +42,11 @@ Task::TaskState TaskFinishParsing::doUpdate(std::shared_ptr blackboa dialogView->hideUnknownProgressDialog(); MessageFinishedParsing().dispatch(); + if (!Application::getInstance()->hasGUI()) + { + MessageQuitApplication().dispatch(); + } + float time = utility::duration(start); if (blackboard->exists("clear_time")) @@ -98,4 +104,9 @@ void TaskFinishParsing::terminate() MessageStatus("An unknown exception was thrown during indexing.", true, false).dispatch(); MessageFinishedParsing().dispatch(); + + if (!Application::getInstance()->hasGUI()) + { + MessageQuitApplication().dispatch(); + } } diff --git a/src/lib/data/graph/Token.h b/src/lib/data/graph/Token.h index 322efa84..2e3518d3 100644 --- a/src/lib/data/graph/Token.h +++ b/src/lib/data/graph/Token.h @@ -50,7 +50,7 @@ private: template ComponentType* Token::getComponent() const { - for (std::shared_ptr component: m_components) + for (const std::shared_ptr& component: m_components) { TokenComponent* componentPtr = component.get(); if (typeid(ComponentType) == typeid(*componentPtr)) diff --git a/src/lib/data/indexer/TaskBuildIndex.cpp b/src/lib/data/indexer/TaskBuildIndex.cpp index ae1a846f..94c3e18e 100644 --- a/src/lib/data/indexer/TaskBuildIndex.cpp +++ b/src/lib/data/indexer/TaskBuildIndex.cpp @@ -11,6 +11,7 @@ #include "data/indexer/IndexerCommandList.h" #include "data/indexer/interprocess/InterprocessIndexer.h" #include "data/storage/StorageProvider.h" +#include "utility/messaging/type/MessageStatus.h" #if _WIN32 const std::string TaskBuildIndex::s_processName("sourcetrail_indexer.exe"); @@ -267,6 +268,16 @@ void TaskBuildIndex::updateIndexingDialog( blackboard->get("indexed_source_file_count", indexedSourceFileCount); } + if (!sourcePath.empty()) + { + std::stringstream ss; + ss << "[" << m_indexingFileCount + << "/" << sourceFileCount + << "] Indexing file: "; + ss << sourcePath.str(); + MessageStatus(ss.str(), false, true).dispatch(); + } + if (std::shared_ptr dialogView = Application::getInstance()->getDialogView()) { dialogView->updateIndexingDialog( diff --git a/src/lib/data/parser/TaskParseWrapper.cpp b/src/lib/data/parser/TaskParseWrapper.cpp index cbc9b976..6b407d30 100644 --- a/src/lib/data/parser/TaskParseWrapper.cpp +++ b/src/lib/data/parser/TaskParseWrapper.cpp @@ -22,7 +22,7 @@ void TaskParseWrapper::doEnter(std::shared_ptr blackboard) if (std::shared_ptr dialogView = Application::getInstance()->getDialogView()) { dialogView->updateIndexingDialog(0, 0, sourceFileCount, ""); - } + } m_start = utility::durationStart(); diff --git a/src/lib/project/Project.cpp b/src/lib/project/Project.cpp index 3b10b2b1..45d92934 100644 --- a/src/lib/project/Project.cpp +++ b/src/lib/project/Project.cpp @@ -108,9 +108,7 @@ bool Project::refresh(bool forceRefresh) Application::getInstance()->hasGUI() ) { - std::vector options; - options.push_back("Yes"); - options.push_back("No"); + std::vector options = { "Yes", "No" }; int result = dialogView->confirm( "Warning: You are about to index your project with the \"verbose indexer logging\" setting " "enabled. This will cause a significant slowdown in indexing performance. Do you want to proceed?", @@ -123,12 +121,9 @@ bool Project::refresh(bool forceRefresh) } } - if (!forceRefresh && needsFullRefresh && question.size() && Application::getInstance()->hasGUI()) { - std::vector options; - options.push_back("Yes"); - options.push_back("No"); + std::vector options = { "Yes", "No"}; int result = dialogView->confirm(question, options); if (result == 1) @@ -139,8 +134,7 @@ bool Project::refresh(bool forceRefresh) if (Application::getInstance()->isInTrial()) { - std::vector options; - options.push_back("Ok"); + std::vector options = { "Ok" }; dialogView->confirm("You can't refresh the project in trial mode, please unlock with a license key.", options); MessageDispatchWhenLicenseValid(std::make_shared()).dispatch(); @@ -148,7 +142,6 @@ bool Project::refresh(bool forceRefresh) return false; } - dialogView->showUnknownProgressDialog("Preparing Project", "Processing Files"); ScopedFunctor dialogHider([&dialogView](){ @@ -275,7 +268,9 @@ void Project::load() MessageStatus("Project not loaded", false, false).dispatch(); } - if (m_state != PROJECT_STATE_LOADED) + // refresh always on headless + // since just opening a project in headless does not make sense + if (m_state != PROJECT_STATE_LOADED || !Application::getInstance()->hasGUI()) { MessageRefresh().dispatch(); } @@ -355,6 +350,7 @@ bool Project::requestIndex(bool forceRefresh, bool needsFullRefresh) filesToAdd = staticSourceFiles; } + std::set staticSourceFilePaths; for (const FilePath& path: allSourceFilePaths) { diff --git a/src/lib/settings/ApplicationSettings.cpp b/src/lib/settings/ApplicationSettings.cpp index d14d493d..5267d5ba 100644 --- a/src/lib/settings/ApplicationSettings.cpp +++ b/src/lib/settings/ApplicationSettings.cpp @@ -262,9 +262,9 @@ std::string ApplicationSettings::getJavaPath() const return getValue("indexing/java/java_path", ""); } -void ApplicationSettings::setJavaPath(const std::string path) +void ApplicationSettings::setJavaPath(const FilePath& path) { - setValue("indexing/java/java_path", path); + setValue("indexing/java/java_path", path.str()); } int ApplicationSettings::getJavaMaximumMemory() const diff --git a/src/lib/settings/ApplicationSettings.h b/src/lib/settings/ApplicationSettings.h index 54a7b9e5..36e02426 100644 --- a/src/lib/settings/ApplicationSettings.h +++ b/src/lib/settings/ApplicationSettings.h @@ -79,7 +79,7 @@ public: void setMultiProcessIndexingEnabled(bool enabled); std::string getJavaPath() const; - void setJavaPath(const std::string path); + void setJavaPath(const FilePath& path); int getJavaMaximumMemory() const; void setJavaMaximumMemory(int size); diff --git a/src/lib/utility/commandline/CommandLineParser.cpp b/src/lib/utility/commandline/CommandLineParser.cpp index acbdfe1f..ae8f59cd 100644 --- a/src/lib/utility/commandline/CommandLineParser.cpp +++ b/src/lib/utility/commandline/CommandLineParser.cpp @@ -1,9 +1,14 @@ #include "utility/commandline/CommandLineParser.h" #include +#include +#include #include "boost/program_options.hpp" +#include "utility/commandline/CommandlineHelper.h" +#include "utility/commandline/commands/CommandlineCommandConfig.h" +#include "utility/commandline/commands/CommandlineCommandIndex.h" #include "utility/ConfigManager.h" #include "utility/text/TextAccess.h" #include "utility/utilityString.h" @@ -12,112 +17,172 @@ namespace po = boost::program_options; -CommandLineParser::CommandLineParser(int argc, char** argv, const std::string& version) - : m_force(false) - , m_quit(false) - , m_withLicense(false) - , m_withoutGUI(false) +namespace commandline { - std::string projectfile; - std::string projectfile_db; - std::string licensefile; - std::string licensetext; - po::options_description desc("Sourcetrail"); - desc.add_options() + +CommandLineParser::CommandLineParser(const std::string& version) + : m_version(version) +{ + setup(); +} + +void CommandLineParser::setup() +{ + po::options_description options("Sourcetrail Options"); + options.add_options() ("help,h", "Print this help message") ("version,v", "Version of Sourcetrail") - ("project,p", "Load Sourcetrail with a Sourcetrailprojectfile") + ("project-file", po::value(), "Open Sourcetrail with this project") ; - po::positional_options_description positionalOption; - positionalOption.add("project-file", 1); - po::options_description hidden_desc("hidden commandlineflags"); - hidden_desc.add_options() - ("force,f", "Force sourcetrail to parse if database exists") - ("licenseFile,z", po::value(&licensefile), "Enter license via Licensefile") - ("license,l", po::value(&licensetext), "Enter licenes via commandline") - ("hidden", "Print this help message with hidden arguments") - ("database,d", "Start sourcetrail to parse a Sourcetrail projectfile to get a sourcetraildatabase") - ("project-file", po::value(&projectfile), "Sourcetrail project file"); - ; - po::options_description all("Allowed options"); - all.add(desc).add(hidden_desc); + m_options.add(options); + m_positional.add("project-file", 1); + addCommand(std::make_unique(this)); + addCommand(std::make_unique(this)); - po::variables_map vm; - po::store(po::command_line_parser(argc,argv).options(all).positional(positionalOption).allow_unregistered().run(), vm); - po::notify(vm); - - if (vm.count("help")) + for ( auto& command : m_commands) { - std::cout << desc << std::endl; - m_quit = true; + command->setup(); } - if (vm.count("hidden")) - { - std::cout << all << std::endl; - m_quit = true; - } - - if (vm.count("force")) - { - m_force = true; - } - - if (vm.count("license")) - { - licensetext = utility::replace(licensetext, "\\n", "\n"); - processLicense(m_license.loadFromString(licensetext)); - } - - if (vm.count("licenseFile")) - { - std::cout << "licensefile flag" << std::endl; - if (FilePath(licensefile).exists()) - { - std::cout << "licensefile exists" << std::endl; - processLicense(m_license.loadFromFile(licensefile)); - } - else - { - std::cout << licensefile << " not found" << std::endl; - } - } - - if (vm.count("version")) - { - std::cout << "Sourcetrail Version " << version << std::endl; - m_quit = true; - } - - if (vm.count("project-file")) - { - processProjectfile(projectfile); - if (vm.count("database")) - { - m_withoutGUI = true; - } - } - else if (vm.count("database") || vm.count("project") ) { - std::cout << "A project file is needed for this option" << std::endl; - } } -void CommandLineParser::processLicense(const bool isLoaded) +void CommandLineParser::setProjectFile(const FilePath &filepath) { - if (!isLoaded) - { - std::cout << "Could not load License" << std::endl; - } - m_license.loadPublicKeyFromString(PUBLIC_KEY); - if (!m_license.isValid()) - { - std::cout << "License is not valid" << std::endl; - } - m_withLicense = true; - m_withoutGUI = true; + m_projectFile = filepath; + processProjectfile(); } +void CommandLineParser::addCommand(std::unique_ptr command) +{ + m_commands.push_back(std::move(command)); +} + +void CommandLineParser::preparse(int argc, char** argv) +{ + // put argv into a string vector + std::vector args; + for(int i = 1; i < argc; i++) + { + args.push_back(std::string(argv[i])); + } + + preparse(args); +} + +void CommandLineParser::preparse(std::vector& args) +{ + if (args.size() < 1) + { + return; + } + m_args = std::move(args); + try + { + // parsing for all commands + for ( auto& command : m_commands) + { + if ( m_args[0] == command->name()) + { + m_withoutGUI = true; + return; + } + } + + po::variables_map vm; + po::positional_options_description positional; + positional.add("project-file",1); + po::store(po::command_line_parser(m_args).options(m_options).positional(positional).allow_unregistered().run(), vm); + po::notify(vm); + + if (vm.count("version")) + { + std::cout << "Sourcetrail Version " << m_version << std::endl; + m_quit = true; + return; + } + + if (vm.count("help")) + { + printHelp(); + m_quit = true; + } + + if (vm.count("project-file")) + { + m_projectFile = FilePath(vm["project-file"].as()); + processProjectfile(); + } + } + catch(boost::program_options::error& e) + { + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + std::cerr << m_options << std::endl; + } +} + +void CommandLineParser::parse() +{ + if (m_args.size() < 1) + { + return; + } + try + { + // parsing for all commands + for ( auto& command : m_commands) + { + if ( m_args[0] == command->name()) + { + m_args.erase(m_args.begin()); + ReturnStatus status = command->parse(m_args); + if (status == ReturnStatus::CMD_QUIT + || status == ReturnStatus::CMD_FAILURE) + { + m_quit = true; + } + } + } + } + catch(boost::program_options::error& e) + { + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + std::cerr << m_options << std::endl; + } + +} + +License* CommandLineParser::getLicensePtr() +{ + return &m_license; +} + +void CommandLineParser::printHelp() const +{ + std::cout << "Usage:\n sourcetrail [command] [option...] [positional arguments]\n\n"; + + // Commands + std::cout << "Commands:\n"; + for (auto& Command : m_commands) + { + std::cout << " " << Command->name() << "\n"; + } + std::cout << "\n * Each Commands has his own --help\n"; + + std::cout << m_options << std::endl; + + if (m_positional.max_total_count() > 0) + { + std::cout << "Positional Arguments: "; + for (unsigned int i = 0; i < m_positional.max_total_count(); i++) + { + std::cout << "\n " << i+1 << ": " << m_positional.name_for_position(i); + } + std::cout << std::endl; + } +} + + bool CommandLineParser::hasError() { return !m_errorString.empty(); @@ -144,34 +209,39 @@ bool CommandLineParser::exitApplication() bool CommandLineParser::startedWithLicense() { - return m_withLicense; + if (m_license.getUser().empty()) + { + return false; + } + return m_license.isValid(); } -void CommandLineParser::processProjectfile(const std::string& file) +void CommandLineParser::processProjectfile() { - FilePath projectfile = FilePath(file).absolute(); + m_projectFile = m_projectFile.absolute(); const std::string errorstring = - "Provided Projectfile is not valid:\n* Provided Projectfile('" + projectfile.fileName() + "') "; - if (!projectfile.exists()) + "Provided Projectfile is not valid:\n* Provided Projectfile('" + m_projectFile.fileName() + "') "; + if (!m_projectFile.exists()) { m_errorString = errorstring + " does not exist"; + m_projectFile = FilePath(); return; } - if (projectfile.extension() != ".srctrlprj" && projectfile.extension() != ".coatiproject") + if (m_projectFile.extension() != ".srctrlprj" && m_projectFile.extension() != ".coatiproject") { m_errorString = errorstring + " has a wrong fileending"; + m_projectFile = FilePath(); return; } std::shared_ptr configManager = ConfigManager::createEmpty(); - if (!configManager->load(TextAccess::createFromFile(projectfile))) + if (!configManager->load(TextAccess::createFromFile(m_projectFile))) { m_errorString = errorstring + " could not be loaded(invalid)"; + m_projectFile = FilePath(); return; } - - m_projectFile = projectfile; } License CommandLineParser::getLicense() @@ -179,6 +249,11 @@ License CommandLineParser::getLicense() return m_license; } +void CommandLineParser::force() +{ + m_force = true; +} + const FilePath& CommandLineParser::getProjectFilePath() const { return m_projectFile; @@ -188,3 +263,5 @@ bool CommandLineParser::getFullProjectRefresh() const { return m_force; } + +} // namespace cmd diff --git a/src/lib/utility/commandline/CommandLineParser.h b/src/lib/utility/commandline/CommandLineParser.h index 2f03b7b8..67da5031 100644 --- a/src/lib/utility/commandline/CommandLineParser.h +++ b/src/lib/utility/commandline/CommandLineParser.h @@ -1,39 +1,75 @@ #ifndef COMMANDLINEPARSER_H #define COMMANDLINEPARSER_H +#include +#include #include +#include + +#include "boost/program_options.hpp" + #include "License.h" #include "utility/file/FilePath.h" +namespace po = boost::program_options; + +namespace commandline { + +class Command; + class CommandLineParser { public: - CommandLineParser(int argc, char** argv, const std::string& version); + + CommandLineParser(const std::string& version); ~CommandLineParser(); + void setup(); + + void preparse(int argc, char** argv); + + /// args will be moved so dont use them after calling this function + void preparse(std::vector& args); + void parse(); + bool runWithoutGUI(); bool exitApplication(); bool startedWithLicense(); bool hasError(); + void force(); + std::string getError(); License getLicense(); + License* getLicensePtr(); const FilePath& getProjectFilePath() const; + void setProjectFile(const FilePath& filepath); bool getFullProjectRefresh() const; private: - void processProjectfile(const std::string& file); + void addCommand(std::unique_ptr command); + void processProjectfile(); void processLicense(const bool isLoaded); + void printHelp() const; FilePath m_projectFile; - bool m_force; - bool m_quit; - bool m_withLicense; - bool m_withoutGUI; + std::vector> m_commands; + + const std::string m_version; + bool m_force{false}; + bool m_quit{false}; + bool m_withoutGUI{false}; + + boost::program_options::options_description m_options; + boost::program_options::positional_options_description m_positional; std::string m_errorString; License m_license; + + std::vector m_args; }; +} // namespace cmd + #endif //COMMANDLINEPARSER_H diff --git a/src/lib/utility/commandline/CommandlineHelper.cpp b/src/lib/utility/commandline/CommandlineHelper.cpp new file mode 100644 index 00000000..9fb4fb03 --- /dev/null +++ b/src/lib/utility/commandline/CommandlineHelper.cpp @@ -0,0 +1,60 @@ +#include "utility/commandline/CommandlineHelper.h" + +#include +#include +#include + +#include "boost/program_options.hpp" + +namespace po = boost::program_options; + +namespace commandline { + +void parseConfigFile(po::variables_map& vm, + po::options_description& options) +{ + if (vm.count("config-file")) + { + const std::string configFile = vm["config-file"].as(); + std::ifstream ifs(configFile.c_str()); + + if (!ifs) + { + std::cout << "Could not open config file( " + << configFile << ")" + << std::endl; + } + else + { + po::store(po::parse_config_file(ifs, options), vm); + } + } +} + +void conflicting_options(const boost::program_options::variables_map& vm, + const char* opt1, const char* opt2) +{ + if (vm.count(opt1) && !vm[opt1].defaulted() + && vm.count(opt2) && !vm[opt2].defaulted()) + { + std::cout << "Options " << opt1 + << " and " << opt2 + << " are conflicted." << std::endl; + } +} + +std::vector extractPaths(const std::vector& vector) +{ + std::vector v; + for (std::string s : vector) + { + std::vector temp= utility::splitToVector(s, ','); + for (std::string path : temp) + { + v.push_back(FilePath(path)); + } + } + return std::move(v); +} + +} // namespace cmd diff --git a/src/lib/utility/commandline/CommandlineHelper.h b/src/lib/utility/commandline/CommandlineHelper.h new file mode 100644 index 00000000..679938ab --- /dev/null +++ b/src/lib/utility/commandline/CommandlineHelper.h @@ -0,0 +1,35 @@ +#ifndef COMMANDLINE_HELPER_H +#define COMMANDLINE_HELPER_H + +#include +#include + +#include "utility/utilityString.h" +#include "utility/utility.h" + +namespace boost { +namespace program_options { + class variables_map; + class options_description; +} +} + +namespace commandline +{ + enum class ReturnStatus { + CMD_OK, + CMD_QUIT, + CMD_FAILURE + }; + + void parseConfigFile(boost::program_options::variables_map& vm, + boost::program_options::options_description& options); + + void conflicting_options(const boost::program_options::variables_map& vm, + const char* opt1, const char* opt2); + + std::vector extractPaths(const std::vector& vector); + +} + +#endif // COMMANDLINE_HELPER_H diff --git a/src/lib/utility/commandline/commands/CommandlineCommand.cpp b/src/lib/utility/commandline/commands/CommandlineCommand.cpp new file mode 100644 index 00000000..f64d78f8 --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineCommand.cpp @@ -0,0 +1,36 @@ +#include "utility/commandline/commands/CommandlineCommand.h" + +#include + +namespace commandline +{ + +Command::Command(const std::string name, CommandLineParser* parser) + : m_name(name) + , m_parser(parser) +{ +} + +const std::string Command::name() +{ + return m_name; +} + +void Command::printHelp() +{ + std::cout << "Usage:\n sourcetrail " + << m_name << " [option...]\n\n"; + std::cout << m_options << std::endl; + if (m_positional.max_total_count() > 0) + { + std::cout << "Positional Arguments: "; + for (unsigned int i = 0; i < m_positional.max_total_count(); i++) + { + std::cout << "\n " << i+1 << ": " << m_positional.name_for_position(i); + } + std::cout << std::endl; + } +} + + +} // namespace cmd diff --git a/src/lib/utility/commandline/commands/CommandlineCommand.h b/src/lib/utility/commandline/commands/CommandlineCommand.h new file mode 100644 index 00000000..3bff9b78 --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineCommand.h @@ -0,0 +1,72 @@ +#ifndef COMMANDLINE_Command_H +#define COMMANDLINE_Command_H + +#include +#include +#include "boost/program_options.hpp" + +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsC.h" +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h" +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsJava.h" + +namespace po = boost::program_options; + +namespace commandline { +enum class ReturnStatus; +class CommandLineParser; + + +class Command { +public: + Command(const std::string name, CommandLineParser* parser = nullptr); + + const std::string name(); + + virtual void setup() = 0; + virtual ReturnStatus parse(std::vector& args) = 0; + virtual void printHelp(); + +protected: + const std::string m_name; + po::options_description m_options; + po::positional_options_description m_positional; + CommandLineParser* m_parser; +}; + +} +//class CommandlineCommandAdd : public CommandlineCommand +//{ +// std::vector> m_sourceGroupTypes; + +// CommandlineSourceGroupOptionsJava javaSourceGroup; + +// virtual void setup() +// { +// // ADD different sourcegroups here +// m_sourceGroupTypes.push_back(std::make_shared()); + + +// for (std::shared_ptr group : m_sourceGroupTypes) +// { +// group->setup(); +// } +// } + +// virtual void parse(int argc, char** argv) +// { +// for (std::shared_ptr group : m_sourceGroupTypes) +// { +// // 0 .. sourcetrail +// // 1 .. add +// // 2 .. sourcegrouptype +// if (argv[2] == group->name()) +// { +// group->parse(argc, argv); +// } +// } +// } +//}; + + + +#endif // !COMMANDLINE_COMMAND_H diff --git a/src/lib/utility/commandline/commands/CommandlineCommandConfig.cpp b/src/lib/utility/commandline/commands/CommandlineCommandConfig.cpp new file mode 100644 index 00000000..b4f23055 --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineCommandConfig.cpp @@ -0,0 +1,257 @@ +#include "utility/commandline/commands/CommandlineCommandConfig.h" + +#include +#include + + +#include "boost/program_options.hpp" + +#include "utility/UserPaths.h" +#include "utility/commandline/CommandlineHelper.h" +#include "utility/commandline/CommandLineParser.h" +#include "utility/file/FilePath.h" +#include "settings/ApplicationSettings.h" +#include "PublicKey.h" +#include "utility/AppPath.h" + +namespace po = boost::program_options; + +namespace commandline { + +// helper functions +typedef void(ApplicationSettings::*intFunc)(int); +void parseAndSetValue( + intFunc f, + const char* opt, + ApplicationSettings* settings, + po::variables_map& vm) +{ + if (vm.count(opt)) + { + (settings->*f)(vm[opt].as()); + } +} + +typedef void(ApplicationSettings::*boolFunc)(bool); +void parseAndSetValue( + boolFunc f, + const char* opt, + ApplicationSettings* settings, + po::variables_map& vm) +{ + if (vm.count(opt)) + { + (settings->*f)(vm[opt].as()); + } +} + +typedef void(ApplicationSettings::*filePathFunc)(const FilePath&); +void parseAndSetValue( + filePathFunc f, + const char* opt, + ApplicationSettings* settings, + po::variables_map& vm) +{ + if (vm.count(opt)) + { + FilePath path(vm[opt].as()); + if (!path.exists()) + { + std::cout << "\nWARNING: " << path.str() + << " does not exist." << std::endl; + } + (settings->*f)(path); + } +} + +typedef bool(ApplicationSettings::*vectorFunc)(const std::vector&); +void parseAndSetValue( + vectorFunc f, + const char* opt, + ApplicationSettings* settings, + po::variables_map& vm) +{ + if (vm.count(opt)) + { + std::vector v = extractPaths(vm[opt].as>()); + (settings->*f)(v); + } +} + +CommandConfig::CommandConfig(CommandLineParser* parser) + : Command("config", parser) +{ +} + +void CommandConfig::setup() +{ + po::options_description options("Config Options"); + options.add_options() + ("help,h", "Print this help message") + ("indexerthreads,t", po::value(), "Set the number of threads used for indexing") + ("use-processes,p", po::value(), "Enable C/C++ Indexer threads to run in different processes. ") + ("logging-enabled,l", po::value(), "Enable file/console logging ") + ("verbose-indexer-logging-enabled,L", po::value(), + "Enable additional log of abstract syntax tree during the indexing. WARNINIG Slows down the indexing process") + ("jvm-path,j", po::value(), "Path to the location of the jvm library") + ("jvm-max-memory,M", po::value(), + "Set the maximum amount of memory for the JVM indexer(-1 for using the JVM default settings)") + ("maven-path,m", po::value(), "Path to the maven binary") + ("jre-system-library-paths,J", po::value>(), + "paths to the jars of the JRE system library. " + "These jars can be found inside your JRE install directory(once per path or comma separated)") + ("license-file,z", po::value(), "Enter license via Licensefile") + ("license-string,Z", po::value(), "Enter licenes via commandline") + ("global-header-search-paths,g", po::value>(), + "Global include paths(once per path or comma separated)") + ("global-framework-search-paths,F", po::value>(), + "Global include paths(once per path or comma separated)") + ("show,s", "displays all settings") + ; + + m_options.add(options); +} + +void printVector(std::string title, std::vector vec) +{ + std::cout << "\n " << title << ":"; + if (vec.empty()) + { + std::cout << "\n -\n"; + } + for (const FilePath& item : vec) + { + std::cout << "\n " << item.str(); + } +} + +void CommandConfig::printSettings() +{ + ApplicationSettings* settings = ApplicationSettings::getInstance().get(); + settings->load(UserPaths::getAppSettingsPath()); + + if (settings == nullptr) + { + LOG_ERROR("Could not load application settings"); + return; + } + + std::cout << "Sourcetrail Settings:\n" + << "\n indexerthread count: " << settings->getIndexerThreadCount() + << "\n use-processes: " << settings->getMultiProcessIndexingEnabled() + << "\n logging-enabled: " << settings->getLoggingEnabled() + << "\n verbose-indexer-logging-enabled: " << settings->getVerboseIndexerLoggingEnabled() + << "\n jvm-path: " << settings->getJavaPath() + << "\n jvm-max-memory: " << settings->getJavaMaximumMemory() + << "\n maven-path: " << settings->getMavenPath().str(); + printVector("global-header-search-paths", std::move(settings->getHeaderSearchPaths())); + printVector("global-framework-search-paths", std::move(settings->getFrameworkSearchPaths())); + printVector("jre-system-library-paths", std::move(settings->getJreSystemLibraryPaths())); + License license; + license.loadFromEncodedString(settings->getLicenseString(), AppPath::getAppPath()); + std::cout << "\nValid license: " << license.isValid() << std::endl; +} + + +ReturnStatus CommandConfig::parse(std::vector& args) +{ + po::variables_map vm; + try + { + po::store(po::command_line_parser(args).options(m_options).run(), vm); + po::notify(vm); + + parseConfigFile(vm, m_options); + } + catch(po::error& e) + { + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + std::cerr << m_options << std::endl; + return ReturnStatus::CMD_FAILURE; + } + + // when "sourcetrail config" without any options is started, + // show help since configure nothing wont help + if (vm.count("help") || args.size() == 0 || args[0] == "help") + { + printHelp(); + return ReturnStatus::CMD_QUIT; + } + + if (args[0] == "show" || vm.count("show")) + { + printSettings(); + return ReturnStatus::CMD_QUIT; + } + + ApplicationSettings* settings = ApplicationSettings::getInstance().get(); + settings->load(UserPaths::getAppSettingsPath()); + + parseAndSetValue(&ApplicationSettings::setMultiProcessIndexingEnabled, "use-processes", settings, vm); + parseAndSetValue(&ApplicationSettings::setLoggingEnabled, "logging-enabled", settings, vm); + parseAndSetValue( + &ApplicationSettings::setVerboseIndexerLoggingEnabled, + "verbose-indexer-logging-enabled", + settings, + vm + ); + + parseAndSetValue(&ApplicationSettings::setIndexerThreadCount, "indexerthreads", settings, vm); + parseAndSetValue(&ApplicationSettings::setJavaMaximumMemory, "jvm-max-memory", settings, vm); + + parseAndSetValue(&ApplicationSettings::setMavenPath, "maven-path", settings, vm); + parseAndSetValue(&ApplicationSettings::setJavaPath, "jvm-path", settings, vm); + + parseAndSetValue(&ApplicationSettings::setJreSystemLibraryPaths, "jre-system-library-paths", settings, vm); + parseAndSetValue(&ApplicationSettings::setHeaderSearchPaths, "global-header-search-paths", settings, vm); + parseAndSetValue(&ApplicationSettings::setFrameworkSearchPaths, "global-framework-search-paths", settings, vm); + + // license + if (vm.count("license-string") || vm.count("license-file") ) + { + bool licenseLoaded = false; + if (vm.count("license-string")) + { + std::string licensetext = utility::replace(vm["license-string"].as(), "\\n", "\n"); + licenseLoaded = m_parser->getLicensePtr()->loadFromString(licensetext); + } + + if (vm.count("license-file")) + { + const std::string licensefile = vm["license-file"].as(); + if (FilePath(licensefile).exists()) + { + std::cout << "Load license from file" << std::endl; + licenseLoaded = m_parser->getLicensePtr()->loadFromFile(licensefile); + } + else + { + std::cout << licensefile << " not found" << std::endl; + } + } + + if (licenseLoaded) + { + if (!m_parser->getLicensePtr()->isValid()) + { + std::cout << "License is not valid" << std::endl; + return ReturnStatus::CMD_FAILURE; + } + else + { + std::cout << "License is valid" << std::endl; + } + } + else + { + std::cout << "Could not load License" << std::endl; + return ReturnStatus::CMD_FAILURE; + } + } + + settings->save(UserPaths::getAppSettingsPath()); + + return ReturnStatus::CMD_QUIT; +} + +} // namespace cmd diff --git a/src/lib/utility/commandline/commands/CommandlineCommandConfig.h b/src/lib/utility/commandline/commands/CommandlineCommandConfig.h new file mode 100644 index 00000000..f0d721eb --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineCommandConfig.h @@ -0,0 +1,31 @@ +#ifndef COMMANDLINE_COMMAND_CONFIG_H +#define COMMANDLINE_COMMAND_CONFIG_H + +#include +#include +#include "utility/commandline/commands/CommandlineCommand.h" + +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsC.h" +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h" +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsJava.h" + +class CommandLineParser; + +namespace commandline +{ +enum class ReturnStatus; + +class CommandConfig : public Command { +public: + CommandConfig(CommandLineParser* parser); + + virtual void setup(); + virtual ReturnStatus parse(std::vector& args); +private: + void printSettings(); + +}; + +} // namespace cmd + +#endif // !COMMANDLINE_COMMAND_H diff --git a/src/lib/utility/commandline/commands/CommandlineCommandIndex.cpp b/src/lib/utility/commandline/commands/CommandlineCommandIndex.cpp new file mode 100644 index 00000000..3ca9df61 --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineCommandIndex.cpp @@ -0,0 +1,63 @@ +#include "utility/commandline/commands/CommandlineCommandIndex.h" + +#include "utility/commandline/CommandlineHelper.h" +#include "utility/commandline/CommandLineParser.h" + +namespace commandline +{ + +CommandIndex::CommandIndex(CommandLineParser* parser) + : Command("index", parser) +{ +} + +void CommandIndex::setup() +{ + po::options_description options("Config Options"); + options.add_options() + ("help,h", "Print this help message") + ("full", "Paths for Sourcefiles") + ("project-file", po::value(), "Project file to index") + ; + + m_options.add(options); + m_positional.add("project-file", 1); +} + +ReturnStatus CommandIndex::parse(std::vector& args) +{ + po::variables_map vm; + try + { + po::store(po::command_line_parser(args).options(m_options).positional(m_positional).run(), vm); + po::notify(vm); + + parseConfigFile(vm, m_options); + } + catch(po::error& e) + { + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + std::cerr << m_options << std::endl; + return ReturnStatus::CMD_FAILURE; + } + + if (vm.count("help") || args.size() == 0 || args[0] == "help") + { + printHelp(); + return ReturnStatus::CMD_QUIT; + } + + if (vm.count("full")) + { + m_parser->force(); + } + + if (vm.count("project-file")) + { + m_parser->setProjectFile(FilePath(vm["project-file"].as())); + } + + return ReturnStatus::CMD_OK; +} + +} diff --git a/src/lib/utility/commandline/commands/CommandlineCommandIndex.h b/src/lib/utility/commandline/commands/CommandlineCommandIndex.h new file mode 100644 index 00000000..f6461acd --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineCommandIndex.h @@ -0,0 +1,28 @@ +#ifndef COMMANDLINE_COMMAND_INDEX_H +#define COMMANDLINE_COMMAND_INDEX_H + +#include +#include "boost/program_options.hpp" + +#include "utility/commandline/commands/CommandlineCommand.h" + +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsC.h" +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h" +//#include "utility/commandline/commands/CommandlineSourceGroupOptionsJava.h" +namespace po = boost::program_options; + +namespace commandline { + +enum class ReturnStatus; + +class CommandIndex : public Command { +public: + CommandIndex(CommandLineParser* parser); + + virtual void setup(); + virtual ReturnStatus parse(std::vector& args); +}; + +} // namespace cmd + +#endif // !COMMANDLINE_COMMAND_H diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.cpp b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.cpp new file mode 100644 index 00000000..c02722fe --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.cpp @@ -0,0 +1,6 @@ +#include "commandlineSourceGroupOptions.h" + +CommandlineSourceGroupOptions::CommandlineSourceGroupOptions() +{ + +} diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.h b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.h new file mode 100644 index 00000000..0bb14bda --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptions.h @@ -0,0 +1,19 @@ +#ifndef COMMANDLINE_SOURCEGROUP_OPTIONS_H +#define COMMANDLINE_SOURCEGROUP_OPTIONS_H + +#include + +#include "boost/program_options.hpp" + +class CommandlineSourceGroupOptions +{ +public: + virtual const std::string name() const = 0; + virtual void setup() = 0; + virtual void parse(int argc, char** argv) = 0; + +protected: + boost::program_options::options_description m_options; +}; + +#endif // COMMANDLINE_SOURCEGROUP_OPTIONS_H diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.cpp b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.cpp new file mode 100644 index 00000000..184bd81f --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.cpp @@ -0,0 +1,6 @@ +#include "CommandlineSourceGroupOptionsC.h" + +CommandlineSourceGroupOptionsC::CommandlineSourceGroupOptionsC() +{ + +} diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.h b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.h new file mode 100644 index 00000000..3633557a --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsC.h @@ -0,0 +1,12 @@ +#ifndef COMMANDLINE_SOURCEGROUP_OPTIONS_C_H +#define COMMANDLINE_SOURCEGROUP_OPTIONS_C_H + +#include "utility/commandline/modes/CommandlineSourceGroupOptions.h" + +class CommandlineSourceGroupOptionsC : public CommandlineSourceGroupOptions +{ +public: + CommandlineSourceGroupOptionsC(); +}; + +#endif // COMMANDLINE_SOURCEGROUP_OPTIONS_C_H diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.cpp b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.cpp new file mode 100644 index 00000000..a3855e4c --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.cpp @@ -0,0 +1,6 @@ +#include "CommandlineSourceGroupOptionsCxx.h" + +CommandlineSourceGroupOptionsCxx::CommandlineSourceGroupOptionsCxx() +{ + +} diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h new file mode 100644 index 00000000..7211c52e --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsCxx.h @@ -0,0 +1,12 @@ +#ifndef COMMANDLINE_SOURCEGROUP_OPTIONS_CXX_H +#define COMMANDLINE_SOURCEGROUP_OPTIONS_CXX_H + +#include "utility/commandline/modes/CommandlineSourceGroupOptions.h" + +class CommandlineSourceGroupOptionsCxx : public CommandlineSourceGroupOptions +{ +public: + CommandlineSourceGroupOptionsCxx(); +}; + +#endif // COMMANDLINE_SOURCEGROUP_OPTIONS_CXX_H diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.cpp b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.cpp new file mode 100644 index 00000000..0692adc4 --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.cpp @@ -0,0 +1,42 @@ +#include "CommandlineSourceGroupOptionsJava.h" + +#include + +namespace po = boost::program_options; + +const std::string CommandlineSourceGroupOptionsJava::name() const +{ + return "java"; +} + +void CommandlineSourceGroupOptionsJava::setup() +{ + m_options.add_options() + ("help,h", "Print this help message") + ("mavenpath,m", po::value(), "path to the maven executable") + ("jvmpath,j", po::value(), "path the jvm root") + ("excludePaths,e", po::value>(), "files or directories that will be excludes indexing") + ("source-extensions", po::value(), "extension of Sourcefiles") + ("java-standard", po::value(), "Java Standard") + ("classpath", po::value>(), "Java Class Paths") + ; +} + +void CommandlineSourceGroupOptionsJava::parse(int argc, char** argv) +{ + po::variables_map vm; + po::store(po::command_line_parser(argc, argv).options(m_options).run(), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << m_options << std::endl; + } + + if (vm.count("config-file")) + { + + } + + +} diff --git a/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.h b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.h new file mode 100644 index 00000000..efce662f --- /dev/null +++ b/src/lib/utility/commandline/commands/CommandlineSourceGroupOptionsJava.h @@ -0,0 +1,17 @@ +#ifndef COMMANDLINE_SOURCEGROUP_OPTIONS_JAVA_H +#define COMMANDLINE_SOURCEGROUP_OPTIONS_JAVA_H + +#include "utility/commandline/modes/CommandlineSourceGroupOptions.h" + + +class CommandlineSourceGroupOptionsJava : public CommandlineSourceGroupOptions +{ + virtual const std::string name() const; + virtual void setup() override; + virtual void parse(int argc, char** argv) override; + +private: + +}; + +#endif // COMMANDLINE_SOURCEGROUP_OPTIONS_JAVA_H diff --git a/src/lib_cxx/data/parser/cxx/ASTAction.h b/src/lib_cxx/data/parser/cxx/ASTAction.h index a2ba831f..64e4fb27 100644 --- a/src/lib_cxx/data/parser/cxx/ASTAction.h +++ b/src/lib_cxx/data/parser/cxx/ASTAction.h @@ -34,6 +34,7 @@ public: protected: virtual std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile) { +// return std::make_unique(&compiler.getASTContext(), &compiler.getPreprocessor(), m_client, m_fileRegister, m_canonicalFilePathCache); return std::unique_ptr( new ASTConsumer(&compiler.getASTContext(), &compiler.getPreprocessor(), m_client, m_fileRegister, m_canonicalFilePathCache)); } diff --git a/src/lib_cxx/utility/CompilationDatabase.cpp b/src/lib_cxx/utility/CompilationDatabase.cpp index 06f2de9b..6cb31eea 100644 --- a/src/lib_cxx/utility/CompilationDatabase.cpp +++ b/src/lib_cxx/utility/CompilationDatabase.cpp @@ -3,6 +3,7 @@ #include #include "clang/Tooling/JSONCompilationDatabase.h" +#include "clang/Tooling/CompilationDatabase.h" #include "utility/file/FilePath.h" #include "utility/utility.h" diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt index 89d1415d..a17ea810 100644 --- a/src/lib_gui/CMakeLists.txt +++ b/src/lib_gui/CMakeLists.txt @@ -99,6 +99,11 @@ add_files( qt/utility/utilityQt.cpp qt/utility/utilityQt.h +# qt/utility/qctrlsignals/qctrlsignalhandler.cpp +# qt/utility/qctrlsignals/qctrlsignalhandler.h +# qt/utility/qctrlsignals/qctrlsignalhandler_p.h +# qt/utility/qctrlsignals/QCtrlSignals + qt/view/graphElements/nodeComponents/QtGraphNodeComponent.cpp qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp @@ -270,8 +275,31 @@ add_files( utility/path_detector/PathDetector.cpp utility/path_detector/PathDetector.h +# utility/signal_handler/SignalHandler.cpp +# utility/signal_handler/SignalHandler.h + +# utility/QtUnixSignalEmitter.cpp +# utility/QtUnixSignalEmitter.h + +# utility/SignalWatcher.cpp +# utility/SignalWatcher.h + utility/utilityApp.cpp utility/utilityApp.h utility/utilityPathDetection.cpp utility/utilityPathDetection.h ) + +#if(WIN32) +#add_files( +# LIB_GUI_FILES +# qt/utility/qctrlsignals/qctrlsignalhandler_win.cpp +# qt/utility/qctrlsignals/qctrlsignalhandler_win.h +#) +#else() +#add_files( +# LIB_GUI_FILES +# qt/utility/qctrlsignals/qctrlsignalhandler_unix.cpp +# qt/utility/qctrlsignals/qctrlsignalhandler_unix.h +#) +#endif() diff --git a/src/lib_gui/qt/QtApplication.cpp b/src/lib_gui/qt/QtApplication.cpp index ad60c4dd..5efbb697 100644 --- a/src/lib_gui/qt/QtApplication.cpp +++ b/src/lib_gui/qt/QtApplication.cpp @@ -8,6 +8,7 @@ #include "utility/logging/LogManager.h" #include "component/controller/LogController.h" +#include "utility/utilityApp.h" QtApplication::QtApplication(int& argc, char** argv) : QApplication(argc, argv) diff --git a/src/lib_gui/qt/QtApplication.h b/src/lib_gui/qt/QtApplication.h index 30e5d714..5579971a 100644 --- a/src/lib_gui/qt/QtApplication.h +++ b/src/lib_gui/qt/QtApplication.h @@ -7,7 +7,6 @@ class QtApplication : public QApplication { Q_OBJECT - public: QtApplication(int& argc, char** argv); diff --git a/src/lib_gui/qt/QtCoreApplication.cpp b/src/lib_gui/qt/QtCoreApplication.cpp index 4696f607..ad13ba07 100644 --- a/src/lib_gui/qt/QtCoreApplication.cpp +++ b/src/lib_gui/qt/QtCoreApplication.cpp @@ -7,39 +7,34 @@ #include "utility/logging/logging.h" #include "utility/AppPath.h" #include "utility/UserPaths.h" +#include "utility/utilityApp.h" #include "License.h" QtCoreApplication::QtCoreApplication(int argc, char **argv ) : QCoreApplication(argc, argv) { + + } QtCoreApplication::~QtCoreApplication() { } -void QtCoreApplication::handleMessage(MessageFinishedParsing* message) +void QtCoreApplication::handleMessage(MessageQuitApplication* message) { - std::cout << "Finished parsing" << std::endl; - LOG_INFO("Finished parsing"); - this->quit(); + emit quit(); +} + +void QtCoreApplication::handleMessage(MessageStatus* message) +{ +// if (m.substr(0,5) == "Index") + { + std::cout << message->status << std::endl; + } } bool QtCoreApplication::saveLicense(License license) { - if (license.isValid()) - { - ApplicationSettings* appSettings = ApplicationSettings::getInstance().get(); - std::string appLocation = AppPath::getAppPath(); - appSettings->setLicenseString(license.getLicenseEncodedString(appLocation)); - FilePath p(appLocation); - appSettings->setLicenseCheck(license.hashLocation(p.absolute().str())); - appSettings->save(UserPaths::getAppSettingsPath()); - return true; - } - else - { - LOG_ERROR( "The entered license key is invalid."); - return false; - } + return utility::saveLicense(&license); } diff --git a/src/lib_gui/qt/QtCoreApplication.h b/src/lib_gui/qt/QtCoreApplication.h index 5e256d96..f146eea9 100644 --- a/src/lib_gui/qt/QtCoreApplication.h +++ b/src/lib_gui/qt/QtCoreApplication.h @@ -3,14 +3,18 @@ #include #include "utility/messaging/MessageListener.h" -#include "utility/messaging/type/MessageFinishedParsing.h" +#include "utility/messaging/type/MessageQuitApplication.h" +#include "utility/messaging/type/MessageStatus.h" class License; +class UnixSignalWatcher; class QtCoreApplication : public QCoreApplication - , public MessageListener + , public MessageListener + , public MessageListener { + Q_OBJECT public: QtCoreApplication(int argc, char **argv); virtual ~QtCoreApplication(); @@ -18,7 +22,8 @@ public: signals: void quitSignal(); private: - virtual void handleMessage(MessageFinishedParsing* message); + virtual void handleMessage(MessageQuitApplication* message); + virtual void handleMessage(MessageStatus* message); }; diff --git a/src/lib_gui/qt/view/QtDialogView.cpp b/src/lib_gui/qt/view/QtDialogView.cpp index 7fe22f3b..1f5585af 100644 --- a/src/lib_gui/qt/view/QtDialogView.cpp +++ b/src/lib_gui/qt/view/QtDialogView.cpp @@ -153,15 +153,6 @@ DialogView::IndexingOptions QtDialogView::startIndexingDialog( void QtDialogView::updateIndexingDialog( size_t startedFileCount, size_t finishedFileCount, size_t totalFileCount, std::string sourcePath) { - if (sourcePath.size()) - { - std::stringstream ss; - ss << "Indexing file: ["; - ss << startedFileCount << "/"; - ss << totalFileCount << "] "; - ss << sourcePath; - MessageStatus(ss.str(), false, true).dispatch(); - } m_onQtThread( [=]() diff --git a/src/lib_gui/qt/window/QtStartScreen.cpp b/src/lib_gui/qt/window/QtStartScreen.cpp index 30e37caa..547506e7 100644 --- a/src/lib_gui/qt/window/QtStartScreen.cpp +++ b/src/lib_gui/qt/window/QtStartScreen.cpp @@ -145,7 +145,7 @@ void QtStartScreen::setupStartScreen() { License license; license.loadFromEncodedString(ApplicationSettings::getInstance()->getLicenseString(), AppPath::getAppPath()); - license.loadPublicKeyFromString(PUBLIC_KEY); +// license.loadPublicKeyFromString(PUBLIC_KEY); bool licenseValid = license.isValid(); setStyleSheet(utility::getStyleSheet(ResourcePaths::getGuiPath().concat(FilePath("startscreen/startscreen.css"))).c_str()); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp index 84bdca85..2c1d76ea 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp @@ -356,7 +356,7 @@ void QtProjectWizzardContentPreferences::save() if (m_javaPath) { - appSettings->setJavaPath(m_javaPath->getText().toStdString()); + appSettings->setJavaPath(FilePath(m_javaPath->getText().toStdString())); } appSettings->setJreSystemLibraryPaths(m_jreSystemLibraryPaths->getList()); diff --git a/src/lib_gui/utility/utilityApp.cpp b/src/lib_gui/utility/utilityApp.cpp index 3818cfb2..14152ee3 100644 --- a/src/lib_gui/utility/utilityApp.cpp +++ b/src/lib_gui/utility/utilityApp.cpp @@ -5,6 +5,11 @@ #include #include +#include "License.h" +#include "settings/ApplicationSettings.h" +#include "utility/logging/logging.h" +#include "utility/AppPath.h" +#include "utility/UserPaths.h" #include "utility/utilityString.h" namespace utility @@ -98,3 +103,33 @@ int utility::getIdealThreadCount() { return QThread::idealThreadCount(); } + +bool utility::saveLicense(License* license) +{ + if (license == nullptr) + { + return false; + } + if (license->isValid()) + { + ApplicationSettings* appSettings = ApplicationSettings::getInstance().get(); + if (appSettings == NULL) + { + LOG_ERROR_STREAM(<< "Unable to retrieve app settings"); + return false; + } + + std::string appLocation = AppPath::getAppPath(); + appSettings->setLicenseString(license->getLicenseEncodedString(appLocation)); + FilePath p(appLocation); + appSettings->setLicenseCheck(license->hashLocation(p.absolute().str())); + appSettings->save(UserPaths::getAppSettingsPath()); + + return true; + } + else + { + LOG_ERROR( "The entered license key is invalid."); + return false; + } +} diff --git a/src/lib_gui/utility/utilityApp.h b/src/lib_gui/utility/utilityApp.h index b561bfda..80a33ce3 100644 --- a/src/lib_gui/utility/utilityApp.h +++ b/src/lib_gui/utility/utilityApp.h @@ -7,6 +7,8 @@ #include "utility/OsType.h" +class License; + namespace utility { std::string executeProcess(const std::string& command, const std::string& workingDirectory = "", int timeout = 30000); @@ -17,6 +19,7 @@ namespace utility int getIdealThreadCount(); OsType getOsType(); + bool saveLicense(License* license); } #endif // UTILITY_APP_H diff --git a/src/lib_license/License.cpp b/src/lib_license/License.cpp index 48c97be2..4fe641bd 100644 --- a/src/lib_license/License.cpp +++ b/src/lib_license/License.cpp @@ -22,6 +22,7 @@ #include "botan/pbkdf.h" #include "utility/Version.h" +#include "PublicKey.h" namespace { @@ -40,6 +41,7 @@ License::License() , m_seats(0) , m_expire("") { + loadPublicKey(); } License::~License() @@ -436,6 +438,27 @@ bool License::loadPublicKeyFromFile(const std::string& filename) return false; } +bool License::loadPublicKey() +{ + if (PUBLIC_KEY.empty()) + { + std::cout << "Public key is empty" << std::endl; + return false; + } + + Botan::DataSource_Memory in(PUBLIC_KEY); + Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(in)); + + if (!rsaPublicKey) + { + std::cout << "The loaded key is not a RSA key" << std::endl; + return false; + } + + m_publicKey = std::shared_ptr(rsaPublicKey); + return true; +} + bool License::loadPublicKeyFromString(const std::string& publicKey) { if (publicKey.empty()) diff --git a/src/lib_license/License.h b/src/lib_license/License.h index 8fdc9555..84640e43 100644 --- a/src/lib_license/License.h +++ b/src/lib_license/License.h @@ -86,10 +86,12 @@ public: bool loadFromFile(const std::string& filename); bool loadFromEncodedString(const std::string& encodedLicense, const std::string& applicationLocation); - bool loadPublicKeyFromFile(const std::string&); + bool loadPublicKey(); - bool loadPublicKeyFromString(const std::string&); - void setSignature(const std::string&); + bool loadPublicKeyFromFile(const std::string&); + bool loadPublicKeyFromString(const std::string&); + + void setSignature(const std::string&); bool isValid() const; bool isExpired() const; diff --git a/src/license_generator/Generator.cpp b/src/license_generator/Generator.cpp index 131f37d8..834aa377 100644 --- a/src/license_generator/Generator.cpp +++ b/src/license_generator/Generator.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "boost/filesystem.hpp" @@ -36,7 +37,7 @@ Generator::~Generator() void Generator::generateKeys() { - m_privateKey = std::unique_ptr(new Botan::RSA_PrivateKey(m_rng, 2048)); + m_privateKey = std::make_unique(m_rng, 2048); } std::string Generator::getPrivateKeyFilename() @@ -123,7 +124,7 @@ bool Generator::verifyLicense(const std::string& filename) { License license; license.loadFromFile(filename); - license.loadPublicKeyFromString(PUBLIC_KEY); +// license.loadPublicKeyFromString(PUBLIC_KEY); return license.isValid(); } @@ -203,7 +204,7 @@ bool Generator::loadPrivateKeyFromFile() return false; } - m_privateKey = std::unique_ptr(rsaKey); + m_privateKey = std::unique_ptr(rsaKey); return (m_privateKey != NULL); } @@ -226,7 +227,7 @@ bool Generator::loadPrivateKeyFromString(const std::string& key) return false; } - m_privateKey = std::unique_ptr(rsaKey); + m_privateKey = std::unique_ptr(rsaKey); return (m_privateKey != NULL); } @@ -243,7 +244,7 @@ void Generator::createLicense( const unsigned int seats ) { - m_license = std::unique_ptr(new License()); + m_license = std::make_unique(); m_license->createHeader(user, type, expiration, seats); diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index be2bad62..7878b373 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -9,6 +9,7 @@ add_files( TestSuiteFixture.h ConfigManagerTestSuite.h + CommandlineTestSuite.h CxxParserTestSuite.h CxxTypeNameTestSuite.h FileManagerTestSuite.h diff --git a/src/test/CommandlineTestSuite.h b/src/test/CommandlineTestSuite.h new file mode 100644 index 00000000..570c7a95 --- /dev/null +++ b/src/test/CommandlineTestSuite.h @@ -0,0 +1,139 @@ +#include "cxxtest/TestSuite.h" + +#include "utility/commandline/CommandLineParser.h" +#include "settings/ApplicationSettings.h" + +#include +#include +#include + +class CommandlineTestSuite: public CxxTest::TestSuite +{ + ApplicationSettings backup_settings; + +public: + + void tearDown() + { + } + + void setUp() + { + } + + void test_commandline_version() + { + std::vector args({"--version", "help"}); + + std::stringstream redStream; + auto oldBuf = std::cout.rdbuf( redStream.rdbuf() ); + + commandline::CommandLineParser parser("2016.1"); + parser.preparse(args); + parser.parse(); + + std::cout.rdbuf( oldBuf ); + + TS_ASSERT_EQUALS(redStream.str(), "Sourcetrail Version 2016.1\n"); + } + + void test_command_config_help() + { + + } + + void test_command_config_filepathVector() + { + std::vector args( + { + "config", + "-g", + "/usr", + "-g", + "/usr/share/include", + "-g", + "/opt/test/include" + }); + + commandline::CommandLineParser parser("2"); + parser.preparse(args); + parser.parse(); + + std::vector paths = ApplicationSettings::getInstance()->getHeaderSearchPaths(); + TS_ASSERT_EQUALS( paths[0].str(), "/usr") + TS_ASSERT_EQUALS( paths[1].str(), "/usr/share/include") + TS_ASSERT_EQUALS( paths[2].str(), "/opt/test/include") + } + + void test_command_config_string_filepath_option() + { + std::vector args( + { + "config", + "--maven-path", + "/opt/testpath/mvn" + }); + + commandline::CommandLineParser parser("2"); + parser.preparse(args); + parser.parse(); + + FilePath path = ApplicationSettings::getInstance()->getMavenPath(); + TS_ASSERT_EQUALS( path.str(), "/opt/testpath/mvn") + + } + + void test_command_config_filepathVector_comma_separated() + { + std::vector args( + { + "config", + "--global-header-search-paths", + "/usr,/usr/include,/include,/opt/include" + }); + + commandline::CommandLineParser parser("2"); + parser.preparse(args); + parser.parse(); + + std::vector paths = ApplicationSettings::getInstance()->getHeaderSearchPaths(); + TS_ASSERT_EQUALS( paths[0].str(), "/usr") + TS_ASSERT_EQUALS( paths[1].str(), "/usr/include") + TS_ASSERT_EQUALS( paths[2].str(), "/include") + TS_ASSERT_EQUALS( paths[3].str(), "/opt/include") + + } + + void test_command_config_bool_options() + { + std::vector args( + { + "config", + "--use-processes", + "false" + }); + + commandline::CommandLineParser parser("2"); + parser.preparse(args); + parser.parse(); + + bool processes = ApplicationSettings::getInstance()->getMultiProcessIndexingEnabled(); + TS_ASSERT_EQUALS( processes, 0); + + std::vector args1( + { + "config", + "--use-processes", + "true" + }); + + parser.preparse(args1); + parser.parse(); + + processes = ApplicationSettings::getInstance()->getMultiProcessIndexingEnabled(); + TS_ASSERT_EQUALS( processes, 1); + } + +private: + +}; diff --git a/src/test/GeneratorTestSuite.h b/src/test/GeneratorTestSuite.h index d228cb68..f5a70b7b 100644 --- a/src/test/GeneratorTestSuite.h +++ b/src/test/GeneratorTestSuite.h @@ -15,7 +15,10 @@ public: std::string privateKey = generator.getPrivateKeyPEMFileAsString(); std::string publicKey = generator.getPublicKeyPEMFileAsString(); - TS_ASSERT_EQUALS(privateKey.size(), 1886); + // normally the size is 1886 + // sometimes it could happen that the size is 1866 + // to prevent the test of failing both sizes are valid + TS_ASSERT(privateKey.size() == 1886 || privateKey.size() == 1866); TS_ASSERT_EQUALS(publicKey.size(), 451); } @@ -46,7 +49,7 @@ public: license.loadFromString(generator.encodeLicense("TestUser", "VolumeLicense", 20)); // license.create(generator.getPrivateKey(), "TestUser", "v2", "Volume License", 20); - license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); +// license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); TS_ASSERT_EQUALS(license.getSeats(), 20); } @@ -58,14 +61,14 @@ public: generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString()); License license; - license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); + license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); license.loadFromString(generator.encodeLicense("User", 10)); TS_ASSERT(license.isValid()); TS_ASSERT_EQUALS(license.getTimeLeft(), 10); // TS_ASSERT_EQUALS(license.getVersion(), "v2"); - license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); + license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); license.loadFromString(generator.encodeLicense("User", -10)); TS_ASSERT(!license.isValid()); diff --git a/src/test/JavaParserTestSuite.h b/src/test/JavaParserTestSuite.h index 9519e383..79628b95 100644 --- a/src/test/JavaParserTestSuite.h +++ b/src/test/JavaParserTestSuite.h @@ -21,7 +21,7 @@ public: std::vector javaPaths = utility::getJavaRuntimePathDetector()->getPaths(); if (!javaPaths.empty()) { - ApplicationSettings::getInstance()->setJavaPath(javaPaths[0].str()); + ApplicationSettings::getInstance()->setJavaPath(javaPaths[0]); } setupJavaEnvironmentFactory();