Compare commits
No commits in common. "master" and "fix-caching" have entirely different histories.
master
...
fix-cachin
|
@ -1 +1 @@
|
|||
Subproject commit 71b613bc7c43d37b444e5531241c355e23de925c
|
||||
Subproject commit d8ca70bca18b8a31e88b31f981a0e9fb120ac8a6
|
|
@ -9,7 +9,7 @@ set(META_APP_DESCRIPTION "Repository manager and package builder for Arch Linux"
|
|||
set(META_APP_CATEGORIES "System;Utility;Network;FileTransfer")
|
||||
set(META_VERSION_MAJOR 0)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 4)
|
||||
set(META_VERSION_PATCH 3)
|
||||
set(META_VERSION_EXACT_SONAME ON)
|
||||
#set(META_CXX_STANDARD 20)
|
||||
set(META_CXX_STANDARD "any")
|
||||
|
|
27
README.md
27
README.md
|
@ -43,16 +43,6 @@ Further ideas (not implemented yet):
|
|||
* bundle an application with its dependencies similar to `linuxdeployqt`
|
||||
and `windeployqt`
|
||||
|
||||
## Important caveats
|
||||
* So far releases are not regularly tagged. It is probably best to build the latest version
|
||||
from Git as needed.
|
||||
* So far also no security review of the code has been done and at the same time the code
|
||||
base contains lots of rather low-level code (instead of relying on frameworks), many
|
||||
self-written parsers and exposes a web service. So use it at your own risk (like most
|
||||
other open source projects, but here I'd like to highlight it specifically).
|
||||
* 32-bit architectures are not supported (as the database needs a huge address space). Of
|
||||
course you can build packages *for* 32-bit architectures.
|
||||
|
||||
## Setup server
|
||||
An example config files can be found in this repository, see the `srv/doc`
|
||||
directory. The example config is also installed so one can easily get started.
|
||||
|
@ -118,7 +108,7 @@ local_mirror = file://$local_db_path
|
|||
```
|
||||
|
||||
The server obviously needs write permissions to add packages to repositories. In my
|
||||
setup I just added it as group and set permissions accordingly:
|
||||
setup I've just add it as group and set permissions accordingly:
|
||||
|
||||
```
|
||||
sudo chown -R martchus:buildservice-git $local_db_path
|
||||
|
@ -212,7 +202,7 @@ location /buildservice/api/ {
|
|||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
location ~ ^(?!/buildservice/api/)/buildservice/(.*)$ {
|
||||
alias /usr/share/buildservice-git/web/static/$1;
|
||||
alias /run/media/devel/projects/c++/cmake/auto-makepkg/buildservice/static/$1;
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -232,14 +222,14 @@ keyserver hkp://keys.gnupg.net
|
|||
#### Notes
|
||||
* Adding the pacman keyring is actually not very useful because we need to check signatures
|
||||
of any upstream project and not just arch devs.
|
||||
* If "auto-key-retrieve" does not work, use `gpg --recv-key <KEYID>` as a workaround.
|
||||
* If "auto-key-retrieve" does not work, use `gpg --recv-key <KEYID>` as a workaround
|
||||
* Also see http://allanmcrae.com/2015/01/two-pgp-keyrings-for-package-management-in-arch-linux/
|
||||
|
||||
### ccache configuration
|
||||
To use ccache one can set the ccache directory in the config (`ccache_dir`) and install the
|
||||
package `ccache` (and `mingw-w64-ccache` for MinGW packages) into the chroot. Make sure the user
|
||||
you start the server with has permissions to read and write there. Otherwise the resulting
|
||||
configuration errors can be confusing. Internally the server is mounting that directory as
|
||||
configure errors can be confusing. Internally the server is mounting that directory like
|
||||
described in [the wiki](https://wiki.archlinux.org/index.php/Ccache#makechrootpkg).
|
||||
|
||||
If you want to use the existing `ccache` directory owned by your current user, you could do
|
||||
|
@ -396,14 +386,13 @@ and CSS files are bundled. For development the full checkout might be useful
|
|||
|
||||
```
|
||||
cd srv/static/node_modules
|
||||
npm install @xterm/xterm @xterm/addon-search
|
||||
npm install xterm
|
||||
npm install --save xterm-addon-search
|
||||
```
|
||||
|
||||
## Copyright notice and license
|
||||
Copyright © 2017-2024 Marius Kittler
|
||||
Copyright © 2017-2023 Marius Kittler
|
||||
|
||||
All code is licensed under [GPL-2-or-later](LICENSE). This does *not* apply to
|
||||
code contained in Git repositories included as Git submodule (which contain
|
||||
their own README and licensing information). This does also *not* apply to
|
||||
code in the directories under `srv/static/node_modules` (which contain 3rdparty
|
||||
code that has its own licensing information).
|
||||
their own README and licensing information).
|
||||
|
|
|
@ -3,11 +3,11 @@ url = http://127.0.0.1:8090
|
|||
user = martchus
|
||||
|
||||
[instance/server]
|
||||
url = https://martchus.dyn.f3l.de/buildservice
|
||||
url = https://martchus.no-ip.biz/buildservice
|
||||
user = martchus
|
||||
|
||||
[instance/bogus]
|
||||
url = http://martchus.dyn.f3l.de/foo
|
||||
url = http://martchus.no-ip.biz/foo
|
||||
user = martchus
|
||||
|
||||
[user/martchus]
|
||||
|
|
|
@ -42,6 +42,9 @@ set(META_PROJECT_TYPE library)
|
|||
set(META_PROJECT_VARNAME LIBPKG)
|
||||
set(META_APP_NAME "Unofficial Arch Linux package library")
|
||||
set(META_APP_DESCRIPTION "C++ library to parse Arch Linux packages and databases")
|
||||
set(META_VERSION_MAJOR 0)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 1)
|
||||
|
||||
# find c++utilities
|
||||
set(CONFIGURATION_PACKAGE_SUFFIX
|
||||
|
|
|
@ -321,7 +321,7 @@ void Database::allPackages(const PackageVisitorMove &visitor)
|
|||
}
|
||||
}
|
||||
|
||||
void Database::allPackagesBase(const PackageVisitorBase &visitor)
|
||||
void Database::allPackages(const PackageVisitorBase &visitor)
|
||||
{
|
||||
auto txn = m_storage->packages.getROTransaction();
|
||||
for (auto i = txn.begin<std::shared_ptr, PackageBase>(); i != txn.end(); ++i) {
|
||||
|
@ -493,9 +493,6 @@ StorageID Database::findBasePackageWithID(const std::string &packageName, Packag
|
|||
|
||||
void Database::removePackage(const std::string &packageName)
|
||||
{
|
||||
if (packageName.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto lock = std::unique_lock(m_storage->updateMutex);
|
||||
auto txn = m_storage->packages.getRWTransaction();
|
||||
const auto [packageID, package] = m_storage->packageCache.retrieve(*m_storage, &txn, packageName);
|
||||
|
@ -894,34 +891,6 @@ PackageSpec LibPkg::PackageUpdater::findPackageWithID(const std::string &package
|
|||
return m_database.m_storage->packageCache.retrieve(*m_database.m_storage, &m_d->packagesTxn, packageName);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Begins updating the existing \a package with the specified \a packageID.
|
||||
* \remarks
|
||||
* - Do not use this function when PackageUpdate has been constructed with clear=true.
|
||||
* - Call this method before modifying \a package. Then modify the package. Then call endUpdate().
|
||||
*/
|
||||
void PackageUpdater::beginUpdate(StorageID packageID, const std::shared_ptr<Package> &package)
|
||||
{
|
||||
m_d->update(packageID, true, package);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ends updating the existing \a package with the specified \a packageID.
|
||||
* \remarks
|
||||
* - Do not use this function when PackageUpdate has been constructed with clear=true.
|
||||
* - Call this method after callsing beginUpdate() and modifying \a package.
|
||||
*/
|
||||
void PackageUpdater::endUpdate(StorageID packageID, const std::shared_ptr<Package> &package)
|
||||
{
|
||||
const auto &storage = m_database.m_storage;
|
||||
storage->packageCache.store(*m_database.m_storage, m_d->packagesTxn, packageID, package);
|
||||
m_d->update(packageID, false, package);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the specified \a package. The \a package may or may not exist.
|
||||
* \remarks If the package exists then provides/deps from the existing package are taken over if appropriate.
|
||||
*/
|
||||
StorageID PackageUpdater::update(const std::shared_ptr<Package> &package)
|
||||
{
|
||||
const auto &storage = m_database.m_storage;
|
||||
|
|
|
@ -120,8 +120,6 @@ struct LIBPKG_EXPORT PackageUpdater {
|
|||
~PackageUpdater();
|
||||
|
||||
PackageSpec findPackageWithID(const std::string &packageName);
|
||||
void beginUpdate(StorageID packageID, const std::shared_ptr<Package> &package);
|
||||
void endUpdate(StorageID packageID, const std::shared_ptr<Package> &package);
|
||||
StorageID update(const std::shared_ptr<Package> &package);
|
||||
bool insertFromDatabaseFile(const std::string &databaseFilePath);
|
||||
void commit();
|
||||
|
@ -173,7 +171,7 @@ struct LIBPKG_EXPORT Database : public ReflectiveRapidJSON::JsonSerializable<Dat
|
|||
static bool isFileRelevant(const char *filePath, const char *fileName, mode_t);
|
||||
std::vector<std::shared_ptr<Package>> findPackages(const std::function<bool(const Database &, const Package &)> &pred);
|
||||
void allPackages(const PackageVisitorMove &visitor);
|
||||
void allPackagesBase(const PackageVisitorBase &visitor);
|
||||
void allPackages(const PackageVisitorBase &visitor);
|
||||
void allPackagesByName(const PackageVisitorByName &visitor);
|
||||
void allPackagesByName(const PackageVisitorByNameBase &visitor);
|
||||
std::size_t packageCount() const;
|
||||
|
|
|
@ -367,26 +367,17 @@ void PackageBase::clear()
|
|||
description.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether addDepsAndProvidesFromOtherPackage() would take over the information (without force).
|
||||
*/
|
||||
bool Package::canDepsAndProvidesFromOtherPackage(const Package &otherPackage) const
|
||||
{
|
||||
return !((otherPackage.origin != PackageOrigin::PackageContents && otherPackage.origin != PackageOrigin::CustomSource)
|
||||
|| version != otherPackage.version
|
||||
|| !(!packageInfo || buildDate.isNull() || (otherPackage.packageInfo && buildDate == otherPackage.buildDate)));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Takes over deps/provides from \a otherPackage if appropriate.
|
||||
* \remarks
|
||||
* The information is not taken over if \a otherPackage does not match the current instance (only
|
||||
* version and build date are considered) or if otherPackage has no info from package contents. Use
|
||||
* the \a force parameter to avoid these checks.
|
||||
*/
|
||||
bool Package::addDepsAndProvidesFromOtherPackage(const Package &otherPackage, bool force)
|
||||
{
|
||||
if (&otherPackage == this || (!force && !canDepsAndProvidesFromOtherPackage(otherPackage))) {
|
||||
if (&otherPackage == this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip if otherPackage does not match the current instance (only version and build date are considered) or if otherPackage has no info from package contents
|
||||
if (!force
|
||||
&& ((otherPackage.origin != PackageOrigin::PackageContents && otherPackage.origin != PackageOrigin::CustomSource)
|
||||
|| version != otherPackage.version
|
||||
|| !(!packageInfo || buildDate.isNull() || (otherPackage.packageInfo && buildDate == otherPackage.buildDate)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -415,7 +415,6 @@ struct LIBPKG_EXPORT Package : public PackageBase,
|
|||
std::string_view directoryPath, const ArchiveFile &file, std::set<std::string> &dllsReferencedByImportLibs);
|
||||
void addDepsAndProvidesFromContents(const FileMap &contents);
|
||||
std::vector<std::string> processDllsReferencedByImportLibs(std::set<std::string> &&dllsReferencedByImportLibs);
|
||||
bool canDepsAndProvidesFromOtherPackage(const Package &otherPackage) const;
|
||||
bool addDepsAndProvidesFromOtherPackage(const Package &otherPackage, bool force = false);
|
||||
bool isArchAny() const;
|
||||
std::vector<std::string> validate() const;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// ignore warning about "return result_type{ storageEntry.id, storageEntry.ref.relatedStorage };"
|
||||
#pragma GCC diagnostic ignored "-Wnull-dereference"
|
||||
|
||||
#include "./storageprivate.h"
|
||||
|
||||
#include <c++utilities/conversion/stringbuilder.h>
|
||||
|
@ -126,11 +129,6 @@ auto StorageCache<StorageEntriesType, StorageType, SpecType>::retrieve(Storage &
|
|||
return retrieve(storage, nullptr, entryName);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Stores the specified \a entry.
|
||||
* \remarks The entry may exist or may not exist. A lookup for an existing entry is done to take over
|
||||
* deps/provides from the existing entry if it makes sense.
|
||||
*/
|
||||
template <typename StorageEntriesType, typename StorageType, typename SpecType>
|
||||
auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &storage, RWTxn &txn, const std::shared_ptr<Entry> &entry) -> StoreResult
|
||||
{
|
||||
|
@ -151,7 +149,6 @@ auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &sto
|
|||
entry->addDepsAndProvidesFromOtherPackage(*res.oldEntry);
|
||||
}
|
||||
lock.unlock();
|
||||
|
||||
// check for package in storage
|
||||
if (!res.oldEntry) {
|
||||
res.oldEntry = std::make_shared<Entry>();
|
||||
|
@ -161,10 +158,8 @@ auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &sto
|
|||
res.oldEntry.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// update package in storage
|
||||
res.id = txn.put(*entry, res.id);
|
||||
|
||||
// update cache entry
|
||||
lock = std::unique_lock(m_mutex);
|
||||
if (cacheEntry) {
|
||||
|
@ -174,31 +169,10 @@ auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &sto
|
|||
}
|
||||
cacheEntry->entry = entry;
|
||||
lock.unlock();
|
||||
|
||||
res.updated = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Stores the specified \a entry with the specified \a storageID.
|
||||
* \remarks This is used to update an existing entry with a known ID.
|
||||
*/
|
||||
template <typename StorageEntriesType, typename StorageType, typename SpecType>
|
||||
auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(
|
||||
Storage &storage, RWTxn &txn, StorageID storageID, const std::shared_ptr<Entry> &entry) -> void
|
||||
{
|
||||
// update package in storage
|
||||
const auto id = txn.put(*entry, storageID);
|
||||
|
||||
// update cache entry
|
||||
using CacheEntry = typename Entries::StorageEntry;
|
||||
using CacheRef = typename Entries::Ref;
|
||||
const auto ref = CacheRef(storage, entry);
|
||||
const auto lock = std::unique_lock(m_mutex);
|
||||
const auto cacheEntry = &m_entries.insert(CacheEntry(ref, id));
|
||||
cacheEntry->entry = entry;
|
||||
}
|
||||
|
||||
template <typename StorageEntriesType, typename StorageType, typename SpecType>
|
||||
bool StorageCache<StorageEntriesType, StorageType, SpecType>::invalidate(Storage &storage, const std::string &entryName)
|
||||
{
|
||||
|
|
|
@ -152,7 +152,6 @@ template <typename StorageEntriesType, typename StorageType, typename SpecType>
|
|||
SpecType retrieve(Storage &storage, RWTxn *, const std::string &entryName);
|
||||
SpecType retrieve(Storage &storage, const std::string &entryName);
|
||||
StoreResult store(Storage &storage, RWTxn &txn, const std::shared_ptr<Entry> &entry);
|
||||
void store(Storage &storage, RWTxn &txn, StorageID storageID, const std::shared_ptr<Entry> &entry);
|
||||
bool invalidate(Storage &storage, const std::string &entryName);
|
||||
bool invalidateCacheOnly(Storage &storage, const std::string &entryName);
|
||||
void clear(Storage &storage);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#ifndef LIBPKG_GLOBAL
|
||||
#define LIBPKG_GLOBAL
|
||||
|
||||
#include "libpkg-definitions.h"
|
||||
#include <c++utilities/application/global.h>
|
||||
|
||||
#ifdef LIBPKG_STATIC
|
||||
|
|
|
@ -1041,9 +1041,8 @@ bool PackageNameData::isVcsPackage() const
|
|||
|
||||
PackageNameData PackageNameData::decompose(std::string_view packageName)
|
||||
{
|
||||
static constexpr auto targetPrefixBrackets = 2;
|
||||
static const auto packageNameRegex
|
||||
= std::regex("((lib32|mingw-w64(-(ucrt|clang-x86_64|clang-aarch64))?|android-aarch64|android-x86-64|android-x86|android-armv7a-eabi|arm-none-eabi|aarch64-linux-"
|
||||
= std::regex("((lib32|mingw-w64|android-aarch64|android-x86-64|android-x86|android-armv7a-eabi|arm-none-eabi|aarch64-linux-"
|
||||
"gnu|static-compat|riscv64-linux|avr|psp)-)?(.*?)((-(cvs|svn|hg|darcs|bzr|git|custom|compat|static|qt\\d+|doc|cli|gui))*)");
|
||||
auto data = PackageNameData{};
|
||||
auto match = std::cmatch{};
|
||||
|
@ -1055,8 +1054,8 @@ PackageNameData PackageNameData::decompose(std::string_view packageName)
|
|||
regexMatch.first + offset, static_cast<std::size_t>(regexMatch.length() - static_cast<std::cmatch::difference_type>(offset)));
|
||||
};
|
||||
data.targetPrefix = matchToStringView(match[2]);
|
||||
data.actualName = matchToStringView(match[3 + targetPrefixBrackets]);
|
||||
data.vcsSuffix = match[4 + targetPrefixBrackets].length() ? matchToStringView(match[4 + targetPrefixBrackets], 1) : std::string_view{};
|
||||
data.actualName = matchToStringView(match[3]);
|
||||
data.vcsSuffix = match[4].length() ? matchToStringView(match[4], 1) : std::string_view{};
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ void walkThroughArchiveInternal(struct archive *ar, const string &archiveName, c
|
|||
}
|
||||
|
||||
if (directoryHandler(std::string_view(filePath, dirEnd))) {
|
||||
goto free;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ void walkThroughArchiveInternal(struct archive *ar, const string &archiveName, c
|
|||
if (entryType == AE_IFLNK) {
|
||||
if (fileHandler(std::string_view(filePath, static_cast<string::size_type>(dirEnd - filePath)),
|
||||
ArchiveFile(fileName, std::string(archive_entry_symlink_utf8(entry)), ArchiveFileType::Link, creationTime, modificationTime))) {
|
||||
goto free;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -128,12 +128,11 @@ void walkThroughArchiveInternal(struct archive *ar, const string &archiveName, c
|
|||
// move it to results
|
||||
if (fileHandler(std::string_view(filePath, static_cast<string::size_type>(dirEnd - filePath)),
|
||||
ArchiveFile(fileName, std::move(fileContent), ArchiveFileType::Regular, creationTime, modificationTime))) {
|
||||
goto free;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// free resources used by libarchive
|
||||
free:
|
||||
archive_entry_free(entry);
|
||||
int returnCode = archive_read_free(ar);
|
||||
if (returnCode != ARCHIVE_OK) {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#include "../data/config.h"
|
||||
|
||||
#include "resources/config.h"
|
||||
|
||||
#include <c++utilities/application/commandlineutils.h>
|
||||
#include <c++utilities/conversion/stringbuilder.h>
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
#include <c++utilities/io/misc.h>
|
||||
|
@ -40,7 +37,6 @@ class DataTests : public TestFixture {
|
|||
CPPUNIT_TEST(testAddingDepsAndProvidesFromOtherPackage);
|
||||
CPPUNIT_TEST(testDependencyExport);
|
||||
CPPUNIT_TEST(testPackageUpdater);
|
||||
CPPUNIT_TEST(stresstestPackageUpdater);
|
||||
CPPUNIT_TEST(testMisc);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
|
@ -65,7 +61,6 @@ public:
|
|||
void testAddingDepsAndProvidesFromOtherPackage();
|
||||
void testDependencyExport();
|
||||
void testPackageUpdater();
|
||||
void stresstestPackageUpdater();
|
||||
void testMisc();
|
||||
|
||||
private:
|
||||
|
@ -233,10 +228,7 @@ void DataTests::testPackageSearch()
|
|||
{
|
||||
setupPackages();
|
||||
|
||||
auto pkgs = m_config.findPackages(std::string_view());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("no results for package with empty name", 0_st, pkgs.size());
|
||||
|
||||
pkgs = m_config.findPackages("foo"sv);
|
||||
auto pkgs = m_config.findPackages("foo"sv);
|
||||
CPPUNIT_ASSERT_EQUAL(2_st, pkgs.size());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("package from first db returned first, cached object returned", m_pkg1, pkgs.front().pkg);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("package from first db returned second, cached object returned", m_pkg3, pkgs.back().pkg);
|
||||
|
@ -572,68 +564,6 @@ void DataTests::testPackageUpdater()
|
|||
CPPUNIT_ASSERT_EQUAL("zlib"s, newPkg->name);
|
||||
}
|
||||
|
||||
void DataTests::stresstestPackageUpdater()
|
||||
{
|
||||
if (!CppUtilities::isEnvVariableSet(PROJECT_VARNAME_UPPER "_ENABLE_STRESS_TESTS").value_or(false)) {
|
||||
return;
|
||||
}
|
||||
m_dbFile = workingCopyPath("stresstest-data.db", WorkingCopyMode::Cleanup);
|
||||
m_config.initStorage(m_dbFile.data());
|
||||
|
||||
auto dbFile = testFilePath("stresstest/ownstuff-protected.files.tar.xz");
|
||||
auto dbFileOld = testFilePath("stresstest/ownstuff-protected.files.tar.xz.old");
|
||||
auto *const db = m_config.findOrCreateDatabase("ownstuff-protected"sv, "x86_64"sv);
|
||||
auto basePackageFromIndex = PackageBase();
|
||||
|
||||
static constexpr auto iterations = 1000;
|
||||
static const auto packageToModify = "android-sdk"s;
|
||||
static const auto newLibdepends = std::set<std::string>{"foo", "bar", "baz"};
|
||||
static const auto newLibprovides = std::set<std::string>{"a", "b", "c"};
|
||||
for (auto i = 0; i != iterations; ++i) {
|
||||
if (i % (iterations / 100) == 0) {
|
||||
std::cerr << "\rRunning stress test: " << (i * 100 / iterations) << " %";
|
||||
}
|
||||
|
||||
auto updater = LibPkg::PackageUpdater(*db, true);
|
||||
updater.insertFromDatabaseFile(i % 2 == 0 ? dbFileOld : dbFile);
|
||||
updater.commit();
|
||||
CPPUNIT_ASSERT_MESSAGE("packages present", db->packageCount() > 0);
|
||||
|
||||
auto updater2 = LibPkg::PackageUpdater(*db);
|
||||
auto [existingPackageID, existingPackage] = updater2.findPackageWithID(packageToModify);
|
||||
CPPUNIT_ASSERT(existingPackage != nullptr);
|
||||
CPPUNIT_ASSERT_EQUAL(packageToModify, existingPackage->name);
|
||||
CPPUNIT_ASSERT(existingPackage->libdepends.empty());
|
||||
CPPUNIT_ASSERT(existingPackage->libprovides.empty());
|
||||
updater2.beginUpdate(existingPackageID, existingPackage);
|
||||
existingPackage->libdepends = newLibdepends;
|
||||
existingPackage->libprovides = newLibprovides;
|
||||
updater2.endUpdate(existingPackageID, existingPackage);
|
||||
updater2.commit();
|
||||
|
||||
db->allPackagesBase([db, &basePackageFromIndex](StorageID packageID, std::shared_ptr<PackageBase> &&basePackage) {
|
||||
CPPUNIT_ASSERT_MESSAGE("package ID valid", packageID);
|
||||
CPPUNIT_ASSERT_MESSAGE("base package returned", basePackage);
|
||||
CPPUNIT_ASSERT_MESSAGE("name assigned", !basePackage->name.empty());
|
||||
CPPUNIT_ASSERT_MESSAGE("version assigned", !basePackage->version.empty());
|
||||
basePackageFromIndex.clear();
|
||||
|
||||
const auto packageIDViaIndex = db->findBasePackageWithID(basePackage->name, basePackageFromIndex);
|
||||
CPPUNIT_ASSERT_MESSAGE("package ID via index valid", packageIDViaIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("index valid, ID matches", packageID, packageIDViaIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("index valid, name matches", basePackage->name, basePackageFromIndex.name);
|
||||
return false;
|
||||
});
|
||||
|
||||
auto updatedPackage = db->findPackage(packageToModify);
|
||||
CPPUNIT_ASSERT(updatedPackage != nullptr);
|
||||
CPPUNIT_ASSERT_EQUAL(packageToModify, updatedPackage->name);
|
||||
CPPUNIT_ASSERT_EQUAL(newLibdepends, updatedPackage->libdepends);
|
||||
CPPUNIT_ASSERT_EQUAL(newLibprovides, updatedPackage->libprovides);
|
||||
}
|
||||
std::cerr << "Running stress test: done\n";
|
||||
}
|
||||
|
||||
void DataTests::testMisc()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL("123.4"s, PackageVersion::trimPackageVersion("123.4"s));
|
||||
|
|
|
@ -128,10 +128,6 @@ void ParserTests::testParsingPackageName()
|
|||
CPPUNIT_ASSERT_EQUAL("gcc"sv, mingwGCC.actualName);
|
||||
CPPUNIT_ASSERT_EQUAL("mingw-w64"sv, mingwGCC.targetPrefix);
|
||||
CPPUNIT_ASSERT_EQUAL(""sv, mingwGCC.vcsSuffix);
|
||||
const auto mingwUcrtCppWinrt = PackageNameData::decompose("mingw-w64-ucrt-cppwinrt");
|
||||
CPPUNIT_ASSERT_EQUAL("cppwinrt"sv, mingwUcrtCppWinrt.actualName);
|
||||
CPPUNIT_ASSERT_EQUAL("mingw-w64-ucrt"sv, mingwUcrtCppWinrt.targetPrefix);
|
||||
CPPUNIT_ASSERT_EQUAL(""sv, mingwUcrtCppWinrt.vcsSuffix);
|
||||
const auto staticCompatQt6 = PackageNameData::decompose("static-compat-qt6-base");
|
||||
CPPUNIT_ASSERT_EQUAL("qt6-base"sv, staticCompatQt6.actualName);
|
||||
CPPUNIT_ASSERT_EQUAL("static-compat"sv, staticCompatQt6.targetPrefix);
|
||||
|
|
|
@ -70,6 +70,9 @@ set(META_PROJECT_VARNAME LIBREPOMGR)
|
|||
set(META_APP_AUTHOR "Martchus")
|
||||
set(META_APP_NAME "Unofficial Arch Linux repository management library")
|
||||
set(META_APP_DESCRIPTION "Library for managing custom Arch Linux repositories")
|
||||
set(META_VERSION_MAJOR 0)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 1)
|
||||
set(META_VERSION_CACHE 11)
|
||||
set(LINK_TESTS_AGAINST_APP_TARGET ON)
|
||||
|
||||
|
@ -165,14 +168,12 @@ add_reflection_generator_invocation(
|
|||
ERROR_RESILIENT)
|
||||
|
||||
# disable Boost's support for concepts to avoid compile errors
|
||||
# ~~~
|
||||
# /usr/include/boost/asio/async_result.hpp:70:20: error: concept cannot have associated constraints
|
||||
# BOOST_ASIO_CONCEPT completion_handler_for =
|
||||
# ^
|
||||
# /usr/include/boost/asio/async_result.hpp:492:20: error: concept cannot have associated constraints
|
||||
# BOOST_ASIO_CONCEPT completion_token_for = requires(T&& t)
|
||||
# ^
|
||||
# ~~~
|
||||
list(APPEND META_PUBLIC_COMPILE_DEFINITIONS BOOST_ASIO_DISABLE_CONCEPTS)
|
||||
|
||||
# include modules to apply configuration
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <c++utilities/io/ansiescapecodes.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
namespace LibRepoMgr {
|
||||
|
||||
|
@ -40,19 +39,16 @@ template <> inline void convertValue(const std::multimap<std::string, std::strin
|
|||
}
|
||||
}
|
||||
|
||||
static constexpr char toUpper(const char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;
|
||||
}
|
||||
|
||||
void ServiceSetup::Authentication::applyConfig(const std::string &userName, const std::multimap<std::string, std::string> &multimap)
|
||||
{
|
||||
auto &user = users[userName];
|
||||
convertValue(multimap, "password_sha512", user.passwordSha512);
|
||||
convertValue(multimap, "permissions", user.permissions);
|
||||
for (auto &c : user.passwordSha512) {
|
||||
c = toUpper(c);
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr char toLower(const char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
|
||||
}
|
||||
|
||||
UserAuth ServiceSetup::Authentication::authenticate(std::string_view authorizationHeader) const
|
||||
|
@ -87,26 +83,22 @@ UserAuth ServiceSetup::Authentication::authenticate(std::string_view authorizati
|
|||
if (user == users.cend()) {
|
||||
return auth;
|
||||
}
|
||||
constexpr auto sha512HexSize = SHA512_DIGEST_LENGTH * 2;
|
||||
constexpr auto sha512HexSize = 128;
|
||||
if (user->second.passwordSha512.size() != sha512HexSize) {
|
||||
return auth;
|
||||
}
|
||||
|
||||
// hash password
|
||||
auto hash = std::array<unsigned char, SHA512_DIGEST_LENGTH>();
|
||||
SHA512(reinterpret_cast<const unsigned char *>(password.data()), password.size(), hash.data());
|
||||
|
||||
// convert hash to string (hexadecimal)
|
||||
auto hashHex = std::array<char, sha512HexSize>();
|
||||
auto hashHexIter = hashHex.begin();
|
||||
for (const auto hashNumber : hash) {
|
||||
*(hashHexIter++) = static_cast<char>(CppUtilities::digitToChar((hashNumber / 16) % 16));
|
||||
*(hashHexIter++) = static_cast<char>(CppUtilities::digitToChar(hashNumber % 16));
|
||||
}
|
||||
unsigned char hash[SHA512_DIGEST_LENGTH];
|
||||
SHA512(reinterpret_cast<const unsigned char *>(password.data()), password.size(), hash);
|
||||
|
||||
// check whether password hash matches
|
||||
if (CRYPTO_memcmp(user->second.passwordSha512.data(), hashHex.data(), sha512HexSize) != 0) {
|
||||
return auth;
|
||||
auto i = user->second.passwordSha512.cbegin();
|
||||
for (unsigned char hashNumber : hash) {
|
||||
const auto digits = CppUtilities::numberToString(hashNumber, 16);
|
||||
if ((toLower(*(i++)) != toLower(digits.size() < 2 ? '0' : digits.front())) || (toLower(*(i++)) != toLower(digits.back()))) {
|
||||
return auth;
|
||||
}
|
||||
}
|
||||
|
||||
// return the user's permissions
|
||||
|
|
|
@ -192,17 +192,11 @@ BuildActionMetaInfo::BuildActionMetaInfo()
|
|||
.param = "fetch-official-pkgbuilds",
|
||||
},
|
||||
BuildActionFlagMetaInfo{
|
||||
.id = static_cast<BuildActionFlagType>(PrepareBuildFlags::UseContainer),
|
||||
.id = static_cast<BuildActionFlagType>(ConductBuildFlags::UseContainer),
|
||||
.name = "Use container",
|
||||
.desc = "Uses `makecontainerpkg` instead of using `makepkg` when printing source info; eliminates the need to having pacman on the host by using docker/podman instead",
|
||||
.param = "use-container",
|
||||
},
|
||||
BuildActionFlagMetaInfo{
|
||||
.id = static_cast<BuildActionFlagType>(PrepareBuildFlags::AurOnly),
|
||||
.name = "AUR-only",
|
||||
.desc = "Consider it an error when a PKGBUILD was found locally and thus was not downloaded from the AUR",
|
||||
.param = "aur-only",
|
||||
},
|
||||
},
|
||||
.settings = {
|
||||
BuildActionSettingMetaInfo{
|
||||
|
|
|
@ -88,7 +88,6 @@ enum class PrepareBuildFlags : BuildActionFlagType {
|
|||
PullingInFurtherDependenciesUnexpected = (1 << 5),
|
||||
FetchOfficialPackageSources = (1 << 6),
|
||||
UseContainer = (1 << 7),
|
||||
AurOnly = (1 << 8),
|
||||
};
|
||||
enum class ConductBuildFlags : BuildActionFlagType {
|
||||
None,
|
||||
|
|
|
@ -519,8 +519,7 @@ private:
|
|||
bool m_pullingInFurtherDependenciesUnexpected = false;
|
||||
bool m_pulledInFurtherDependencies = false;
|
||||
bool m_fetchOfficialSources = false;
|
||||
bool m_useContainer = false;
|
||||
bool m_aurOnly = false;
|
||||
bool m_useContainer;
|
||||
};
|
||||
|
||||
struct LIBREPOMGR_EXPORT BatchProcessingSession : public MultiSession<std::string> {
|
||||
|
|
|
@ -1142,7 +1142,7 @@ void ConductBuild::invokeMakechrootpkgStep3(std::shared_ptr<BuildProcessSession>
|
|||
locks.emplace_back(std::move(chrootLock));
|
||||
auto lock = lockToRead();
|
||||
auto &packageProgress = m_buildProgress.progressByPackage[packageName];
|
||||
processSession->launch(boost::process::start_dir(packageProgress.buildDirectory), m_makeChrootPkgPath, sudoArgs, makechrootpkgFlags, "-Y",
|
||||
processSession->launch(boost::process::start_dir(packageProgress.buildDirectory), m_makeChrootPkgPath, sudoArgs, makechrootpkgFlags, "-C",
|
||||
m_globalPackageCacheDir, "-r", chrootDir, "-l", packageProgress.chrootUser, packageProgress.makechrootpkgFlags, "--", makepkgFlags,
|
||||
packageProgress.makepkgFlags, boost::process::std_in < boost::asio::buffer(m_sudoPassword));
|
||||
lock.unlock();
|
||||
|
|
|
@ -78,7 +78,6 @@ void PrepareBuild::run()
|
|||
m_pullingInFurtherDependenciesUnexpected = flags & PrepareBuildFlags::PullingInFurtherDependenciesUnexpected;
|
||||
m_fetchOfficialSources = flags & PrepareBuildFlags::FetchOfficialPackageSources;
|
||||
m_useContainer = flags & PrepareBuildFlags::UseContainer;
|
||||
m_aurOnly = flags & PrepareBuildFlags::AurOnly;
|
||||
if (m_forceBumpPackageVersion && m_keepPkgRelAndEpoch) {
|
||||
reportError("Can not force-bump pkgrel and keeping it at the same time.");
|
||||
return;
|
||||
|
@ -891,22 +890,14 @@ void PrepareBuild::computeDependencies(WebClient::AurSnapshotQuerySession::Conta
|
|||
}
|
||||
|
||||
// check for errors
|
||||
auto failedPackages = std::set<std::string>();
|
||||
auto localPackages = std::set<std::string>();
|
||||
auto errorMessage = std::string();
|
||||
set<string> failedPackages;
|
||||
for (const auto &buildData : m_buildDataByPackage) {
|
||||
if (!buildData.second.error.empty()) {
|
||||
failedPackages.emplace(buildData.first);
|
||||
} else if (m_aurOnly && !buildData.second.originalSourceDirectory.empty()) {
|
||||
localPackages.emplace(buildData.first);
|
||||
}
|
||||
}
|
||||
if (!failedPackages.empty()) {
|
||||
errorMessage = "Unable to retrieve the following packages (see result data for details): " + joinStrings(failedPackages, " ");
|
||||
} else if (!localPackages.empty()) {
|
||||
errorMessage = "The following packages have a local override but the AUR-only flag was set: " + joinStrings(localPackages, " ");
|
||||
}
|
||||
if (!errorMessage.empty()) {
|
||||
auto errorMessage = "Unable to retrieve the following packages (see result data for details): " + joinStrings(failedPackages, " ");
|
||||
m_buildAction->appendOutput(Phrases::ErrorMessage, errorMessage, '\n');
|
||||
auto resultData = makeResultData(std::move(errorMessage));
|
||||
auto buildActionWriteLock = m_setup.building.lockToWrite();
|
||||
|
|
|
@ -364,7 +364,7 @@ void ReloadLibraryDependencies::loadPackageInfoFromContents()
|
|||
m_buildAction->appendOutput(Phrases::SuccessMessage, "Adding parsed information to databases ...\n");
|
||||
std::size_t counter = 0;
|
||||
for (DatabaseToConsider &relevantDb : m_relevantPackagesByDatabase) {
|
||||
auto lock = m_setup.config.lockToRead();
|
||||
auto configWritelock = m_setup.config.lockToRead();
|
||||
auto *const db = m_setup.config.findDatabase(relevantDb.name, relevantDb.arch);
|
||||
if (!db) {
|
||||
continue; // the whole database has been removed while we were loading package contents
|
||||
|
@ -377,19 +377,19 @@ void ReloadLibraryDependencies::loadPackageInfoFromContents()
|
|||
}
|
||||
// find the package in the database again
|
||||
const auto [packageID, existingPackage] = updater.findPackageWithID(package.info.name);
|
||||
// skip if the package has been removed meanwhile if it it does no longer match what's in the database
|
||||
if (!existingPackage || !existingPackage->canDepsAndProvidesFromOtherPackage(package.info)) {
|
||||
continue;
|
||||
if (!existingPackage) {
|
||||
continue; // the package has been removed while we were loading package contents
|
||||
}
|
||||
// add the dependencies/provides to the existing package
|
||||
updater.beginUpdate(packageID, existingPackage);
|
||||
existingPackage->addDepsAndProvidesFromOtherPackage(package.info, true);
|
||||
if (!existingPackage->addDepsAndProvidesFromOtherPackage(package.info)) {
|
||||
continue; // the package does no longer match what's in the database
|
||||
}
|
||||
// update timestamp so we can skip this package on the next run
|
||||
if (existingPackage->timestamp < package.lastModified) {
|
||||
existingPackage->timestamp = package.lastModified;
|
||||
}
|
||||
// add the new dependencies on database-level
|
||||
updater.endUpdate(packageID, existingPackage);
|
||||
updater.update(existingPackage);
|
||||
++counter;
|
||||
}
|
||||
updater.commit();
|
||||
|
|
|
@ -337,7 +337,7 @@ void MovePackages::run()
|
|||
});
|
||||
|
||||
// remove package from database file of source repo
|
||||
m_setup.locks.acquireToWrite(m_buildAction->log(), std::move(m_sourceDatabaseLockName),
|
||||
m_setup.locks.acquireToWrite(m_buildAction->log(), std::move(m_destinationDatabaseLockName),
|
||||
[this, buildAction = m_buildAction,
|
||||
repoRemoveProcess = m_buildAction->makeBuildProcess("repo-remove", m_workingDirectory + "/repo-remove.log",
|
||||
std::bind(&MovePackages::handleRepoRemoveResult, this, processSession, std::placeholders::_1, std::placeholders::_2))](
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#ifndef LIBREPOMGR_GLOBAL
|
||||
#define LIBREPOMGR_GLOBAL
|
||||
|
||||
#include "librepomgr-definitions.h"
|
||||
#include <c++utilities/application/global.h>
|
||||
|
||||
#ifdef LIBREPOMGR_STATIC
|
||||
|
|
|
@ -27,8 +27,8 @@ VCSCLIENTS=('bzr::bzr'
|
|||
'hg::mercurial'
|
||||
'svn::subversion')
|
||||
|
||||
MARTCHUS_GIT_URL_PREFIX='git+https://martchus.dyn.f3l.de/gitea/Martchus/'
|
||||
MARTCHUS_GIT_URL_PREFIX_PRIVATE='git+ssh://gitea@martchus.dyn.f3l.de/Martchus'
|
||||
MARTCHUS_GIT_URL_PREFIX='git+https://martchus.no-ip.biz/gitea/Martchus/'
|
||||
MARTCHUS_GIT_URL_PREFIX_PRIVATE='git+ssh://gitea@martchus.no-ip.biz/Martchus'
|
||||
|
||||
#########################################################################
|
||||
# ARCHITECTURE, COMPILE FLAGS
|
||||
|
|
|
@ -314,7 +314,6 @@ void BuildActionsTests::testParsingInfoFromPkgFiles()
|
|||
auto &fooDb = config.databases[0];
|
||||
auto &barDb = config.databases[1];
|
||||
const auto harfbuzz = LibPkg::Package::fromPkgFileName("mingw-w64-harfbuzz-1.4.2-1-any.pkg.tar.xz");
|
||||
harfbuzz->libprovides = { "harfbuzzlibrary.so" };
|
||||
const auto harfbuzzID = fooDb.updatePackage(harfbuzz);
|
||||
const auto syncthingtray = LibPkg::Package::fromPkgFileName("syncthingtray-0.6.2-1-x86_64.pkg.tar.xz");
|
||||
const auto syncthingtrayID = fooDb.updatePackage(syncthingtray);
|
||||
|
@ -323,14 +322,6 @@ void BuildActionsTests::testParsingInfoFromPkgFiles()
|
|||
barDb.updatePackage(cmake);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("origin", LibPkg::PackageOrigin::PackageFileName, cmake->origin);
|
||||
barDb.localPkgDir = directory(testFilePath("repo/bar/cmake-3.8.2-1-x86_64.pkg.tar.xz"));
|
||||
auto harfbuzzLibraryPresent = false;
|
||||
fooDb.providingPackages("harfbuzzlibrary.so", false, [&](LibPkg::StorageID id, const std::shared_ptr<LibPkg::Package> &package) {
|
||||
CPPUNIT_ASSERT_EQUAL(harfbuzzID, id);
|
||||
CPPUNIT_ASSERT_EQUAL(harfbuzz->name, package->name);
|
||||
harfbuzzLibraryPresent = true;
|
||||
return true;
|
||||
});
|
||||
CPPUNIT_ASSERT_MESSAGE("harfbuzz found via \"harfbuzzlibrary.so\" before reload", harfbuzzLibraryPresent);
|
||||
|
||||
auto buildAction = std::make_shared<BuildAction>(0, &m_setup);
|
||||
auto reloadLibDependencies = ReloadLibraryDependencies(m_setup, buildAction);
|
||||
|
@ -354,11 +345,6 @@ void BuildActionsTests::testParsingInfoFromPkgFiles()
|
|||
CPPUNIT_ASSERT_EQUAL(1_st, pkgsProvidingLibSyncthingConnector.size());
|
||||
CPPUNIT_ASSERT_EQUAL(syncthingtray->name, pkgsProvidingLibSyncthingConnector.front().pkg->name);
|
||||
CPPUNIT_ASSERT_EQUAL(syncthingtrayID, pkgsProvidingLibSyncthingConnector.front().id);
|
||||
|
||||
fooDb.providingPackages("harfbuzzlibrary.so", false, [&](LibPkg::StorageID, const std::shared_ptr<LibPkg::Package> &) {
|
||||
CPPUNIT_FAIL("harfbuzz still found via \"harfbuzzlibrary.so\" after reload");
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -585,7 +571,7 @@ void BuildActionsTests::testConductingBuild()
|
|||
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
||||
"no staging needed: updpkgsums log", "fake updatepkgsums: \n"s, readFile("building/build-data/conduct-build-test/boost/pkg/updpkgsums.log"));
|
||||
TESTUTILS_ASSERT_LIKE("no staging needed: build log",
|
||||
"fake makechrootpkg: -c -u -Y .*building/test-cache-dir/x86_64 -r .*chroot-dir/arch-x86_64 -l buildservice --\n"s,
|
||||
"fake makechrootpkg: -c -u -C .*building/test-cache-dir/x86_64 -r .*chroot-dir/arch-x86_64 -l buildservice --\n"s,
|
||||
readFile("building/build-data/conduct-build-test/boost/pkg/build.log"));
|
||||
TESTUTILS_ASSERT_LIKE("no staging needed: repo-add log",
|
||||
"fake repo-add: boost.db.tar.zst boost(-libs)?-1\\.73\\.0-1-x86_64.pkg.tar.zst boost(-libs)?-1\\.73\\.0-1-x86_64.pkg.tar.zst\n"s,
|
||||
|
|
|
@ -13,6 +13,9 @@ set(META_PROJECT_VARNAME REPO_CLEAN)
|
|||
set(META_APP_NAME "Package finder")
|
||||
set(META_APP_AUTHOR "Martchus")
|
||||
set(META_APP_DESCRIPTION "Tool to find the package containing a certain file")
|
||||
set(META_VERSION_MAJOR 0)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 1)
|
||||
|
||||
# find c++utilities
|
||||
set(CONFIGURATION_PACKAGE_SUFFIX
|
||||
|
|
|
@ -13,6 +13,9 @@ set(META_PROJECT_VARNAME REPO_CLEAN)
|
|||
set(META_APP_NAME "Package parser")
|
||||
set(META_APP_AUTHOR "Martchus")
|
||||
set(META_APP_DESCRIPTION "Tool to parse an Arch Linux package printing the results as JSON")
|
||||
set(META_VERSION_MAJOR 0)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 1)
|
||||
|
||||
# find c++utilities
|
||||
set(CONFIGURATION_PACKAGE_SUFFIX
|
||||
|
|
|
@ -20,10 +20,10 @@ set(JAVA_SCRIPT_FILES
|
|||
static/js/terminal.js
|
||||
static/js/utils.js
|
||||
static/js/main.js
|
||||
static/node_modules/@xterm/xterm/lib/xterm.js
|
||||
static/node_modules/@xterm/addon-search/lib/addon-search.js)
|
||||
static/node_modules/xterm/lib/xterm.js
|
||||
static/node_modules/xterm-addon-search/lib/xterm-addon-search.js)
|
||||
set(CSS_FILES static/css/basics.css static/css/genericrendering.css static/css/layout.css static/css/log.css
|
||||
static/css/specifics.css static/node_modules/@xterm/xterm/css/xterm.css)
|
||||
static/css/specifics.css static/node_modules/xterm/css/xterm.css)
|
||||
set(IMG_FILES
|
||||
static/img/favicon.svg
|
||||
static/img/logo.svg
|
||||
|
@ -61,6 +61,9 @@ set(META_APP_NAME "Repo manager and package builder for Arch Linux")
|
|||
set(META_APP_AUTHOR "Martchus")
|
||||
set(META_APP_DESCRIPTION
|
||||
"Daemon and web application for building Arch Linux packages and managing custom Arch Linux repositories")
|
||||
set(META_VERSION_MAJOR 0)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 1)
|
||||
|
||||
# include CMake modules from own project directory
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" "${CMAKE_MODULE_PATH}")
|
||||
|
|
|
@ -10,5 +10,5 @@ location /buildservice/api/ {
|
|||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
location ~ ^(?!/buildservice/api/)/buildservice/(.*)$ {
|
||||
alias /run/media/devel/projects/c++/cmake/auto-makepkg/srv/static/$1;
|
||||
alias /run/media/devel/projects/c++/cmake/auto-makepkg/buildservice/static/$1;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#package-search-db {
|
||||
height: 100px !important;
|
||||
}
|
||||
#package-search-form table input[type="text"], input[type="search"], #package-search-form table select {
|
||||
#package-search-form table input[type="text"], #package-search-form table select {
|
||||
width: 100%;
|
||||
}
|
||||
#package-search-form table td, #package-search-form table th {
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<link rel="icon" href="img/favicon.svg" type="image/svg+xml" />
|
||||
<!-- include xterm.js -->
|
||||
<link rel="stylesheet" type="text/css" href="node_modules/@xterm/xterm/css/xterm.css" />
|
||||
<link rel="stylesheet" type="text/css" href="node_modules/xterm/css/xterm.css" />
|
||||
<script type="text/javascript">window.exports = {} // hack for xtermjs exports as it does not support ES6 modules yet</script>
|
||||
<script src="node_modules/@xterm/xterm/lib/xterm.js"></script>
|
||||
<script src="node_modules/@xterm/addon-search/lib/addon-search.js"></script>
|
||||
<script src="node_modules/xterm/lib/xterm.js"></script>
|
||||
<script src="node_modules/xterm-addon-search/lib/xterm-addon-search.js"></script>
|
||||
<!-- include custom styles and scripts -->
|
||||
<link rel="stylesheet" type="text/css" href="css/basics.css" />
|
||||
<link rel="stylesheet" type="text/css" href="css/layout.css" />
|
||||
|
@ -65,7 +65,7 @@
|
|||
<table class="form-row">
|
||||
<tr>
|
||||
<th>Package name:</th>
|
||||
<td><input type="search" name="name" placeholder="Package name" /></td>
|
||||
<td><input type="text" name="name" placeholder="Package name" /></td>
|
||||
<th rowspan="3">Database:</th>
|
||||
<th rowspan="3">
|
||||
<select id="package-search-db-arch-filter" class="arch-filter">
|
||||
|
@ -216,7 +216,6 @@
|
|||
</div>
|
||||
<div class="form-row">
|
||||
<label for="build-action-package-names">Package names:</label>
|
||||
<input type="button" value="Clear" style="float: right;" onclick="this.form.elements['package-names'].value = ''" />
|
||||
<br />
|
||||
<textarea name="package-names" id="build-action-package-names" style="box-sizing: border-box; width: 100%; height: 50px;"></textarea>
|
||||
</div>
|
||||
|
@ -245,8 +244,6 @@
|
|||
onchange="this.form['start-after-id'].disabled = !this.checked" />
|
||||
<label for="build-action-start-after">After</label>
|
||||
<input type="text" name="start-after-id" value="" placeholder="build action ID" disabled="disabled" />
|
||||
<input type="button" name="start-after-latest" value="After latest"
|
||||
title="Start after the first action displayed on the current page of the build actions table" />
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -38,8 +38,6 @@ export function queryRoute(method, path, callback, type)
|
|||
return window.alert('Authentication failed. Try again.');
|
||||
default:
|
||||
try {
|
||||
// avoid showing HTML code from gateway
|
||||
ajaxRequest.responseTextDisplay = ajaxRequest.status >= 500 && ajaxRequest.status < 600 ? 'internal server error' : ajaxRequest.responseText;
|
||||
return callback(this, status === 200);
|
||||
} catch (e) {
|
||||
window.alert('Unable to process server response: ' + e);
|
||||
|
@ -90,7 +88,7 @@ function makeFormQueryParameter(form)
|
|||
continue; // if we disable a form element or hide it via CSS we also don't want to submit its data
|
||||
}
|
||||
const type = formElement.type;
|
||||
if ((type === 'button') || ((type === 'checkbox' || type === 'radio') && !formElement.checked)) {
|
||||
if ((type === 'checkbox' || type === 'radio') && !formElement.checked) {
|
||||
continue;
|
||||
}
|
||||
const name = formElement.name;
|
||||
|
|
|
@ -34,17 +34,6 @@ export function initBuildActionsForm()
|
|||
handleBuildActionPresetChange();
|
||||
};
|
||||
|
||||
// allow selecting to start after the latest build action
|
||||
const buildActionsFormElements = buildActionsForm.elements;
|
||||
buildActionsFormElements['start-after-latest'].onclick = function() {
|
||||
const condElement = buildActionsFormElements['start-condition'];
|
||||
const idElement = buildActionsFormElements['start-after-id'];
|
||||
const id = document.getElementById('build-actions-list')?.getElementsByTagName('table')[0]?.tBodies[0]?.getElementsByTagName('tr')[0]?.dataset.id;
|
||||
condElement.value = 'after';
|
||||
idElement.disabled = false;
|
||||
idElement.value = id || '';
|
||||
};
|
||||
|
||||
queryBuildActions();
|
||||
handleBuildActionTypeChange();
|
||||
buildActionsForm.dataset.initialized = true;
|
||||
|
@ -261,20 +250,19 @@ function renderBuildActionActions(actionValue, buildAction, detailsTable)
|
|||
|
||||
function showBuildActions(ajaxRequest)
|
||||
{
|
||||
if (!window.globalInfo && ajaxRequest.status === 200) {
|
||||
if (!window.globalInfo) {
|
||||
window.functionsPostponedUntilGlobalInfo.push(showBuildActions.bind(this, ...arguments));
|
||||
return;
|
||||
}
|
||||
const buildActionsList = Utils.getAndEmptyElement('build-actions-list');
|
||||
if (ajaxRequest.status !== 200) {
|
||||
buildActionsList.appendChild(document.createTextNode('Unable to load build actions: ' + ajaxRequest.responseTextDisplay));
|
||||
buildActionsList.appendChild(document.createTextNode(' '));
|
||||
buildActionsList.appendChild(document.createTextNode('Unable to load build actions: ' + ajaxRequest.responseText));
|
||||
buildActionsList.appendChild(CustomRendering.renderReloadButton(queryBuildActions));
|
||||
return;
|
||||
}
|
||||
const responseJson = JSON.parse(ajaxRequest.responseText);
|
||||
if (!Array.isArray(responseJson)) {
|
||||
buildActionsList.appendChild(document.createTextNode('Unable to load build actions: response is no array '));
|
||||
buildActionsList.appendChild(document.createTextNode('Unable to load build actions: response is no array'));
|
||||
buildActionsList.appendChild(CustomRendering.renderReloadButton(queryBuildActions));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@ function handleGlobalStatusUpdate(ajaxRequest)
|
|||
{
|
||||
const globalStatus = Utils.getAndEmptyElement('global-status');
|
||||
let responseText = ajaxRequest.responseText;
|
||||
if (ajaxRequest.status === 500) {
|
||||
responseText = 'internal server error';
|
||||
}
|
||||
if (ajaxRequest.status !== 200) {
|
||||
globalStatus.appendChild(document.createTextNode('unable to load global status: ' + ajaxRequest.responseTextDisplay));
|
||||
globalStatus.appendChild(document.createTextNode(' '));
|
||||
globalStatus.appendChild(CustomRendering.renderReloadButton(queryGlobalStatus));
|
||||
globalStatus.appendChild(document.createTextNode('unable to load global status: ' + responseText));
|
||||
return;
|
||||
}
|
||||
const responseJson = JSON.parse(responseText);
|
||||
|
|
|
@ -156,7 +156,7 @@ export function showPackageDetails(ajaxRequest, row)
|
|||
const packageID = makePackageID(row);
|
||||
const packageDetailsContainer = Utils.getAndEmptyElement('package-details-container');
|
||||
if (ajaxRequest.status !== 200) {
|
||||
packageDetailsContainer.appendChild(document.createTextNode('unable query package details: ' + ajaxRequest.responseTextDisplay));
|
||||
packageDetailsContainer.appendChild(document.createTextNode('unable query package details: ' + ajaxRequest.responseText));
|
||||
return;
|
||||
}
|
||||
const responseJson = JSON.parse(ajaxRequest.responseText);
|
||||
|
|
|
@ -108,7 +108,7 @@ function showPackageSearchResults(ajaxRequest)
|
|||
{
|
||||
const packageSearchResults = Utils.getAndEmptyElement('package-search-results');
|
||||
if (ajaxRequest.status !== 200) {
|
||||
packageSearchResults.appendChild(document.createTextNode('unable search for packages: ' + ajaxRequest.responseTextDisplay));
|
||||
packageSearchResults.appendChild(document.createTextNode('unable search for packages: ' + ajaxRequest.responseText));
|
||||
return;
|
||||
}
|
||||
const responseJson = JSON.parse(ajaxRequest.responseText);
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
srv/static/node_modules/xterm-addon-search/lib/xterm-addon-search.js
generated
vendored
Normal file
2
srv/static/node_modules/xterm-addon-search/lib/xterm-addon-search.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
0
srv/static/node_modules/@xterm/xterm/LICENSE → srv/static/node_modules/xterm/LICENSE
generated
vendored
0
srv/static/node_modules/@xterm/xterm/LICENSE → srv/static/node_modules/xterm/LICENSE
generated
vendored
|
@ -140,7 +140,7 @@
|
|||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.xterm .xterm-accessibility:not(.debug),
|
||||
.xterm .xterm-accessibility,
|
||||
.xterm .xterm-message {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
@ -152,15 +152,6 @@
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
.xterm .xterm-accessibility-tree:not(.debug) *::selection {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.xterm .xterm-accessibility-tree {
|
||||
user-select: text;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.xterm .live-region {
|
||||
position: absolute;
|
||||
left: -9999px;
|
File diff suppressed because one or more lines are too long
|
@ -5,22 +5,22 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@xterm/addon-search": "^0.14.0",
|
||||
"@xterm/xterm": "^5.4.0"
|
||||
"xterm": "^5.0.0",
|
||||
"xterm-addon-search": "^0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@xterm/addon-search": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.14.0.tgz",
|
||||
"integrity": "sha512-gyKIjC1c2bqxBevPmWlMWRsHqiufUgl3HjN3OYim6YPClqNRUlTab7l8aW8i3W83XzU9q0gmAfIOe4KDmo0GfQ==",
|
||||
"node_modules/xterm": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz",
|
||||
"integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg=="
|
||||
},
|
||||
"node_modules/xterm-addon-search": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm-addon-search/-/xterm-addon-search-0.10.0.tgz",
|
||||
"integrity": "sha512-l+kjDxNDQbkniU5OUo9BHknxUEPZGM0OFpVpc2sMmrb97S0FKJVJO4wAZPJvSGVJ8ZEG6KuDyzXluvnb08t71Q==",
|
||||
"peerDependencies": {
|
||||
"@xterm/xterm": "^5.0.0"
|
||||
"xterm": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@xterm/xterm": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@xterm/addon-search": "^0.14.0",
|
||||
"@xterm/xterm": "^5.4.0"
|
||||
"xterm": "^5.0.0",
|
||||
"xterm-addon-search": "^0.10.0"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue