diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..0451da0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,67 @@ +# Generated from CLion C/C++ Code Style settings +BasedOnStyle: LLVM +AccessModifierOffset: -8 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: Consecutive +AlignOperands: Align +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +ColumnLimit: 0 +CompactNamespaces: false +ContinuationIndentWidth: 4 +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 8 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +QualifierAlignment: Left +PointerAlignment: Right +ReflowComments: false +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 0 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 8 +UseTab: ForContinuationAndIndentation diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..53466ac --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,31 @@ +Checks: >- + bugprone-*, + cppcoreguidelines-*, + google-*, + misc-*, + modernize-*, + performance-*, + readability-*, + -bugprone-lambda-function-name, + -bugprone-easily-swappable-parameters, + -bugprone-reserved-identifier, + -cppcoreguidelines-avoid-goto, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-vararg, + -google-readability-braces-around-statements, + -google-readability-function-size, + -misc-no-recursion, + -modernize-return-braced-init-list, + -modernize-use-nodiscard, + -modernize-use-trailing-return-type, + -performance-unnecessary-value-param, + -readability-identifier-length, + -readability-magic-numbers + +CheckOptions: + readability-function-cognitive-complexity.Threshold: 100 + readability-function-cognitive-complexity.IgnoreMacros: true + readability-identifier-naming.ClassCase: CamelCase diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..8f3813e --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..79b3c94 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..63ed359 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/sc3dev.iml b/.idea/sc3dev.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/sc3dev.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f866d03..de8d647 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,14 @@ set(CMAKE_VERBOSE_MAKEFILES ON) find_package(scsl REQUIRED) +include(FindPkgConfig) +pkg_check_modules(CURLPP REQUIRED curlpp) +if (CURLPP_FOUND) + message(STATUS "Found CURL version: ${CURLPP_VERSION_STRING}") + message(STATUS "Using CURL include dir(s): ${CURLPP_INCLUDE_DIRS}") + message(STATUS "Using CURL lib(s): ${CURLPP_LIBRARIES}") +endif () + include(CTest) enable_testing() @@ -34,11 +42,13 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") else () # nothing special for gcc at the moment endif () +add_compile_definitions(SCSL_DESKTOP_BUILD) set(HEADERS) set(SOURCES) include_directories(SYSTEM include) +include_directories(SYSTEM ${CURLPP_INCLUDE_DIRS}) ### THE REAL TARGETS ### diff --git a/cmake-package.sh b/cmake-package.sh new file mode 100644 index 0000000..91ccb87 --- /dev/null +++ b/cmake-package.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -eux + +BUILD_TYPE="${BUILD_TYPE:-RelWithDebInfo}" + +if [ "${USE_CLANG:-}" == "yes" ] +then + export CC=$(command -v clang) + export CXX=$(command -v clang++) +fi + +[[ -d build ]] && rm -rf build +mkdir -p build && cd build +cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} .. && make all package + +sc3dev-packager --owner ${OWNER:-sc} debian --comp ${COMPONENT:-dev} put *.deb +sc3dev-packager --owner ${OWNER:-sc} generic put *.sh *.tar.gz diff --git a/src/packager.cc b/src/packager.cc index 0c7df62..4bf2832 100644 --- a/src/packager.cc +++ b/src/packager.cc @@ -5,37 +5,164 @@ /// \brief Packaging tools for shimmering-clarity. /// +#include #include #include #include -#include +#include +#include -static struct { - scsl::Flags *flags; - std::string owner; - std::string distribution; - std::string component; - std::string password; - std::string username; - std::string version; -} config; +void +usage(std::ostream &outs, int exc) +{ + outs << "sc3dev-packager: manage packages on gitea\n"; + outs << "usage:\n"; + outs << "\tsc3dev-packager [--component component] [--owner owner] \n"; + outs << "\t\t[--distribution distribution] debian command packages ...\n"; + outs << "\tsc3dev-packager [--owner owner] generic command packages ...\n"; + outs << "\nCommands:\n"; + outs << "\t- delete: remove a package\n"; + outs << "\t- put: upload a package\n"; + + exit(exc); +} + + +std::string +getDefaultConfigFile() +{ + auto userEnv = getenv("USER"); + auto user = std::string(userEnv); + + if (user == "root") { + return std::filesystem::path("/etc/sc3dev/packager.conf"); + } + + if (user.empty()) { + return ""; + } + + userEnv = getenv("HOME"); + auto userHome = std::filesystem::path(userEnv); + + userHome /= std::filesystem::path(".config"); + userHome /= std::filesystem::path("sc3dev-packager.conf"); + return userHome; +} + +static bool +putDebian(std::vector args) +{ + std::cout << "[+] put Debian package\n"; + for (auto &arg: args) { + std::cout << "\t[*] " << arg << "\n"; + } + return false; +} + + +static bool +debianPackager(std::vector args) +{ + scsl::Commander commander; + commander.Register(scsl::Subcommand("put", 1, putDebian)); + + std::cout << "[+] Debian packager invoked\n"; + for (auto &arg: args) { + std::cout << "\t[*] " << arg << "\n"; + } + + auto command = args[0]; + args.erase(args.cbegin()); + return commander.Run(command, args) == scsl::Subcommand::Status::OK; +} int main(int argc, char *argv[]) { - config.flags = new scsl::Flags("sc3dev-packager", "package tooling for shimmering clarity"); - config.flags->Register("--component", "main", "Debian package component"); - config.flags->Register("--distribution", "ubuntu", "Debian package distribution"); - config.flags->Register("--owner", "sc", "package repository owner"); + int retc; + scsl::Flags *flags; + std::string configFile = getDefaultConfigFile(); + std::string owner; + std::string distribution; + std::string component; + std::string version; - auto status = config.flags->Parse(argc, argv); + flags = new scsl::Flags("sc3dev-packager", "package tooling for shimmering clarity"); + flags->Register("--config", configFile, "path to a configuration file"); + flags->Register("--component", "main", "Debian package component"); + flags->Register("--distribution", "ubuntu", "Debian package distribution"); + flags->Register("--owner", "sc", "package repository owner"); + flags->Register("--version", scsl::FlagType::String, "version to operate on (only matters for delete)"); + + auto status = flags->Parse(argc, argv); if (status != scsl::Flags::ParseStatus::OK) { std::cerr << "failed to parse flags: " - << scsl::Flags::ParseStatusToString(status) - << "\n"; + << scsl::Flags::ParseStatusToString(status) + << "\n"; exit(1); } + + scsl::Commander commander; + commander.Register(scsl::Subcommand("debian", 1, debianPackager)); + + flags->GetString("--config", configFile); + if (std::filesystem::exists(std::filesystem::path(configFile))) { + if (scsl::SimpleConfig::LoadGlobal(configFile) != 0) { + std::cerr << "[!] failed to read config file " << configFile << ".\n"; + exit(1); + } + } + + if (flags->GetString("--owner", owner)) { + scsl::SimpleConfig::PutGlobal("owner", owner); + } + + if (flags->GetString("--distribution", distribution)) { + scsl::SimpleConfig::PutGlobal("distribution", distribution); + } + + if (flags->GetString("--component", component)) { + scsl::SimpleConfig::PutGlobal("component", component); + } + + if (flags->GetString("--version", version)) { + scsl::SimpleConfig::PutGlobal("version", version); + } + + if (flags->NumArgs() < 1) { + std::cerr << "[!] not enough arguments provided.\n"; + exit(1); + } + + auto command = flags->Arg(0); + auto args = flags->Args(); + args.erase(args.begin()); + + auto result = commander.Run(command, args); + delete flags; + + switch (result) { + case scsl::Subcommand::Status::OK: + std::cout << "[+] OK\n"; + retc = 0; + break; + case scsl::Subcommand::Status::NotEnoughArgs: + usage(std::cerr, 1); + break; + case scsl::Subcommand::Status::Failed: + std::cerr << "[!] '" << command << "' failed\n"; + break; + case scsl::Subcommand::Status::CommandNotRegistered: + std::cerr << "[!] '" << command << "' not registered.\n"; + usage(std::cerr, 1); + break; + default: + abort(); + } + + return retc; }