FOSSredder 0.5.0
Loading...
Searching...
No Matches
ZipArchiveAdapter.cpp
Go to the documentation of this file.
1
5
6#include "archive/pch.h"
8
11
12#include <exception>
13#include <filesystem>
14#include <string>
15#include <utility>
16
17#include <zip.h>
18
19namespace infra::archive {
20
21namespace {
22
23void reportArchiveFailure(core::ports::diagnostics::IErrorReporter* reporter,
24 std::string message,
25 core::errors::ErrorContext context = {})
26{
27 if (!reporter) return;
28
29 core::errors::ErrorEvent event;
31 event.origin = "infra::archive::ZipArchiveAdapter::create";
32 event.message = std::move(message);
34 event.context = std::move(context);
35 core::errors::report(reporter, event);
36}
37
38bool createZipArchive(const std::filesystem::path& sourceDir,
39 const std::filesystem::path& outputArchive,
40 core::ports::diagnostics::IErrorReporter* errorReporter)
41{
42 int errorCode = 0;
43 zip_t* archive = zip_open(outputArchive.string().c_str(), ZIP_CREATE | ZIP_TRUNCATE, &errorCode);
44 if (!archive) {
45 reportArchiveFailure(errorReporter,
46 "failed to open output archive",
47 {{"path", outputArchive.string()}, {"zipErrorCode", std::to_string(errorCode)}});
48 return false;
49 }
50
51 bool success = true;
52 for (const auto& entry : std::filesystem::recursive_directory_iterator(sourceDir)) {
53 if (!entry.is_regular_file()) continue;
54
55 const std::filesystem::path absolutePath = entry.path();
56 std::filesystem::path relativePath;
57 try {
58 relativePath = std::filesystem::relative(absolutePath, sourceDir);
59 } catch (...) {
60 relativePath = absolutePath.filename();
61 }
62
63 zip_source_t* source = zip_source_file(archive, absolutePath.string().c_str(), 0, 0);
64 if (!source) {
65 reportArchiveFailure(errorReporter,
66 "failed to create zip source",
67 {{"path", absolutePath.string()}});
68 success = false;
69 break;
70 }
71
72 const std::string zipPath = relativePath.generic_string();
73 if (zip_file_add(archive, zipPath.c_str(), source, ZIP_FL_OVERWRITE | ZIP_FL_ENC_UTF_8) < 0) {
74 zip_source_free(source);
75 reportArchiveFailure(errorReporter,
76 "failed to add file to zip archive",
77 {{"path", absolutePath.string()}, {"archivePath", zipPath}});
78 success = false;
79 break;
80 }
81 }
82
83 if (!success) {
84 zip_discard(archive);
85 return false;
86 }
87
88 const bool closed = zip_close(archive) == 0;
89 const bool exists = std::filesystem::exists(outputArchive);
90 if (!closed || !exists) {
91 reportArchiveFailure(errorReporter,
92 "failed to finalize zip archive",
93 {{"path", outputArchive.string()}});
94 }
95 return closed && exists;
96}
97
98} // namespace
99
100ZipArchiveAdapter::ZipArchiveAdapter(std::shared_ptr<core::ports::diagnostics::IErrorReporter> errorReporter)
101 : errorReporter_(std::move(errorReporter))
102{
103}
104
105bool ZipArchiveAdapter::create(const std::filesystem::path& sourceDirectory,
106 const std::filesystem::path& outputArchive,
108{
110 reportArchiveFailure(errorReporter_.get(),
111 "unsupported archive format",
112 {{"path", outputArchive.string()}});
113 return false;
114 }
115 try {
116 return createZipArchive(sourceDirectory, outputArchive, errorReporter_.get());
117 } catch (...) {
118 core::errors::reportException(errorReporter_.get(),
120 "infra::archive::ZipArchiveAdapter::create",
121 std::current_exception());
122 return false;
123 }
124}
125
126} // namespace infra::archive
Provides shared helpers for reporting structured errors and exceptions.
Declares the archive adapter used by export packaging.
ZipArchiveAdapter(std::shared_ptr< core::ports::diagnostics::IErrorReporter > errorReporter)
bool create(const std::filesystem::path &sourceDirectory, const std::filesystem::path &outputArchive, core::ports::exporting::PackageFormat format) const override
Creates a ZIP archive from the files contained in a source directory.
Defines shared structured error codes.
Precompiled header for the archive infrastructure module.
constexpr const char * GenericError
Fallback code for generic structured errors.
std::vector< std::pair< std::string, std::string > > ErrorContext
Key/value context attached to an error event.
Definition ErrorEvent.h:27
void reportException(core::ports::diagnostics::IErrorReporter *reporter, ErrorSeverity severity, const char *origin, std::exception_ptr exception)
Report an exception through the reporter's default exception handling.
void report(core::ports::diagnostics::IErrorReporter *reporter, const ErrorEvent &event)
Report an already constructed error event when a reporter exists.