diff options
author | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-30 13:26:22 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-30 15:44:45 +0300 |
commit | 0a98fece5a9b54f16afeb3a94b3eb3105e9c3962 (patch) | |
tree | 291d72dbd7e9865399f668c84d11ed86fb190bbf /library/cpp/zipatch/writer.cpp | |
parent | cb2c8d75065e5b3c47094067cb4aa407d4813298 (diff) | |
download | ydb-0a98fece5a9b54f16afeb3a94b3eb3105e9c3962.tar.gz |
YQ Connector:Use docker-compose in integrational tests
Diffstat (limited to 'library/cpp/zipatch/writer.cpp')
-rw-r--r-- | library/cpp/zipatch/writer.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/library/cpp/zipatch/writer.cpp b/library/cpp/zipatch/writer.cpp new file mode 100644 index 0000000000..a9ca451b01 --- /dev/null +++ b/library/cpp/zipatch/writer.cpp @@ -0,0 +1,232 @@ +#include "writer.h" + +#include <library/cpp/json/json_value.h> +#include <library/cpp/json/json_writer.h> + +#include <util/string/join.h> + +#include <contrib/libs/libarchive/libarchive/archive.h> +#include <contrib/libs/libarchive/libarchive/archive_entry.h> + +using namespace NJson; + +namespace NZipatch { + +class TWriter::TImpl { +public: + TImpl(const TFsPath& path) + : Actions_(new TJsonValue(JSON_ARRAY)) + , Meta_(new TJsonValue(JSON_MAP)) + , Revprops_(new TJsonValue(JSON_MAP)) + , Archive_(nullptr) + { + Archive_ = archive_write_new(); + if (!Archive_) { + ythrow yexception() << "can't create archive object"; + } + archive_write_set_format_zip(Archive_); + archive_write_zip_set_compression_deflate(Archive_); + + if (ARCHIVE_OK != archive_write_open_filename(Archive_, TString(path).c_str())) { + ythrow yexception() << "can't open archive path = " << path; + } + } + + ~TImpl() { + if (Actions_ || Meta_ || Revprops_) { + Finish(); + } + if (Archive_) { + archive_write_free(Archive_); + } + } + + void Finish() { + if (Actions_) { + if (Archive_) { + WriteEntry("actions.json", WriteJson(Actions_.Get(), true, false)); + } + + Actions_.Destroy(); + } + + if (Meta_) { + if (Archive_) { + WriteEntry("meta.json", WriteJson(Meta_.Get(), true)); + } + + Meta_.Destroy(); + } + + if (Revprops_) { + if (Archive_) { + WriteEntry("revprops.json", WriteJson(Revprops_.Get(), true)); + } + + Revprops_.Destroy(); + } + + if (Archive_) { + archive_write_close(Archive_); + } + } + + void Copy(const TString& path, const TOrigin& origin) { + Y_ASSERT(origin.Path); + Y_ASSERT(origin.Revision); + + if (Actions_) { + TJsonValue item; + item["type"] = "svn_copy"; + item["path"] = path; + item["orig_path"] = origin.Path; + item["orig_revision"] = origin.Revision; + Actions_->AppendValue(item); + } + } + + void MkDir(const TString& path) { + if (Actions_) { + TJsonValue item; + item["type"] = "mkdir"; + item["path"] = path; + Actions_->AppendValue(item); + } + } + + void RemoveFile(const TString& path) { + if (Actions_) { + TJsonValue item; + item["type"] = "remove_file"; + item["path"] = path; + Actions_->AppendValue(item); + } + } + + void RemoveTree(const TString& path) { + if (Actions_) { + TJsonValue item; + item["type"] = "remove_tree"; + item["path"] = path; + Actions_->AppendValue(item); + } + } + + void StoreFile( + const TString& path, + const TString& data, + const bool execute, + const bool symlink, + const TMaybe<bool> binaryHint, + const TMaybe<bool> encrypted) + { + if (Actions_) { + const TString file = Join("/", "files", path); + TJsonValue item; + item["type"] = "store_file"; + item["executable"] = execute; + item["path"] = path; + item["file"] = file; + if (binaryHint.Defined()) { + item["binary_hint"] = *binaryHint; + } + if (encrypted.Defined()) { + item["encrypted"] = *encrypted; + } + Actions_->AppendValue(item); + WriteEntry(file, data, symlink); + } + } + + void SetBaseSvnRevision(ui64 revision) { + if (Meta_) { + (*Meta_)["base_svn_revision"] = revision; + } + } + + void AddRevprop(const TString& prop, const TString& value) { + if (Revprops_) { + (*Revprops_)[prop] = value; + } + } + +private: + void WriteEntry( + const TString& path, + const TString& data, + const bool symlink = false) + { + struct archive_entry* const entry = archive_entry_new(); + // Write header. + archive_entry_set_pathname(entry, path.c_str()); + archive_entry_set_size(entry, data.size()); + archive_entry_set_filetype(entry, symlink ? AE_IFLNK : AE_IFREG); + archive_entry_set_perm(entry, 0644); + if (symlink) { + archive_entry_set_symlink(entry, data.c_str()); + } + archive_write_header(Archive_, entry); + // Write data. + // If entry is symlink then entry size become zero. + if (archive_entry_size(entry) > 0) { + archive_write_data(Archive_, data.data(), data.size()); + } + archive_entry_free(entry); + } + +private: + THolder<NJson::TJsonValue> Actions_; + THolder<NJson::TJsonValue> Meta_; + THolder<NJson::TJsonValue> Revprops_; + struct archive* Archive_; +}; + +TWriter::TWriter(const TFsPath& path) + : Impl_(new TImpl(path)) +{ +} + +TWriter::~TWriter() +{ } + +void TWriter::Finish() { + Impl_->Finish(); +} + +void TWriter::SetBaseSvnRevision(ui64 revision) { + Impl_->SetBaseSvnRevision(revision); +} + +void TWriter::AddRevprop(const TString& prop, const TString& value) { + Impl_->AddRevprop(prop, value); +} + +void TWriter::Copy(const TString& path, const TOrigin& origin) { + Impl_->Copy(path, origin); +} + +void TWriter::MkDir(const TString& path) { + Impl_->MkDir(path); +} + +void TWriter::RemoveFile(const TString& path) { + Impl_->RemoveFile(path); +} + +void TWriter::RemoveTree(const TString& path) { + Impl_->RemoveTree(path); +} + +void TWriter::StoreFile( + const TString& path, + const TString& data, + const bool execute, + const bool symlink, + const TMaybe<bool> binaryHint, + const TMaybe<bool> encrypted) +{ + Impl_->StoreFile(path, data, execute, symlink, binaryHint, encrypted); +} + +} // namespace NZipatch + |