Compression
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Armin Friedl 2021-02-19 06:07:32 +01:00
parent 189be660f5
commit 4c1c5bf00f
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
3 changed files with 64 additions and 17 deletions

View file

@ -1,7 +1,9 @@
#include "Archiver.hpp"
#include <spdlog/common.h>
#include <spdlog/spdlog.h>
#include <filesystem>
#include <map>
#include <memory>
@ -15,16 +17,19 @@ namespace fs = std::filesystem;
fs::path archive_extension(const fs::path& path) {
// TODO: creates lots of paths, refactor
fs::path ext;
fs::path tmp_ext;
fs::path tmp_path = path;
while (tmp_path.has_extension()) {
fs::path tmp_ext = tmp_path.extension() += ext;
tmp_ext = tmp_path.extension() += tmp_ext;
auto search = extensions_format.find(tmp_ext);
// (Combined) extension not known, return last known extension
if (search == extensions_format.end()) return ext;
if (search != extensions_format.end()) {
// (Combined) extension known. Remember as `ext` and keep
// looking for even longer extensions.
ext = tmp_ext;
} // else: (Combined) extension not known, keep `ext` as-is but try longer
// extensions
// Continue extending extension
ext = tmp_ext;
tmp_path = tmp_path.stem();
}
@ -34,20 +39,28 @@ fs::path archive_extension(const fs::path& path) {
// Strip longest known extension from path
fs::path strip_archive_extension(const fs::path& path) {
// TODO: creates lots of paths, refactor
fs::path ext;
int longest_ext = 0;
fs::path tmp_ext;
fs::path tmp_path = path;
fs::path stem_path = path;
while (tmp_path.has_extension()) {
fs::path tmp_ext = tmp_path.extension() += ext;
tmp_ext = tmp_path.extension() += tmp_ext;
auto search = extensions_format.find(tmp_ext);
// (Combined) extension not known, return stripped path
if (search == extensions_format.end()) return tmp_path;
if (search != extensions_format.end()) {
// (Combined) extension known. Remember as `longest_ext` and keep
// looking for even longer extensions.
longest_ext++;
} // else: (Combined) extension not known, keep `longest_ext` as-is but try longer
// extensions
// Continue stripping path
ext = tmp_ext;
tmp_path = tmp_path.stem();
}
tmp_path = path;
for(int i=0; i<longest_ext; i++) tmp_path = tmp_path.stem();
return tmp_path;
}
@ -63,7 +76,9 @@ bool can_extract(const fs::path& path) {
}
Format parse_format(const fs::path& path) {
spdlog::debug("Looking for path {}", path);
fs::path ext = archive_extension(path);
spdlog::debug("Looking for ext {}", ext);
auto search = extensions_format.find(ext);
if (search == extensions_format.end()) {
throw XwimError{"No known archiver for {}", path};

View file

@ -83,11 +83,10 @@ void Xwim::infer_compression_output() {
if (ins.size() == 1) {
// archive name is just the name of the input with default archive
// extension
fs::path p = *ins.begin();
while (p.has_extension()) p = p.stem();
p += default_extension;
out = p;
fs::path archive_stem = xwim::strip_archive_extension(*ins.begin());
fs::path path = (*ins.begin()).stem();
path += default_extension;
out = path;
} else {
// We cannot guess the name of the output archive

View file

@ -1,7 +1,9 @@
#include <archive.h>
#include <archive_entry.h>
#include <fcntl.h>
#include <fmt/core.h>
#include <spdlog/spdlog.h>
#include <sys/stat.h>
#include <filesystem>
#include <iostream>
@ -16,7 +18,38 @@ namespace fs = std::filesystem;
static int copy_data(shared_ptr<archive> reader, shared_ptr<archive> writer);
void LibArchiver::compress(set<fs::path> ins, fs::path archive_out) { return; }
void LibArchiver::compress(set<fs::path> ins, fs::path archive_out) {
spdlog::debug("Compressing to {}", archive_out);
// cannot use unique_ptr here since unique_ptr requires a
// complete type. `archive` is forward declared only.
shared_ptr<archive> writer;
writer = shared_ptr<archive>(archive_write_new(), archive_write_free);
archive_write_add_filter_gzip(writer.get());
archive_write_set_format_pax_restricted(writer.get());
archive_write_open_filename(writer.get(), archive_out.c_str());
archive_entry *entry = archive_entry_new();
char buff[8192];
for(auto path: ins) {
archive_entry_set_pathname(entry, path.c_str());
archive_entry_set_size(entry, fs::file_size(path));
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_perm(entry, 0644);
archive_write_header(writer.get(), entry);
int fd = open(path.c_str(), O_RDONLY);
int len = read(fd, buff, sizeof(buff));
while (len > 0) {
archive_write_data(writer.get(), buff, len);
len = read(fd, buff, sizeof(buff));
}
close(fd);
archive_entry_clear(entry);
}
}
void LibArchiver::extract(fs::path archive_in, fs::path out) {
spdlog::debug("Extracting archive {} to {}", archive_in, out);