From 3092965d49a351020c394f19c8302ecb84aaa169 Mon Sep 17 00:00:00 2001 From: Martchus Date: Wed, 6 Jan 2016 02:08:24 +0100 Subject: [PATCH] added cmake project --- CMakeLists.txt | 195 ++++++++++++++++++ alpm/config.cpp | 11 +- alpm/config.h | 1 + alpm/mingwbundle.cpp | 86 +++----- alpm/package.cpp | 15 ++ alpm/package.h | 1 + repoindex.pro | 17 +- .../settings}/repoindex.conf.js | 5 +- resources/systemd/repoindex.service | 12 ++ 9 files changed, 274 insertions(+), 69 deletions(-) create mode 100644 CMakeLists.txt rename {samples => resources/settings}/repoindex.conf.js (85%) create mode 100644 resources/systemd/repoindex.service diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a6a9ccb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,195 @@ +cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) + +# add project files +set(HEADER_FILES + alpm/manager.h + alpm/package.h + alpm/list.h + alpm/utilities.h + network/server.h + network/connection.h + alpm/group.h + alpm/config.h + alpm/resolvebuildorder.h + alpm/mingwbundle.h + network/userrepository.h + alpm/alpmpackage.h + alpm/aurpackage.h + alpm/alpmdatabase.h + alpm/repository.h + alpm/upgradelookup.h + alpm/suggestionslookup.h + alpm/packageinfolookup.h + alpm/packagelookup.h + alpm/packagefinder.h +) +set(SRC_FILES + main.cpp + alpm/manager.cpp + alpm/package.cpp + alpm/utilities.cpp + alpm/group.cpp + alpm/config.cpp + alpm/resolvebuildorder.cpp + alpm/mingwbundle.cpp + alpm/alpmpackage.cpp + alpm/aurpackage.cpp + alpm/alpmdatabase.cpp + alpm/repository.cpp + alpm/upgradelookup.cpp + alpm/suggestionslookup.cpp + alpm/packageinfolookup.cpp + alpm/packagelookup.cpp + alpm/packagefinder.cpp + network/server.cpp + network/connection.cpp + network/userrepository.cpp +) +set(WEB_FILES + web/3rdparty/bootstrap/css/bootstrap-theme.css + web/3rdparty/bootstrap/css/bootstrap-theme.css.map + web/3rdparty/bootstrap/css/bootstrap-theme.min.css + web/3rdparty/bootstrap/css/bootstrap.css + web/3rdparty/bootstrap/css/bootstrap.css.map + web/3rdparty/bootstrap/css/bootstrap.min.css + web/3rdparty/bootstrap/fonts/glyphicons-halflings-regular.eot + web/3rdparty/bootstrap/fonts/glyphicons-halflings-regular.svg + web/3rdparty/bootstrap/fonts/glyphicons-halflings-regular.ttf + web/3rdparty/bootstrap/fonts/glyphicons-halflings-regular.woff + web/3rdparty/bootstrap/fonts/glyphicons-halflings-regular.woff2 + web/3rdparty/bootstrap/js/bootstrap.js + web/3rdparty/bootstrap/js/bootstrap.min.js + web/3rdparty/bootstrap/js/npm.js + web/3rdparty/bootstrap_dropdowns_enhancement/css/dropdowns-enhancement.min.css + web/3rdparty/bootstrap_dropdowns_enhancement/js/dropdowns-enhancement.js + web/css/.core.css.swp + web/css/core.css + web/css/dashboard.css + web/index.html + web/js/client.js + web/js/entrymanagement.js + web/js/expandcollapse.js + web/js/groupmanagement.js + web/js/packagemanagement.js + web/js/pagemanagement.js + web/js/pagination.js + web/js/proto.js + web/js/repomanagement.js + web/js/utils.js +) + +# meta data +set(META_PROJECT_NAME repoindex) +set(META_APP_NAME "Repository browser") +set(META_APP_AUTHOR "Martchus") +set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}") +set(META_APP_DESCRIPTION "Arch Linux repository browser") +set(META_VERSION_MAJOR 0) +set(META_VERSION_MINOR 0) +set(META_VERSION_PATCH 1) + +# stringification of meta data +set(META_PROJECT_NAME_STR "\"${META_PROJECT_NAME}\"") +set(META_APP_NAME_STR "\"${META_APP_NAME}\"") +set(META_APP_AUTHOR_STR "\"${META_APP_AUTHOR}\"") +set(META_APP_URL_STR "\"${META_APP_URL}\"") +set(META_APP_DESCRIPTION_STR "\"${META_APP_DESCRIPTION}\"") +set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}) +set(META_APP_VERSION_STR "\"${META_APP_VERSION}\"") + +# define project +project(${META_PROJECT_NAME}) + +# add configuration header +configure_file( + "${PROJECT_SOURCE_DIR}/resources/config.h.in" + "${PROJECT_BINARY_DIR}/resources/config.h" +) +include_directories("${PROJECT_BINARY_DIR}") + +# add windows resource file +if(MINGW) + # create windows rc file from template + set(WINDOWS_EXT "exe") + configure_file( + "${PROJECT_SOURCE_DIR}/resources/windows.rc.in" + "${PROJECT_BINARY_DIR}/resources/windows.rc" + ) + # set windres as resource compiler + set(RES_FILES "${PROJECT_BINARY_DIR}/resources/windows.rc") + set(CMAKE_RC_COMPILER_INIT windres) + set(CMAKE_RC_COMPILE_OBJECT " -O coff -i -o ") + enable_language(RC) +endif(MINGW) + +# check required Qt 5 modules +find_package(Qt5Core REQUIRED) +find_package(Qt5Concurrent REQUIRED) +find_package(Qt5Network REQUIRED) +find_package(Qt5WebSockets REQUIRED) +find_package(KF5Archive REQUIRED) + +# enable moc +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# disable new ABI (can't catch ios_base::failure with new ABI) +add_definitions( + -D_GLIBCXX_USE_CXX11_ABI=0 + -DCMAKE_BUILD +) + +# executable and linking +add_executable(${META_PROJECT_NAME} ${HEADER_FILES} ${SRC_FILES} ${RES_FILES}) +target_link_libraries(${META_PROJECT_NAME} c++utilities alpm Qt5::Core Qt5::Concurrent Qt5::Network Qt5::WebSockets KF5::Archive) +set_target_properties(${META_PROJECT_NAME} PROPERTIES + CXX_STANDARD 11 +) + +# add install target +install(TARGETS ${META_PROJECT_NAME} + RUNTIME DESTINATION bin + COMPONENT binary +) +install(FILES resources/systemd/${META_PROJECT_NAME}.service + DESTINATION lib/systemd/system + COMPONENT service +) +install(FILES resources/settings/${META_PROJECT_NAME}.conf.js + DESTINATION share/${META_PROJECT_NAME}/skel + COMPONENT config +) +foreach(WEB_FILE ${WEB_FILES}) + get_filename_component(WEB_DIR ${WEB_FILE} DIRECTORY) + install( + FILES ${WEB_FILE} + DESTINATION share/${META_PROJECT_NAME}/${WEB_DIR} + COMPONENT web + ) +endforeach() +add_custom_target(install-binary + DEPENDS ${META_PROJECT_NAME} + COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=binary -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" +) +add_custom_target(install-service + DEPENDS ${META_PROJECT_NAME} + COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=service -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" +) +add_custom_target(install-config + DEPENDS ${META_PROJECT_NAME} + COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=config -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" +) +add_custom_target(install-web + DEPENDS ${META_PROJECT_NAME} + COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=web -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" +) +add_custom_target(install-mingw-w64 + DEPENDS install-binary +) +add_custom_target(install-binary-strip + DEPENDS ${META_PROJECT_NAME} + COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_DO_STRIP=1 -DCMAKE_INSTALL_COMPONENT=binary -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" +) +add_custom_target(install-mingw-w64-strip + DEPENDS install-binary-strip +) diff --git a/alpm/config.cpp b/alpm/config.cpp index 826f7ff..2c8a635 100644 --- a/alpm/config.cpp +++ b/alpm/config.cpp @@ -52,6 +52,7 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) : iconThemesArg("icon-packages", "i", "specifies the names of the icon packages to include"), defaultIconThemeArg("default-icon-theme", string(), "specifies the name of the default icon theme (should be included in --icon-packages)"), extraPackagesArg("extra-packages", string(), "specifies extra packages to be included"), + cacheDirArg("cache-dir", string(), "specifies the cache directory (default is /var/cache/repoindex)"), shSyntaxArg("sh-syntax", string(), "prints the output using shell syntax: export REPOINDEX_RESULTS=('res1' 'res2' 'res3') or export REPOINDEX_ERROR='some error message'"), repoArg("repo", string(), "specifies the repository") { @@ -126,7 +127,10 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) : upgradeLookupArg.setSecondaryArguments({&shSyntaxArg}); buildOrderArg.setSecondaryArguments({&aurArg, &addSourceOnlyDeps, &verboseArg, &shSyntaxArg}); mingwBundleArg.setSecondaryArguments({&targetDirArg, &targetNameArg, &targetFormatArg, &iconThemesArg, &defaultIconThemeArg, &extraPackagesArg}); - parser.setMainArguments({&buildOrderArg, &upgradeLookupArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &helpArg}); + cacheDirArg.setCombinable(true); + cacheDirArg.setRequiredValueCount(1); + cacheDirArg.setValueNames(pathValueName); + parser.setMainArguments({&buildOrderArg, &upgradeLookupArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &cacheDirArg, &helpArg}); } /*! @@ -141,7 +145,7 @@ Config::Config() : m_alpmRootDir(QStringLiteral("/")), m_alpmDbPath(QStringLiteral("/var/lib/pacman")), m_pacmanConfFile(QStringLiteral("/etc/pacman.conf")), - m_cacheDir(QStringLiteral(".")), + m_cacheDir(QStringLiteral("/var/cache/repoindex")), m_websocketServerListeningAddr(QHostAddress::LocalHost), m_websocketServerListeningPort(1234), m_serverInsecure(false), @@ -301,6 +305,9 @@ void Config::loadFromArgs(const ConfigArgs &args) } m_verbose = args.verboseArg.isPresent(); m_runServer = args.serverArg.isPresent(); + if(args.cacheDirArg.isPresent()) { + m_cacheDir = QString::fromLocal8Bit(args.cacheDirArg.values().front().data()); + } } /*! diff --git a/alpm/config.h b/alpm/config.h index 761237c..123b2d5 100644 --- a/alpm/config.h +++ b/alpm/config.h @@ -43,6 +43,7 @@ public: ApplicationUtilities::Argument iconThemesArg; ApplicationUtilities::Argument defaultIconThemeArg; ApplicationUtilities::Argument extraPackagesArg; + ApplicationUtilities::Argument cacheDirArg; ApplicationUtilities::Argument shSyntaxArg; ApplicationUtilities::Argument repoArg; }; diff --git a/alpm/mingwbundle.cpp b/alpm/mingwbundle.cpp index b6f948e..8619e89 100644 --- a/alpm/mingwbundle.cpp +++ b/alpm/mingwbundle.cpp @@ -100,8 +100,7 @@ enum class RelevantFileType GLib2Data, GLib2Schemas, Theme, - IconTheme, - ConfigFile + IconTheme }; enum class RelevantFileArch @@ -186,8 +185,8 @@ void getFiles(PkgFileInfo &pkgFileInfo) const auto *binEntry = rootDir->entry(QStringLiteral("bin")); if(binEntry && binEntry->isDirectory()) { const auto *binDir = static_cast(binEntry); - for(const auto &entryName : binDir->entries()) { - if(entryName.endsWith(QLatin1String(".exe")) || entryName.endsWith(QLatin1String(".dll"))) { + for(const QString &entryName : binDir->entries()) { + if(entryName.endsWith(QLatin1String(".exe")) || entryName.indexOf(QLatin1String(".dll")) > 0) { if(const auto *entry = binDir->entry(entryName)) { if(entry->isFile()) { pkgFileInfo.relevantFiles.emplace_back(static_cast(entry), binDir, RelevantFileType::Binary, root.first); @@ -254,10 +253,12 @@ void getFiles(PkgFileInfo &pkgFileInfo) addEntries(pkgFileInfo, RelevantFileType::Data, static_cast(dataEntry), QString(), QString(), root.first); } - // shared directory: translations, themes, icons, schemas + // share directory: translations, themes, icons, schemas const auto *shareEntry = rootDir->entry(QStringLiteral("share")); if(shareEntry && shareEntry->isDirectory()) { const auto *shareDir = static_cast(shareEntry); + + // Qt translations const auto *qtEntry = shareDir->entry(QStringLiteral("qt")); if(qtEntry && qtEntry->isDirectory()) { const auto *qtDir = static_cast(qtEntry); @@ -276,6 +277,7 @@ void getFiles(PkgFileInfo &pkgFileInfo) } } + // GTK themes const auto *themesEntry = shareDir->entry(QStringLiteral("themes")); if(themesEntry && themesEntry->isDirectory()) { const auto *themesDir = static_cast(themesEntry); @@ -287,6 +289,7 @@ void getFiles(PkgFileInfo &pkgFileInfo) } } + // icon themes const auto *iconsEntry = shareDir->entry(QStringLiteral("icons")); if(iconsEntry && iconsEntry->isDirectory()) { const auto *iconsDir = static_cast(iconsEntry); @@ -298,6 +301,7 @@ void getFiles(PkgFileInfo &pkgFileInfo) } } + // glib2 stuff (need to compile glib2 schemes later) const auto *glib2Entry = shareDir->entry(QStringLiteral("glib-2.0")); if(glib2Entry && glib2Entry->isDirectory()) { const auto *glib2Dir = static_cast(glib2Entry); @@ -315,52 +319,11 @@ void getFiles(PkgFileInfo &pkgFileInfo) } } + // application specific stuff (Qt stuff is added separately, so skip Qt here) if(pkgFileInfo.name.compare(QLatin1String("qt"))) { const auto *appEntry = shareDir->entry(pkgFileInfo.name); if(appEntry && appEntry->isDirectory()) { - const auto *appDir = static_cast(appEntry); - for(const auto &entryName : appDir->entries()) { - const auto *entry = appDir->entry(entryName); - if(entry->isFile()) { - pkgFileInfo.relevantFiles.emplace_back(static_cast(entry), appDir, RelevantFileType::ConfigFile, root.first); - } else { - const auto subDir = static_cast(entry); - if(entryName == QLatin1String("translations")) { - for(const auto &entryName : subDir->entries()) { - if(entryName.endsWith(QLatin1String(".qm"))) { - if(const auto *qmEntry = subDir->entry(entryName)) { - if(qmEntry->isFile()) { - pkgFileInfo.relevantFiles.emplace_back(static_cast(qmEntry), subDir, RelevantFileType::Translation, root.first); - } - } - } - } - } else { - for(const auto &entryName : subDir->entries()) { - if(const auto *configEntry = subDir->entry(entryName)) { - if(configEntry->isFile()) { - pkgFileInfo.relevantFiles.emplace_back(static_cast(configEntry), subDir, RelevantFileType::ConfigFile, root.first, subDir->name()); - } - } - } - } - } - - } - const auto *trEntry = appDir->entry(QStringLiteral("translations")); - if(trEntry && trEntry->isDirectory()) { - const auto trDir = static_cast(trEntry); - for(const auto &entryName : trDir->entries()) { - if(entryName.endsWith(QLatin1String(".qm"))) { - if(const auto *qmEntry = trDir->entry(entryName)) { - if(qmEntry->isFile()) { - pkgFileInfo.relevantFiles.emplace_back(static_cast(qmEntry), trDir, RelevantFileType::Translation, root.first); - } - } - } - } - } - + addEntries(pkgFileInfo, RelevantFileType::SharedData, static_cast(appEntry), QString(), QString(), root.first); } } @@ -449,7 +412,7 @@ void makeArchive(const list &pkgFiles, const QByteArray &pkgList, c // -> add note targetArchive->writeFile(root + QStringLiteral("/note.txt"), QByteArray("This archive has been created with Martchus' repository indexing tool.\n" - "List of included packages: var/lib/repoindex/packages.list\n" + "List of included packages (name, version, license info and upstream URL): var/lib/repoindex/packages.list\n" "More info: http://martchus.netai.net/page.php?name=programming")); // -> add package list if(!pkgList.isEmpty()) { @@ -504,15 +467,9 @@ void makeArchive(const list &pkgFiles, const QByteArray &pkgList, c path = root % QStringLiteral("/share/icons/") % relevantFile.subDir % QChar('/') % relevantFile.name; mode = 0100644; break; - case RelevantFileType::ConfigFile: - if(relevantFile.subDir.isEmpty()) { - path = root % QStringLiteral("/share/") % pkgFile.name % QChar('/') % relevantFile.name; - } else { - path = root % QStringLiteral("/share/") % pkgFile.name % QChar('/') % relevantFile.subDir % QChar('/') % relevantFile.name; - } - mode = 0100644; - break; } + // write the file + // disable symlinks: there is no decent support for symlinks under Windows //if(relevantFile.symlinkTarget.isEmpty()) { targetArchive->writeFile(path, relevantFile.data, mode); //} else { @@ -533,7 +490,7 @@ void MingwBundle::createBundle(const string &targetDir, const string &targetName cerr << shchar << "Gathering relevant files ..." << endl; // get package files list pkgFiles; - for(const auto *pkg : m_packages) { + for(const Package *pkg : m_packages) { QString pkgFile; if(!pkg->repository()->packagesDirectory().isEmpty()) { pkgFile = pkg->repository()->packagesDirectory() % QChar('/') % pkg->fileName(); @@ -547,7 +504,14 @@ void MingwBundle::createBundle(const string &targetDir, const string &targetName // TODO: download package from mirror } } - pkgFiles.emplace_back(pkg->name().startsWith(QLatin1String("mingw-w64-")) ? pkg->name().mid(10) : pkg->name(), pkgFile); + // strip "mingw-w64-"-prefix and vcs-suffix (if present) + QStringRef pkgName = pkg->name().startsWith(QLatin1String("mingw-w64-")) ? pkg->name().midRef(10) : QStringRef(&pkg->name()); + if(pkgName.endsWith(QLatin1String("-svn")) || pkgName.endsWith(QLatin1String("-git"))) { + pkgName = pkgName.mid(0, pkgName.length() - 4); + } else if(pkgName.endsWith(QLatin1String("-hg"))) { + pkgName = pkgName.mid(0, pkgName.length() - 3); + } + pkgFiles.emplace_back(pkgName.toString(), pkgFile); } for(const auto &pkgFileStdStr : m_extraPackages) { QString pkgFile = QString::fromLocal8Bit(pkgFileStdStr.data()); @@ -573,8 +537,8 @@ void MingwBundle::createBundle(const string &targetDir, const string &targetName } // make a list with package info to be included in the target archive QJsonArray pkgArray; - for(const auto *pkg : m_packages) { - pkgArray << pkg->basicInfo(true); + for(const Package *pkg : m_packages) { + pkgArray << pkg->simpleInfo(); } QJsonDocument pkgList; pkgList.setArray(pkgArray); diff --git a/alpm/package.cpp b/alpm/package.cpp index 1abba91..28aab0b 100644 --- a/alpm/package.cpp +++ b/alpm/package.cpp @@ -337,6 +337,21 @@ QJsonObject Package::detailedInfo() const return info; } +QJsonObject Package::simpleInfo() const +{ + QJsonObject info; + put(info, QStringLiteral("name"), name()); + put(info, QStringLiteral("ver"), version()); + put(info, QStringLiteral("desc"), description()); + put(info, QStringLiteral("flagdate"), outOfDate()); + put(info, QStringLiteral("arch"), buildArchitecture()); + put(info, QStringLiteral("bdate"), buildDate()); + put(info, QStringLiteral("url"), upstreamUrl()); + put(info, QStringLiteral("lic"), licenses()); + put(info, QStringLiteral("packer"), packer()); + return info; +} + /*! * \brief Writes the package contents to the specified data stream. */ diff --git a/alpm/package.h b/alpm/package.h index 8304748..b77a18a 100644 --- a/alpm/package.h +++ b/alpm/package.h @@ -184,6 +184,7 @@ public: // JSON serialization QJsonObject basicInfo(bool includeRepoAndName = false) const; QJsonObject detailedInfo() const; + QJsonObject simpleInfo() const; // caching void writeToCacheStream(QDataStream &out); diff --git a/repoindex.pro b/repoindex.pro index 88a20d4..914453b 100644 --- a/repoindex.pro +++ b/repoindex.pro @@ -46,7 +46,8 @@ HEADERS += \ alpm/packagelookup.h \ alpm/packagefinder.h -SOURCES += main.cpp \ +SOURCES += \ + main.cpp \ alpm/manager.cpp \ alpm/package.cpp \ alpm/utilities.cpp \ @@ -72,7 +73,9 @@ OTHER_FILES += \ LICENSE \ CMakeLists.txt \ resources/config.h.in \ - resources/windows.rc.in + resources/windows.rc.in \ + resources/systemd/repoindex.service \ + resources/settings/repoindex.conf.js DISTFILES += \ web/index.html \ @@ -86,8 +89,12 @@ DISTFILES += \ web/js/utils.js \ web/css/core.css \ web/css/dashboard.css \ - repoindex.conf.js \ - web/js/client.js + web/js/client.js \ + web/3rdparty/bootstrap/css/bootstrap.min.css \ + web/3rdparty/bootstrap_dropdowns_enhancement/css/dropdowns-enhancement.min.css \ + web/3rdparty/bootstrap/js/bootstrap.min.js \ + web/3rdparty/bootstrap_dropdowns_enhancement/js/dropdowns-enhancement.js + # libs and includepath CONFIG(debug, debug|release) { @@ -95,7 +102,7 @@ CONFIG(debug, debug|release) { } else { LIBS += -lc++utilities } -LIBS += -lalpm -lKF5Archive +LIBS += -lalpm # installs target.path = $$(INSTALL_ROOT)/bin diff --git a/samples/repoindex.conf.js b/resources/settings/repoindex.conf.js similarity index 85% rename from samples/repoindex.conf.js rename to resources/settings/repoindex.conf.js index dde94b5..9970c34 100644 --- a/samples/repoindex.conf.js +++ b/resources/settings/repoindex.conf.js @@ -9,8 +9,11 @@ "enabled": true }, + "cacheDir": "/var/cache/repoindex" + "server": { - "listeningPort": 1234, + "websocketListeningAddr": "any-IPv4", + "websocketListeningPort": 1234, "certFile": "some.cert", "keyFile": "some.key", "insecure": false diff --git a/resources/systemd/repoindex.service b/resources/systemd/repoindex.service new file mode 100644 index 0000000..a644d91 --- /dev/null +++ b/resources/systemd/repoindex.service @@ -0,0 +1,12 @@ +[Unit] +Description=A repository browser. +After=network.target + +[Service] +User=http +ExecStart=/usr/bin/repoindex server +KillSignal=SIGQUIT +Restart=on-failure + +[Install] +WantedBy=multi-user.target