Porytiles
Loading...
Searching...
No Matches
project_artifact_checksum_provider.cpp
Go to the documentation of this file.
2
3#include <filesystem>
4#include <format>
5#include <fstream>
6#include <map>
7
8#include "nlohmann/json.hpp"
9
14
15namespace {
16
17std::filesystem::path checksums_file(const std::filesystem::path &project_root, const std::string &tileset_name)
18{
19 return project_root / "porytiles" / "tilesets" / tileset_name / "tileset.cache.json";
20}
21
22} // namespace
23
24namespace porytiles {
25
26std::unordered_map<ArtifactKey, std::string>
28{
29 std::unordered_map<ArtifactKey, std::string> checksums{};
30
31 for (const auto &key : keys) {
32 constexpr StreamDigest digest{};
33 // Keys are relative to project_root_, so prepend for filesystem operations
34 const auto absolute_path = project_root_ / key.key();
35 if (!std::filesystem::exists(absolute_path)) {
36 panic(std::format("expected artifact '{}' does not exist", absolute_path.string()));
37 }
38 std::ifstream stream{absolute_path};
39 const auto key_digest = digest.digest(stream);
40 checksums.emplace(key, key_digest);
41 }
42
43 return checksums;
44}
45
46std::unordered_map<ArtifactKey, std::string>
48{
49 const auto artifact_checksum_path = checksums_file(project_root_, tileset_name);
50
51 // If checksum file doesn't exist, just return nothing
52 if (!exists(artifact_checksum_path)) {
53 return {};
54 }
55
56 std::ifstream file{artifact_checksum_path};
57 nlohmann::json json_data;
58 file >> json_data;
59
60 std::unordered_map<ArtifactKey, std::string> checksums;
61 for (const auto &[key, value] : json_data.items()) {
62 const auto full_path = std::filesystem::path{key};
63 checksums.emplace(ArtifactKey{full_path}, value.get<std::string>());
64 }
65
66 return checksums;
67}
68
70 const std::string &tileset_name, const std::unordered_map<ArtifactKey, std::string> &checksums) const
71{
72 const auto artifact_checksum_file = checksums_file(project_root_, tileset_name);
73 std::filesystem::create_directories(artifact_checksum_file.parent_path());
74 std::ofstream file{artifact_checksum_file};
75
76 // Collect all keys with their checksums in sorted order for consistent JSON output
77 std::map<std::string, std::string> sorted_checksums;
78 for (const auto &[artifact_key, checksum] : checksums) {
79 // Keys are already relative to project_root_, so use them directly
80 sorted_checksums[artifact_key.key()] = checksum;
81 }
82
83 /*
84 * Technically, the above sorting step is unnecessary, since by default the nlohmann json library automatically
85 * sorts json keys alphabetically (the underlying implementation uses std::map). However, we explicitly sort them
86 * here in case this implementation ever changes, or we change json libraries.
87 *
88 * https://json.nlohmann.me/features/object_order/#default-behavior-sort-keys
89 */
90
91 // Now build JSON from the sorted map, ensuring consistent ordering
92 nlohmann::json json_data;
93 for (const auto &[path, checksum] : sorted_checksums) {
94 json_data[path] = checksum;
95 }
96
97 // prettify the json with 2-space indentation
98 file << json_data.dump(2);
99 file << std::endl;
100 return {};
101}
102
103} // namespace porytiles
A type-safe wrapper for artifact keys.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
std::unordered_map< ArtifactKey, std::string > load_cached_tileset_checksums(const std::string &tileset_name) const override
Loads the cached checksums for the given Tileset.
ChainableResult< void > cache_tileset_checksums(const std::string &tileset_name, const std::unordered_map< ArtifactKey, std::string > &checksums) const override
Caches checksums for the given Tileset to persistent storage.
std::unordered_map< ArtifactKey, std::string > compute_tileset_artifact_checksums(const std::vector< ArtifactKey > &keys) const override
Computes checksums for the given Tileset artifacts.
Computes the MD5 digest of an input stream.
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.
Definition panic.cpp:43