diff --git a/include/version.hpp b/include/version.hpp index 17c8de5..f0e18c9 100644 --- a/include/version.hpp +++ b/include/version.hpp @@ -1 +1 @@ -static const char *VERSION = "4"; +static const char *VERSION = "5"; diff --git a/src/generator.cpp b/src/generator.cpp index ec5bacf..32c322e 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -25,6 +25,40 @@ static uint64_t fnv1a_64(const void* data, size_t len) { return h; } +// Helper function to output the _recreate_file_ utility function +static void output_recreate_file_utility(std::ofstream& cpp) { + cpp << R"cpp( +// Utility function to recreate a file with proper permissions +static bool _recreate_file_(const std::filesystem::path& outpath, uint64_t file_hash, std::filesystem::perms file_perms, const unsigned char* filedata, size_t filedata_len) { + namespace fs = std::filesystem; + uint64_t existing_hash = 0; + if (fs::exists(outpath)) { + std::ifstream in(outpath, std::ios::binary); + std::ostringstream oss; + oss << in.rdbuf(); + std::string data = oss.str(); + existing_hash = fnv1a_64(data.data(), data.size()); + } + bool needs_write = !fs::exists(outpath) || existing_hash != file_hash; + if (needs_write) { + fs::create_directories(outpath.parent_path()); + std::ofstream out(outpath, std::ios::binary); + out.write(reinterpret_cast(filedata), filedata_len); + out.close(); + // Set the file permissions + fs::permissions(outpath, file_perms); + } + + if (!fs::exists(outpath)) { + std::cout << "[dehydrate] " << outpath.filename() << ": created\n"; + } else if (needs_write) { + std::cout << "[dehydrate] " << outpath.filename() << ": updated (hash changed)\n"; + } + return needs_write; +} +)cpp"; +} + void generate_file_code(const std::string& source, const std::string& destfolder, bool silent) { fs::path src(source); @@ -64,6 +98,10 @@ static uint64_t fnv1a_64(const void* data, size_t len) { )cpp"; cpp << "#include \"" << hppname << "\"\n"; cpp << "namespace " << ns << " {\n"; + + // Output the recreate_file utility function + output_recreate_file_utility(cpp); + // Embed file data cpp << "static const unsigned char filedata[] = {"; for (size_t i = 0; i < filedata.size(); ++i) { @@ -81,29 +119,7 @@ static uint64_t fnv1a_64(const void* data, size_t len) { bool recreate_file(std::string destination_folder) { namespace fs = std::filesystem; fs::path outpath = fs::path(destination_folder) / ")cpp" << src.filename().string() << R"cpp("; - uint64_t existing_hash; - if (fs::exists(outpath)) { - std::ifstream in(outpath, std::ios::binary); - std::ostringstream oss; - oss << in.rdbuf(); - std::string data = oss.str(); - existing_hash = fnv1a_64(data.data(), data.size()); - } - bool needs_write = !fs::exists(outpath) || existing_hash != file_hash; - if (needs_write) { - std::ofstream out(outpath, std::ios::binary); - out.write(reinterpret_cast(filedata), filedata_len); - out.close(); - // Set the file permissions - fs::permissions(outpath, file_perms); - } - - if (!fs::exists(outpath)) { - std::cout << "[dehydrate] " << outpath.filename() << ": created\n"; - } else if (needs_write) { - std::cout << "[dehydrate] " << outpath.filename() << ": updated (hash changed)\n"; - } - return needs_write; + return _recreate_file_(outpath, file_hash, file_perms, filedata, filedata_len); } )cpp"; cpp << "}\n"; @@ -190,6 +206,9 @@ static uint64_t fnv1a_64(const void* data, size_t len) { )cpp"; + // Output the recreate_file utility function + output_recreate_file_utility(cpp); + // Embed all files for (const auto& file : files) { std::ifstream in(file, std::ios::binary); @@ -216,7 +235,7 @@ static uint64_t fnv1a_64(const void* data, size_t len) { cpp << "static const char* rel_" << var << " = \"" << rel << "\";\n"; cpp << "static std::filesystem::perms perms_" << var << " = std::filesystem::perms(" << static_cast(file_perms) << ");\n"; } - // Write recreate_tree using heredoc style + // Write recreate_tree using the utility function cpp << R"cpp( bool recreate_tree(std::string destination_folder) { namespace fs = std::filesystem; @@ -227,29 +246,8 @@ bool recreate_tree(std::string destination_folder) { std::string var = sanitize(rel); cpp << R"cpp( { fs::path outpath = fs::path(destination_folder) / )cpp" << "rel_" << var << R"cpp(; - fs::create_directories(outpath.parent_path()); - uint64_t existing_hash; - if (fs::exists(outpath)) { - std::ifstream in(outpath, std::ios::binary); - std::ostringstream oss; oss << in.rdbuf(); - std::string data = oss.str(); - existing_hash = fnv1a_64(data.data(), data.size()); - } - bool needs_write = !fs::exists(outpath) || existing_hash != )cpp" << "hash_" << var << R"cpp(; - if (needs_write) { - std::ofstream out(outpath, std::ios::binary); - out.write(reinterpret_cast()cpp" << "data_" << var << R"cpp(), )cpp" << "len_" << var << R"cpp(); - out.close(); - // Set the file permissions - fs::permissions(outpath, )cpp" << "perms_" << var << R"cpp(); - } - - if (!fs::exists(outpath)) { - std::cout << "[dehydrate] " << outpath.filename() << ": created\n"; - } else if (needs_write) { - std::cout << "[dehydrate] " << outpath.filename() << ": updated (hash changed)\n"; - } - any_written = any_written || needs_write; + bool file_written = _recreate_file_(outpath, )cpp" << "hash_" << var << ", perms_" << var << ", data_" << var << ", len_" << var << R"cpp(); + any_written = any_written || file_written; } )cpp"; }