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

View file

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

View file

@ -1,7 +1,9 @@
#include <archive.h> #include <archive.h>
#include <archive_entry.h> #include <archive_entry.h>
#include <fcntl.h>
#include <fmt/core.h> #include <fmt/core.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sys/stat.h>
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
@ -16,7 +18,38 @@ namespace fs = std::filesystem;
static int copy_data(shared_ptr<archive> reader, shared_ptr<archive> writer); 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) { void LibArchiver::extract(fs::path archive_in, fs::path out) {
spdlog::debug("Extracting archive {} to {}", archive_in, out); spdlog::debug("Extracting archive {} to {}", archive_in, out);