Wrapper: fix cache.nixos.org-1 key; drop AppImage; pin publish to mozart/cargoxx-pkgs.
284 lines
9.0 KiB
C++
284 lines
9.0 KiB
C++
module;
|
|
|
|
#include <toml.hpp>
|
|
|
|
module cargoxx.lockfile;
|
|
|
|
import std;
|
|
import cargoxx.util;
|
|
|
|
namespace cargoxx::lockfile {
|
|
|
|
auto Lockfile::nixpkgs_rev() const -> std::optional<std::string> {
|
|
for (const auto& p : packages) {
|
|
if (p.nixpkgs_rev && !p.nixpkgs_rev->empty()) {
|
|
return p.nixpkgs_rev;
|
|
}
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
namespace {
|
|
|
|
using util::Error;
|
|
using util::ErrorCode;
|
|
|
|
auto err(ErrorCode code, std::string msg, std::filesystem::path path) -> Error {
|
|
return Error{code, std::move(msg), "", std::move(path), std::nullopt};
|
|
}
|
|
|
|
auto extract_string_array(const toml::array& arr, std::string_view field,
|
|
const std::filesystem::path& path)
|
|
-> util::Result<std::vector<std::string>> {
|
|
std::vector<std::string> out;
|
|
out.reserve(arr.size());
|
|
for (const auto& el : arr) {
|
|
if (auto s = el.value<std::string>()) {
|
|
out.push_back(*s);
|
|
} else {
|
|
return std::unexpected(err(ErrorCode::ManifestInvalidField,
|
|
std::format("'{}' must be an array of strings", field),
|
|
path));
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
auto parse_package(const toml::table& tbl, const std::filesystem::path& path)
|
|
-> util::Result<LockfilePackage> {
|
|
LockfilePackage pkg;
|
|
|
|
if (auto v = tbl["name"].value<std::string>()) {
|
|
pkg.name = *v;
|
|
} else {
|
|
return std::unexpected(
|
|
err(ErrorCode::ManifestInvalidField, "lockfile package missing 'name'", path));
|
|
}
|
|
|
|
if (auto v = tbl["version"].value<std::string>()) {
|
|
pkg.version = *v;
|
|
} else {
|
|
return std::unexpected(
|
|
err(ErrorCode::ManifestInvalidField, "lockfile package missing 'version'", path));
|
|
}
|
|
|
|
if (const auto* deps = tbl["dependencies"].as_array()) {
|
|
auto r = extract_string_array(*deps, "dependencies", path);
|
|
if (!r) {
|
|
return std::unexpected(r.error());
|
|
}
|
|
pkg.dependencies = std::move(*r);
|
|
}
|
|
|
|
if (auto v = tbl["nixpkgs_attr"].value<std::string>()) {
|
|
pkg.nixpkgs_attr = *v;
|
|
}
|
|
if (auto v = tbl["nixpkgs_rev"].value<std::string>()) {
|
|
pkg.nixpkgs_rev = *v;
|
|
}
|
|
if (auto v = tbl["cargoxx_pkgs_attr"].value<std::string>()) {
|
|
pkg.cargoxx_pkgs_attr = *v;
|
|
}
|
|
if (auto v = tbl["cargoxx_pkgs_rev"].value<std::string>()) {
|
|
pkg.cargoxx_pkgs_rev = *v;
|
|
}
|
|
if (auto v = tbl["linkdb_source"].value<std::string>()) {
|
|
pkg.linkdb_source = *v;
|
|
}
|
|
if (auto v = tbl["find_package"].value<std::string>()) {
|
|
pkg.find_package = *v;
|
|
}
|
|
if (const auto* arr = tbl["targets"].as_array()) {
|
|
auto r = extract_string_array(*arr, "targets", path);
|
|
if (!r) {
|
|
return std::unexpected(r.error());
|
|
}
|
|
pkg.targets = std::move(*r);
|
|
}
|
|
if (auto v = tbl["pkg_config_module"].value<std::string>()) {
|
|
pkg.pkg_config_module = *v;
|
|
}
|
|
if (const auto* arr = tbl["brute_force_libs"].as_array()) {
|
|
auto r = extract_string_array(*arr, "brute_force_libs", path);
|
|
if (!r) {
|
|
return std::unexpected(r.error());
|
|
}
|
|
pkg.brute_force_libs = std::move(*r);
|
|
}
|
|
if (const auto* arr = tbl["brute_force_includes"].as_array()) {
|
|
auto r = extract_string_array(*arr, "brute_force_includes", path);
|
|
if (!r) {
|
|
return std::unexpected(r.error());
|
|
}
|
|
pkg.brute_force_includes = std::move(*r);
|
|
}
|
|
if (auto v = tbl["source_kind"].value<std::string>()) {
|
|
pkg.source_kind = *v;
|
|
}
|
|
if (auto v = tbl["source_path"].value<std::string>()) {
|
|
pkg.source_path = *v;
|
|
}
|
|
if (auto v = tbl["source_git_url"].value<std::string>()) {
|
|
pkg.source_git_url = *v;
|
|
}
|
|
if (auto v = tbl["source_git_commit"].value<std::string>()) {
|
|
pkg.source_git_commit = *v;
|
|
}
|
|
if (auto v = tbl["source_git_sha256"].value<std::string>()) {
|
|
pkg.source_git_sha256 = *v;
|
|
}
|
|
|
|
return pkg;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
auto parse(const std::filesystem::path& path) -> util::Result<Lockfile> {
|
|
std::error_code ec;
|
|
if (!std::filesystem::exists(path, ec) || ec) {
|
|
return std::unexpected(err(ErrorCode::ManifestNotFound,
|
|
std::format("lockfile not found: {}", path.string()), path));
|
|
}
|
|
|
|
toml::table root;
|
|
try {
|
|
root = toml::parse_file(path.string());
|
|
} catch (const toml::parse_error& e) {
|
|
return std::unexpected(err(ErrorCode::ManifestParseError,
|
|
std::format("toml parse error: {}", e.description()), path));
|
|
}
|
|
|
|
Lockfile lock;
|
|
if (auto v = root["version"].value<int>()) {
|
|
lock.version = *v;
|
|
}
|
|
if (auto v = root["nixpkgs_rev"].value<std::string>()) {
|
|
lock.nixpkgs_rev_pin = *v;
|
|
}
|
|
if (auto v = root["flake_utils_rev"].value<std::string>()) {
|
|
lock.flake_utils_rev_pin = *v;
|
|
}
|
|
|
|
if (const auto* arr = root["package"].as_array()) {
|
|
lock.packages.reserve(arr->size());
|
|
for (const auto& el : *arr) {
|
|
const auto* tbl = el.as_table();
|
|
if (!tbl) {
|
|
return std::unexpected(err(ErrorCode::ManifestInvalidField,
|
|
"[[package]] entries must be tables", path));
|
|
}
|
|
auto p = parse_package(*tbl, path);
|
|
if (!p) {
|
|
return std::unexpected(p.error());
|
|
}
|
|
lock.packages.push_back(std::move(*p));
|
|
}
|
|
}
|
|
|
|
return lock;
|
|
}
|
|
|
|
auto write(const Lockfile& lock, const std::filesystem::path& path) -> util::Result<void> {
|
|
toml::table root;
|
|
root.insert_or_assign("version", lock.version);
|
|
if (lock.nixpkgs_rev_pin) {
|
|
root.insert_or_assign("nixpkgs_rev", *lock.nixpkgs_rev_pin);
|
|
}
|
|
if (lock.flake_utils_rev_pin) {
|
|
root.insert_or_assign("flake_utils_rev", *lock.flake_utils_rev_pin);
|
|
}
|
|
|
|
toml::array packages;
|
|
for (const auto& p : lock.packages) {
|
|
toml::table tbl;
|
|
tbl.insert_or_assign("name", p.name);
|
|
tbl.insert_or_assign("version", p.version);
|
|
if (!p.dependencies.empty()) {
|
|
toml::array deps;
|
|
for (const auto& d : p.dependencies) {
|
|
deps.push_back(d);
|
|
}
|
|
tbl.insert_or_assign("dependencies", std::move(deps));
|
|
}
|
|
if (p.nixpkgs_attr) {
|
|
tbl.insert_or_assign("nixpkgs_attr", *p.nixpkgs_attr);
|
|
}
|
|
if (p.nixpkgs_rev) {
|
|
tbl.insert_or_assign("nixpkgs_rev", *p.nixpkgs_rev);
|
|
}
|
|
if (p.cargoxx_pkgs_attr) {
|
|
tbl.insert_or_assign("cargoxx_pkgs_attr", *p.cargoxx_pkgs_attr);
|
|
}
|
|
if (p.cargoxx_pkgs_rev) {
|
|
tbl.insert_or_assign("cargoxx_pkgs_rev", *p.cargoxx_pkgs_rev);
|
|
}
|
|
if (p.linkdb_source) {
|
|
tbl.insert_or_assign("linkdb_source", *p.linkdb_source);
|
|
}
|
|
if (p.find_package) {
|
|
tbl.insert_or_assign("find_package", *p.find_package);
|
|
}
|
|
if (!p.targets.empty()) {
|
|
toml::array arr;
|
|
for (const auto& t : p.targets) {
|
|
arr.push_back(t);
|
|
}
|
|
tbl.insert_or_assign("targets", std::move(arr));
|
|
}
|
|
if (p.pkg_config_module) {
|
|
tbl.insert_or_assign("pkg_config_module", *p.pkg_config_module);
|
|
}
|
|
if (!p.brute_force_libs.empty()) {
|
|
toml::array arr;
|
|
for (const auto& l : p.brute_force_libs) {
|
|
arr.push_back(l);
|
|
}
|
|
tbl.insert_or_assign("brute_force_libs", std::move(arr));
|
|
}
|
|
if (!p.brute_force_includes.empty()) {
|
|
toml::array arr;
|
|
for (const auto& i : p.brute_force_includes) {
|
|
arr.push_back(i);
|
|
}
|
|
tbl.insert_or_assign("brute_force_includes", std::move(arr));
|
|
}
|
|
if (p.source_kind) {
|
|
tbl.insert_or_assign("source_kind", *p.source_kind);
|
|
}
|
|
if (p.source_path) {
|
|
tbl.insert_or_assign("source_path", *p.source_path);
|
|
}
|
|
if (p.source_git_url) {
|
|
tbl.insert_or_assign("source_git_url", *p.source_git_url);
|
|
}
|
|
if (p.source_git_commit) {
|
|
tbl.insert_or_assign("source_git_commit", *p.source_git_commit);
|
|
}
|
|
if (p.source_git_sha256) {
|
|
tbl.insert_or_assign("source_git_sha256", *p.source_git_sha256);
|
|
}
|
|
packages.push_back(std::move(tbl));
|
|
}
|
|
root.insert_or_assign("package", std::move(packages));
|
|
|
|
std::ofstream out{path};
|
|
if (!out) {
|
|
return std::unexpected(util::Error{
|
|
util::ErrorCode::Internal,
|
|
std::format("cannot open lockfile for writing: {}", path.string()),
|
|
"", path, std::nullopt,
|
|
});
|
|
}
|
|
out << root << '\n';
|
|
if (!out) {
|
|
return std::unexpected(util::Error{
|
|
util::ErrorCode::Internal,
|
|
std::format("write failed: {}", path.string()),
|
|
"", path, std::nullopt,
|
|
});
|
|
}
|
|
return {};
|
|
}
|
|
|
|
} // namespace cargoxx::lockfile
|