[feat] Add known fileformats
All checks were successful
continuous-integration/drone/push Build is passing

Reliably stripping (multiple) archive extensions (e.g. .tar.gz) is not supported
by std::filesystem::path. Dots in the regular root folder name can cause issues.

fileformats.hpp adds well-known format extensions which are used for stripping
the extension.

Note that this is not used by libarchive or xwim to determine the
filters/formats for extraction. This is done by libarchive's `bidding`.
This commit is contained in:
Armin Friedl 2020-02-23 15:20:47 +01:00
parent 064c936f11
commit e59968444e
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
7 changed files with 48 additions and 17 deletions

View file

@ -1,5 +1,5 @@
project('xwim', 'cpp',
version: '0.1',
version: '0.2',
default_options: ['cpp_std=c++17'])
subdir('src')

View file

@ -14,6 +14,7 @@ namespace logger = spdlog;
#include "archive_sys.hpp"
#include "archive.hpp"
#include "spec.hpp"
#include "fileformats.hpp"
namespace xwim {
@ -22,9 +23,7 @@ static void _spec_is_root_filename(ArchiveSpec* spec,
std::filesystem::path* filepath) {
auto entry_path = entry.path();
auto norm_stem = filepath->filename();
while (norm_stem.has_extension())
norm_stem = norm_stem.stem();
norm_stem = xwim::stem(norm_stem);
if (*entry_path.begin() != norm_stem) {
logger::debug("Archive root does not match archive name");

View file

@ -1,5 +1,4 @@
#ifndef ARCHIVE_H
#define ARCHIVE_H
#pragma once
#include <archive.h>
#include <fmt/format.h>
@ -42,5 +41,3 @@ class ArchiveException : public std::exception {
};
} // namespace xwim
#endif

38
src/fileformats.hpp Normal file
View file

@ -0,0 +1,38 @@
#pragma once
#include <spdlog/spdlog.h>
namespace logger = spdlog;
/** Common archive formats understood by xwim
*
* The underlying libarchive backend retrieves format information by a process
* called `bidding`. Hence, this information is mainly used to strip extensions.
*
* Stripping extensions via `std::filesystem::path` does not work reliably since
* it gets easily confused by dots in the regular file name.
*/
#include <filesystem>
#include <set>
#include <string>
namespace xwim {
const std::set<std::string> fileformats{
".7z", ".7zip", ".jar", ".tgz", ".bz2", ".bzip2", ".gz",
".gzip", ".rar", ".tar", ".tar.gz", ".tar.bz2", ".tar.xz", ".zip"};
inline std::filesystem::path stem(std::filesystem::path& path) {
std::filesystem::path p_stem {path};
logger::trace("Stemming {}", p_stem.string());
while( fileformats.find(p_stem.extension().string()) != fileformats.end() ) {
p_stem = p_stem.stem();
logger::trace("Stemmed to {}", p_stem.string());
}
logger::trace("Finished stemming {}", p_stem.string());
return p_stem;
}
} // namespace xwim

View file

@ -9,6 +9,7 @@ namespace logger = spdlog;
#include "archive.hpp"
#include "spec.hpp"
#include "fileformats.hpp"
int main(int argc, char** argv) {
logger::set_level(logger::level::trace);
@ -25,10 +26,7 @@ int main(int argc, char** argv) {
if (!archive_spec.has_single_root || !archive_spec.is_root_filename) {
extract_spec.make_dir = true;
std::filesystem::path stem = filepath.stem();
while (stem.has_extension())
stem = stem.stem();
std::filesystem::path stem = xwim::stem(filepath);
extract_spec.dirname = stem;
}

View file

@ -1,9 +1,11 @@
src = ['main.cpp',
'archive.cpp',
'archive_sys.cpp']
inc = ['archive.hpp',
'spec.hpp',
'archive_sys.hpp']
'archive_sys.hpp',
'fileformats.hpp']
libs = [dependency('libarchive', required: true),
dependency('fmt', required: true),

View file

@ -1,5 +1,4 @@
#ifndef SPEC_H
#define SPEC_H
#pragma once
#include <archive.h>
#include <fmt/core.h>
@ -55,5 +54,3 @@ struct fmt::formatter<xwim::ExtractSpec> {
spec.make_dir, spec.dirname.string(), spec.extract_subarchive);
}
};
#endif