Porytiles
Loading...
Searching...
No Matches
project_artifact_checksum_provider.cpp
Go to the documentation of this file.
2
3#include <filesystem>
4#include <fstream>
5#include <map>
6
7#include "fmt/format.h"
8#include "nlohmann/json.hpp"
9
13
14namespace porytiles2 {
15
16std::unordered_map<ArtifactKey, std::string>
18{
19 std::unordered_map<ArtifactKey, std::string> checksums{};
20
21 for (const auto &all_keys = key_provider_->get_all_artifact_keys(tileset_name); const auto &key : all_keys) {
22 const StreamDigest digest{};
23 if (!key_provider_->artifact_exists(key)) {
24 panic(fmt::format("expected artifact '{}' does not exist", key.key()));
25 }
26 std::ifstream stream{key.key()};
27 const auto key_digest = digest.digest(stream);
28 checksums.emplace(key, key_digest);
29 }
30
31 return checksums;
32}
33
34std::unordered_map<ArtifactKey, std::string>
36{
37 // TODO: tileset checksum file location should be configurable?
38 const auto artifact_checksum_file = key_provider_->tileset_root(tileset_name) / "artifact_checksums.json";
39
40 // If checksum file doesn't exist, create it
41 if (!exists(artifact_checksum_file)) {
42 const auto new_checksums = compute_tileset_artifact_checksums(tileset_name);
43 if (const auto result = cache_tileset_checksums(tileset_name, new_checksums); !result) {
44 panic(fmt::format("failed to initialize checksum cache for '{}'", tileset_name));
45 }
46 }
47
48 std::ifstream file{artifact_checksum_file};
49 nlohmann::json json_data;
50 file >> json_data;
51
52 std::unordered_map<ArtifactKey, std::string> checksums;
53 for (const auto &[key, value] : json_data.items()) {
54 const auto full_path = key_provider_->tileset_root(tileset_name) / std::filesystem::path{key};
55 checksums.emplace(ArtifactKey{full_path}, value.get<std::string>());
56 }
57
58 return checksums;
59}
60
62 const std::string &tileset_name, const std::unordered_map<ArtifactKey, std::string> &checksums) const
63{
64 // TODO: tileset checksum file location should be configurable?
65 const auto artifact_checksum_file = key_provider_->tileset_root(tileset_name) / "artifact_checksums.json";
66 std::ofstream file{artifact_checksum_file};
67
68 // First, collect all relative paths with their checksums
69 std::map<std::string, std::string> sorted_checksums;
70 for (const auto &[artifact_key, checksum] : checksums) {
71 /*
72 * Before saving the checksums, relativize the key's path against the tileset root. Since the user might call
73 * the command from different working directories, it shouldn't save the path relative to the working directory.
74 * It also doesn't really make sense to save an absolute path here, since users might rename the tileset or move
75 * their project folder.
76 */
77 const auto relative_key =
78 std::filesystem::relative(artifact_key.key(), key_provider_->tileset_root(tileset_name));
79 sorted_checksums[relative_key] = checksum;
80 }
81
82 /*
83 * Technically, the above sorting step is unnecessary, since by default the nlohmann json library automatically
84 * sorts json keys alphabetically (the underlying implementation uses std::map). However, we explicitly sort them
85 * here in case this implementation ever changes, or we change json libraries.
86 *
87 * https://json.nlohmann.me/features/object_order/#default-behavior-sort-keys
88 */
89
90 // Now build JSON from the sorted map, ensuring consistent ordering
91 nlohmann::json json_data;
92 for (const auto &[path, checksum] : sorted_checksums) {
93 json_data[path] = checksum;
94 }
95
96 // prettify the json with 2-space indentation
97 file << json_data.dump(2);
98 return {};
99}
100
101} // namespace porytiles2
A type-safe wrapper for artifact keys.
Result< 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::string &tileset_name) const override
Computes checksums for the artifacts that belong to the given Tileset.
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.
std::filesystem::path tileset_root(const std::string &tileset_name) const
Returns the filesystem path to the root directory of a tileset.
bool artifact_exists(const ArtifactKey &key) const override
Checks whether an artifact exists in the backing store for the given key.
Computes the MD5 digest of an input stream.
virtual std::vector< ArtifactKey > get_all_artifact_keys(const std::string &tileset_name) const
Gets the keys for all tileset artifacts (both Porytiles and Porymap) present in the given Tileset.
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.
Definition panic.hpp:53
std::expected< T, E > Result
A result with some type T on success, otherwise an error of type E.
Definition result.hpp:25