Move repo interaction into separate source file
Dependencies
- [2]
7YS2X7JJFix compilation against older Nix versions (tested with 2.13.6) - [3]
SVCRRNQ6Remove unnecessary version checks - [4]
3KEFKH5FImport existing code - [5]
U5AKEHEQFix build for Nix 2.19 to 2.21
Change contents
- file addition: repo.h[3.15]
#ifndef NIX_PLUGIN_PIJUL_REPO_H#define NIX_PLUGIN_PIJUL_REPO_H#include <optional>#include <date/date.h>#include <types.hh>namespace nixpluginpijul{struct RepoStatus {std::string channel;std::string state;uint64_t lastModified;};std::string runPijul(nix::Strings args, std::optional<nix::Path> chdir = {}, std::optional<std::string> input = {}, bool isInteractive = false);RepoStatus getRepoStatus(const nix::PathView &repoPath);std::pair<std::string, uint64_t> getState(const nix::PathView &repoPath);std::string getRepoChannel(const nix::PathView &repoPath);date::sys_time<std::chrono::milliseconds> parseRFC3339(const std::string &spec);}#endif // NIX_PLUGIN_PIJUL_REPO_H - file addition: repo.cpp[3.15]
#include "repo.h"#include <types.hh>#include <util.hh>#if NIX_VERSION >= 0x021900#include <processes.hh>#endif#include <nlohmann/json.hpp>using nlohmann::json;using namespace nix;using namespace std::string_literals;using namespace std::string_view_literals;namespace nixpluginpijul{std::string runPijul(Strings args, std::optional<Path> chdir, std::optional<std::string> input, bool isInteractive){auto program = "pijul"sv;auto res = runProgram(RunOptions{.program = std::string(program),.searchPath = true,.args = std::move(args),.chdir = std::move(chdir),.input = std::move(input),.isInteractive = isInteractive,});if (!statusOk(res.first)) {throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first));}return res.second;}RepoStatus getRepoStatus(const PathView &repoPath){auto [state, lastModified] = getState(repoPath);auto channel = getRepoChannel(repoPath);return RepoStatus{.channel = std::move(channel),.state = std::move(state),.lastModified = lastModified,};}std::pair<std::string, uint64_t> getState(const PathView &repoPath){const auto &output = runPijul({"log", "--output-format", "json", "--state", "--limit", "1"}, Path(repoPath));const auto &json = json::parse(output);const auto &commitInfo = json.at(0);const auto ×tampSpec = commitInfo.at("timestamp").get<std::string>();const uint64_t timestamp = std::chrono::duration_cast<std::chrono::seconds>(parseRFC3339(timestampSpec).time_since_epoch()).count();const std::string &state = commitInfo.at("state");return {state, timestamp};}std::string getRepoChannel(const PathView &repoPath){const auto &output = runPijul({"channel"}, Path(repoPath));std::string::size_type pos = 0;do {const auto nl = output.find('\n', pos);const auto line = std::string_view(output).substr(pos, nl - pos);if (line.empty()) {continue;}if (line.at(0) == '*') {return std::string(line.substr(2));}pos = nl;} while (pos != std::string::npos);throw Error("could not parse current channel"s);}date::sys_time<std::chrono::milliseconds> parseRFC3339(const std::string &spec){std::istringstream in{spec};date::sys_time<std::chrono::milliseconds> pt;in >> date::parse("%FT%TZ", pt);if (in.fail()) {in.clear();in.exceptions(std::ios::failbit);in.str(spec);in >> date::parse("%FT%T%Ez", pt);}return pt;}} - edit in src/fetcher.cpp at line 1
#include "repo.h" - edit in src/fetcher.cpp at line 25
using nixpluginpijul::getRepoStatus;using nixpluginpijul::getState;using nixpluginpijul::RepoStatus; - edit in src/fetcher.cpp at line 34[3.331]→[3.331:332](∅→∅),[3.332]→[3.332:709](∅→∅),[2.28]→[3.709:749](∅→∅),[3.709]→[3.709:749](∅→∅),[2.36]→[3.749:915](∅→∅),[3.749]→[3.749:915](∅→∅)
std::string runPijul(Strings args, std::optional<Path> chdir = {}, std::optional<std::string> input = {}, bool isInteractive = false){auto program = "pijul"sv;auto res = runProgram(RunOptions{.program = std::string(program),.searchPath = true,.args = std::move(args),.chdir = std::move(chdir),.input = std::move(input),.isInteractive = isInteractive,});if (!statusOk(res.first)) {throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first));}return res.second;} - edit in src/fetcher.cpp at line 211
struct RepoStatus {std::string channel;std::string state;uint64_t lastModified;}; - edit in src/fetcher.cpp at line 436[3.10847]→[3.10847:11185](∅→∅),[3.11185]→[3.11185:11191](∅→∅),[3.11191]→[3.11191:11827](∅→∅),[3.11827]→[3.11827:11894](∅→∅),[3.11894]→[3.11894:11900](∅→∅),[3.11900]→[3.11900:11961](∅→∅),[3.11961]→[3.11961:12099](∅→∅),[3.12099]→[3.12099:12814](∅→∅)
static RepoStatus getRepoStatus(const PathView &repoPath){auto [state, lastModified] = getState(repoPath);auto channel = getRepoChannel(repoPath);return RepoStatus{.channel = std::move(channel),.state = std::move(state),.lastModified = lastModified,};}static std::pair<std::string, uint64_t> getState(const PathView &repoPath){const auto &output = runPijul({"log", "--output-format", "json", "--state", "--limit", "1"}, Path(repoPath));const auto &json = nlohmann::json::parse(output);const auto &commitInfo = json.at(0);const auto ×tampSpec = commitInfo.at("timestamp").get<std::string>();const uint64_t timestamp = std::chrono::duration_cast<std::chrono::seconds>(parseRFC3339(timestampSpec).time_since_epoch()).count();const std::string &state = commitInfo.at("state");return {state, timestamp};}static date::sys_seconds parseRFC3339(const std::string &spec){std::istringstream in;date::sys_seconds pt;in >> date::parse("%FT%TZ", pt);if (in.fail()) {in.clear();in.exceptions(std::ios::failbit);in >> date::parse("%FT%T%Ez", pt);}return pt;}static std::string getRepoChannel(const PathView &repoPath){const auto &output = runPijul({"channel"}, Path(repoPath));std::string::size_type pos = 0;do {const auto nl = output.find('\n', pos);const auto line = std::string_view(output).substr(pos, nl - pos);if (line.empty()) {continue;}if (line.at(0) == '*') {return std::string(line.substr(2));}pos = nl;} while (pos != std::string::npos);throw Error("could not parse current channel"s);} - replacement in src/CMakeLists.txt at line 4
fetcher.cpp)fetcher.cpprepo.cpprepo.h)