Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync improvements #37

Merged
merged 10 commits into from
May 25, 2024
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ conan_cmake_run(CONANFILE conanfile.txt

add_subdirectory(daemon)
add_subdirectory(frontend)
add_subdirectory(dbcli)
1 change: 1 addition & 0 deletions conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ c-ares/1.19.1
scnlib/1.1.2
cereal/1.3.2
libcoro/0.11.1
scope-lite/0.2.0

[generators]
cmake
Expand Down
30 changes: 28 additions & 2 deletions daemon/core/application/services/SyncService.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,43 @@
#pragma once

#include "core/application/dtos/PackageSectionDTO.h"
#include "utilities/Error.h"
#include "utilities/errors/Macro.h"

#include <coro/task.hpp>
#include <frozen/string.h>
#include <frozen/unordered_map.h>

namespace bxt::Core::Application {

class SyncService {
public:
struct SyncError : public bxt::Error {
enum Type {
NetworkError,
IOError,
ParseError,
RepositoryError,
ValidationError
};
Type error_type;

SyncError(Type type) : error_type(type) {
message = type_messages.at(type).data();
}

static constexpr frozen::unordered_map<Type, frozen::string, 5>
type_messages {{NetworkError, "Network error occurred"},
{IOError, "Input/output error occurred"},
{ParseError, "Parsing error occurred"},
{RepositoryError, "Repository error occurred"},
{ValidationError, "Validation error occurred"}};
};
BXT_DECLARE_RESULT(SyncError)
virtual ~SyncService() = default;

virtual coro::task<void> sync(const PackageSectionDTO section) = 0;
virtual coro::task<void> sync_all() = 0;
virtual coro::task<Result<void>> sync(const PackageSectionDTO section) = 0;
virtual coro::task<Result<void>> sync_all() = 0;
};

} // namespace bxt::Core::Application
6 changes: 6 additions & 0 deletions daemon/core/domain/entities/Package.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "fmt/core.h"
#include "scn/tuple_return/tuple_return.h"
#include "utilities/Error.h"
#include "utilities/alpmdb/Desc.h"

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
Expand Down Expand Up @@ -69,6 +70,11 @@ Package::Result<Package> Package::from_file_path(

if (!name.has_value()) { return bxt::make_error<ParseError>(); }

auto desc = bxt::Utilities::AlpmDb::Desc::parse_package(filepath, false);
if (!desc.has_value()) {
return bxt::make_error_with_source<ParseError>(std::move(desc.error()));
}

Package result(section, *name, false);
result.pool_entries().emplace(location, *pool_entry);
return result;
Expand Down
68 changes: 30 additions & 38 deletions daemon/core/domain/value_objects/PackageVersion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
*/
#include "PackageVersion.h"

#include "core/domain/entities/Package.h"
#include "scn/tuple_return/tuple_return.h"
#include "utilities/Error.h"

#include <optional>
#include <scn/scn.h>
#include <scn/tuple_return.h>
Expand Down Expand Up @@ -114,15 +110,13 @@ std::strong_ordering PackageVersion::compare(const PackageVersion& lh,
const PackageVersion& rh) {
std::strong_ordering ret = std::strong_ordering::equal;

if (!(lh.epoch || rh.epoch)) {
ret = rpmvercmp(std::to_string(*lh.epoch), std::to_string(*rh.epoch));
}
ret = rpmvercmp(std::string(lh.epoch), std::string(rh.epoch));

if (ret == 0) {
ret = rpmvercmp(lh.version, rh.version);
if (ret == std::strong_ordering::equal) {
ret = rpmvercmp(std::string(lh.version), std::string(rh.version));

if (ret == 0 && lh.release.length() > 0 && rh.release.length() > 0) {
ret = rpmvercmp(lh.release, rh.release);
if (ret == std::strong_ordering::equal && lh.release && rh.release) {
ret = rpmvercmp(std::string(*lh.release), std::string(*rh.release));
}
}

Expand All @@ -131,46 +125,44 @@ std::strong_ordering PackageVersion::compare(const PackageVersion& lh,

PackageVersion::ParseResult
PackageVersion::from_string(std::string_view version_str) {
auto [scan_ok, version, epoch_int, release] =
scn::scan_tuple<std::string, int, std::string>(
version_str, "{:[:alnum:.]}\:{}-{:[:alnum:.]}");
std::optional<int> epoch = std::nullopt;

if (!scan_ok) {
if (!scn::scan(version_str, "{:[:alnum:.]}-{}", version, release)) {
return bxt::make_error<ParsingError>(
ParsingError::ErrorCode::InvalidFormat);
}
std::string epoch;
std::string version;
std::optional<std::string> release;
size_t pos = 0;

size_t epoch_end = version_str.find(':');
if (epoch_end != std::string::npos) {
epoch = version_str.substr(0, epoch_end);
pos = epoch_end + 1;
} else {
epoch = epoch_int;
}

static constexpr auto version_validator = [](const char& ch) {
return std::isalnum(ch) || ch == '.';
};

if (!std::ranges::all_of(version, version_validator)) {
return bxt::make_error<ParsingError>(
ParsingError::ErrorCode::InvalidVersion);
epoch = "0";
}

if (!std::ranges::all_of(release, version_validator)) {
size_t release_start = version_str.rfind('-');
if (release_start != std::string::npos && release_start > pos) {
version = version_str.substr(pos, release_start - pos);
release = version_str.substr(release_start + 1);
} else if (pos < version_str.length()) {
version = version_str.substr(pos);
release = std::nullopt;
} else {
return bxt::make_error<ParsingError>(
ParsingError::ErrorCode::InvalidReleaseTag);
ParsingError::ErrorCode::InvalidFormat);
}

return PackageVersion {version, epoch, release};
return PackageVersion {
.version = version, .epoch = epoch, .release = release};
}

std::string PackageVersion::string() const {
std::string format = "{1}";

if (epoch) { format = "{0}:" + format; }
if (std::string(epoch) != "0") { format = "{0}:" + format; }

if (release.length() > 0) { format = format + "-{2}"; }
if (release) { format = format + "-{2}"; }

return fmt::format(fmt::runtime(format), epoch.value_or(0),
std::string(version), release);
return fmt::format(fmt::runtime(format), std::string(epoch),
std::string(version), release.value_or(Name("0")));
}

} // namespace bxt::Core::Domain
4 changes: 2 additions & 2 deletions daemon/core/domain/value_objects/PackageVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ struct PackageVersion {
std::string string() const;

Name version;
std::optional<int> epoch = {};
std::string release;
Name epoch;
std::optional<Name> release = {};
};

} // namespace bxt::Core::Domain
16 changes: 14 additions & 2 deletions daemon/infrastructure/alpm/ArchRepoSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
*/
#pragma once

#include "utilities/repo-schema/SchemaExtension.h"

#include <filesystem>
#include <fstream>
#include <optional>
#include <parallel_hashmap/phmap.h>
#include <string>
#include <yaml-cpp/yaml.h>

namespace bxt::Infrastructure {
struct ArchRepoSource {
Expand All @@ -30,6 +31,16 @@ struct ArchRepoSource {
"repo-structure-template", result.repo_structure_template);
result.download_path = get_if_defined.operator()<std::string>(
"pool-path", result.download_path);
const auto exclude_list_path = get_if_defined.operator()<std::string>(
"exclude-list-path", "exclude_list");
std::ifstream file(exclude_list_path);
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
result.exclude_list.insert(std::move(line));
}
file.close();
}

return result;
};
Expand All @@ -38,6 +49,7 @@ struct ArchRepoSource {
std::string repo_structure_template =
"/archlinux/{repository}/os/{architecture}";
std::filesystem::path download_path = "/var/tmp/bxt/";
phmap::parallel_flat_hash_set<std::string> exclude_list;

std::optional<std::string> repo_name;
};
Expand Down
Loading