Relative root path in archive, clang-format, refactoring
Compressed archives now contain a single root which consists of the file or folder being compressed. Before, the archive root contained the full relative path form the current working directory to the compressed file or folder. This is unintuitive in most cases and not dwim.
This commit is contained in:
parent
cdb3775eb6
commit
d9cbf47036
4 changed files with 296 additions and 74 deletions
169
.clang-format
169
.clang-format
|
@ -1 +1,168 @@
|
|||
BasedOnStyle: Chromium
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Auto
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
|
|
|
@ -126,12 +126,12 @@ Per default xwim chooses an appropriate log level according to your build type
|
|||
- off
|
||||
|
||||
# Contributing
|
||||
While xwim is still in incubator phase (i.e. before version 1.0) it's main
|
||||
While xwim is still in incubator phase (i.e. before version 1.0) its main
|
||||
repository is hosted on https://git.friedl.net/incubator/xwim with a mirror on
|
||||
https://github.com/arminfriedl/xwim. With the first stable release it will most
|
||||
likely move to GitHub as it's main repository.
|
||||
likely move to GitHub as its main repository.
|
||||
|
||||
If you want to contribute, you can either issue a pull request on it's Github
|
||||
If you want to contribute, you can either issue a pull request on its Github
|
||||
mirror (will be cherry picked into the main repository) or send patches to
|
||||
dev[at]friedl[dot]net.
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
project('xwim', 'cpp',
|
||||
version: '0.2',
|
||||
version: '0.3',
|
||||
default_options: ['cpp_std=c++17',
|
||||
'warning_level=3',
|
||||
'b_coverage=true'])
|
||||
'b_coverage=true',
|
||||
'b_ndebug=if-release'])
|
||||
|
||||
subdir('src')
|
||||
subdir('doc')
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
#include <fcntl.h>
|
||||
#include <archive_entry.h>
|
||||
#include <fcntl.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "archive.hpp"
|
||||
#include "fileformats.hpp"
|
||||
#include "spec.hpp"
|
||||
namespace logger = spdlog;
|
||||
|
||||
#include "archive_sys.hpp"
|
||||
|
||||
#include <archive.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
bool xwim::ArchiveEntryView::is_empty() {
|
||||
return (this->ae == nullptr);
|
||||
}
|
||||
#include "archive_sys.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
bool xwim::ArchiveEntryView::is_empty() { return (this->ae == nullptr); }
|
||||
|
||||
std::string xwim::ArchiveEntryView::path_name() {
|
||||
if (!this->ae) throw ArchiveSysException{"Access to invalid archive entry"};
|
||||
|
@ -22,9 +24,9 @@ std::string xwim::ArchiveEntryView::path_name() {
|
|||
return archive_entry_pathname(this->ae);
|
||||
}
|
||||
|
||||
std::filesystem::path xwim::ArchiveEntryView::path() {
|
||||
fs::path xwim::ArchiveEntryView::path() {
|
||||
if (!this->ae) throw ArchiveSysException{"Access to invalid archive entry"};
|
||||
return std::filesystem::path{this->path_name()};
|
||||
return fs::path{this->path_name()};
|
||||
}
|
||||
|
||||
mode_t xwim::ArchiveEntryView::file_type() {
|
||||
|
@ -36,7 +38,7 @@ bool xwim::ArchiveEntryView::is_directory() {
|
|||
return S_ISDIR(this->file_type());
|
||||
}
|
||||
|
||||
xwim::ArchiveReaderSys::ArchiveReaderSys(std::filesystem::path& path) {
|
||||
xwim::ArchiveReaderSys::ArchiveReaderSys(fs::path &path) {
|
||||
int r; // libarchive error handling
|
||||
|
||||
logger::trace("Setting up archive reader");
|
||||
|
@ -63,8 +65,12 @@ bool xwim::ArchiveReaderSys::advance() {
|
|||
logger::trace("Advancing reader to next archive entry");
|
||||
|
||||
r = archive_read_next_header(this->ar, &this->ae);
|
||||
if (r == ARCHIVE_EOF) { this->ae = nullptr; return false; }
|
||||
if (r != ARCHIVE_OK) throw(ArchiveSysException{"Could not list archive", this->ar});
|
||||
if (r == ARCHIVE_EOF) {
|
||||
this->ae = nullptr;
|
||||
return false;
|
||||
}
|
||||
if (r != ARCHIVE_OK)
|
||||
throw(ArchiveSysException{"Could not list archive", this->ar});
|
||||
|
||||
logger::trace("Got entry {}", archive_entry_pathname(ae));
|
||||
return true;
|
||||
|
@ -74,16 +80,17 @@ const xwim::ArchiveEntryView xwim::ArchiveReaderSys::cur() {
|
|||
return ArchiveEntryView{this->ae};
|
||||
}
|
||||
|
||||
xwim::ArchiveExtractorSys::ArchiveExtractorSys(std::filesystem::path& root) {
|
||||
xwim::ArchiveExtractorSys::ArchiveExtractorSys(fs::path &root) {
|
||||
logger::trace("Constructing ArchiveExtractorSys with path {}", root.string());
|
||||
|
||||
std::filesystem::create_directories(root);
|
||||
std::filesystem::current_path(root);
|
||||
fs::create_directories(root);
|
||||
fs::current_path(root);
|
||||
|
||||
this->writer = archive_write_disk_new();
|
||||
archive_write_disk_set_standard_lookup(this->writer);
|
||||
|
||||
logger::trace("Constructed ArchiveExtractorSys at {:p}", (void*) this->writer);
|
||||
logger::trace("Constructed ArchiveExtractorSys at {:p}",
|
||||
(void *)this->writer);
|
||||
}
|
||||
|
||||
xwim::ArchiveExtractorSys::ArchiveExtractorSys() {
|
||||
|
@ -91,19 +98,20 @@ xwim::ArchiveExtractorSys::ArchiveExtractorSys() {
|
|||
|
||||
this->writer = archive_write_disk_new();
|
||||
archive_write_disk_set_standard_lookup(this->writer);
|
||||
logger::trace("Constructed ArchiveExtractorSys at {:p}", (void*) this->writer);
|
||||
logger::trace("Constructed ArchiveExtractorSys at {:p}",
|
||||
(void *)this->writer);
|
||||
}
|
||||
|
||||
void xwim::ArchiveExtractorSys::extract_all(xwim::ArchiveReaderSys& reader) {
|
||||
while(reader.advance()) {
|
||||
void xwim::ArchiveExtractorSys::extract_all(xwim::ArchiveReaderSys &reader) {
|
||||
while (reader.advance()) {
|
||||
this->extract_entry(reader);
|
||||
}
|
||||
}
|
||||
|
||||
// forward declared
|
||||
static int copy_data(struct archive* ar, struct archive* aw);
|
||||
static int copy_data(struct archive *ar, struct archive *aw);
|
||||
|
||||
void xwim::ArchiveExtractorSys::extract_entry(xwim::ArchiveReaderSys& reader) {
|
||||
void xwim::ArchiveExtractorSys::extract_entry(xwim::ArchiveReaderSys &reader) {
|
||||
int r;
|
||||
r = archive_write_header(this->writer, reader.ae);
|
||||
if (r != ARCHIVE_OK) {
|
||||
|
@ -116,83 +124,65 @@ void xwim::ArchiveExtractorSys::extract_entry(xwim::ArchiveReaderSys& reader) {
|
|||
}
|
||||
}
|
||||
|
||||
xwim::ArchiveExtractorSys::~ArchiveExtractorSys(){
|
||||
logger::trace("Destructing ArchiveExtractorSys at {:p}", (void*) this->writer);
|
||||
if(this->writer) {
|
||||
xwim::ArchiveExtractorSys::~ArchiveExtractorSys() {
|
||||
logger::trace("Destructing ArchiveExtractorSys at {:p}",
|
||||
(void *)this->writer);
|
||||
if (this->writer) {
|
||||
archive_write_close(this->writer);
|
||||
archive_write_free(this->writer);
|
||||
}
|
||||
}
|
||||
|
||||
xwim::ArchiveCompressorSys::ArchiveCompressorSys(std::filesystem::path& root, xwim::CompressSpec compress_spec): root{root}, compress_spec{compress_spec} {
|
||||
xwim::ArchiveCompressorSys::ArchiveCompressorSys(
|
||||
fs::path &root, xwim::CompressSpec compress_spec)
|
||||
: root{root}, compress_spec{compress_spec} {
|
||||
this->new_archive = archive_write_new();
|
||||
|
||||
for(xwim::archive_filter filter: this->compress_spec.filters) {
|
||||
for (xwim::archive_filter filter : this->compress_spec.filters) {
|
||||
archive_write_add_filter(this->new_archive, filter);
|
||||
}
|
||||
|
||||
archive_write_set_format(this->new_archive, this->compress_spec.format);
|
||||
}
|
||||
|
||||
// forward declared
|
||||
static fs::path archive_path_norm(const fs::path &root,
|
||||
const xwim::CompressSpec &compress_spec);
|
||||
|
||||
void xwim::ArchiveCompressorSys::compress() {
|
||||
std::filesystem::path archive_path{this->root};
|
||||
if(!std::filesystem::exists(archive_path)) {
|
||||
logger::error("Non-existing path: {}", archive_path.string());
|
||||
throw ArchiveSysException{"Path does not exists"};
|
||||
}
|
||||
fs::path archive_path = archive_path_norm(this->root, this->compress_spec);
|
||||
|
||||
std::filesystem::file_status file_status = std::filesystem::status(archive_path);
|
||||
logger::debug("Writing archive at: {}", archive_path.filename().c_str());
|
||||
|
||||
if(file_status.type() != std::filesystem::file_type::directory
|
||||
&& file_status.type() != std::filesystem::file_type::regular) {
|
||||
logger::error("Unknown path type: {}", file_status.type());
|
||||
throw ArchiveSysException{"Unknown path type"};
|
||||
}
|
||||
archive_write_open_filename(this->new_archive,
|
||||
archive_path.filename().c_str());
|
||||
|
||||
if ((file_status.permissions() & std::filesystem::perms::owner_read) ==
|
||||
std::filesystem::perms::none &&
|
||||
(file_status.permissions() & std::filesystem::perms::group_read) ==
|
||||
std::filesystem::perms::none &&
|
||||
(file_status.permissions() & std::filesystem::perms::others_read) ==
|
||||
std::filesystem::perms::none) {
|
||||
logger::error("Cannot read path with permissions: {}",
|
||||
file_status.permissions());
|
||||
throw ArchiveSysException{"Unreadable path"};
|
||||
}
|
||||
|
||||
if(file_status.type() == std::filesystem::file_type::regular) {
|
||||
while(archive_path.has_extension()) {
|
||||
archive_path.replace_extension();
|
||||
}
|
||||
}
|
||||
|
||||
archive_path.concat(this->compress_spec.extension);
|
||||
logger::debug("Writing archive at: {}", std::filesystem::absolute(archive_path).c_str());
|
||||
archive_write_open_filename(this->new_archive, std::filesystem::absolute(archive_path).c_str());
|
||||
|
||||
archive* disk = archive_read_disk_new();
|
||||
archive *disk = archive_read_disk_new();
|
||||
archive_read_disk_set_standard_lookup(disk);
|
||||
|
||||
int r;
|
||||
|
||||
r = archive_read_disk_open(disk, std::filesystem::relative(this->root).c_str());
|
||||
if(r != ARCHIVE_OK) {
|
||||
r = archive_read_disk_open(disk, fs::relative(this->root).c_str());
|
||||
if (r != ARCHIVE_OK) {
|
||||
throw ArchiveSysException("Could not open path for archiving", disk);
|
||||
}
|
||||
|
||||
archive_entry* entry;
|
||||
archive_entry *entry;
|
||||
char buff[16384];
|
||||
|
||||
for (;;) {
|
||||
entry = archive_entry_new();
|
||||
r = archive_read_next_header2(disk, entry);
|
||||
if (r == ARCHIVE_EOF)
|
||||
break;
|
||||
if (r == ARCHIVE_EOF) break;
|
||||
if (r != ARCHIVE_OK) {
|
||||
throw ArchiveSysException("Could not read next archive entry", disk);
|
||||
}
|
||||
|
||||
archive_read_disk_descend(disk);
|
||||
|
||||
const char* ae_path = archive_entry_pathname(entry);
|
||||
fs::path ae_rel_path = fs::relative(fs::path(ae_path), this->root.parent_path());
|
||||
archive_entry_set_pathname(entry, ae_rel_path.c_str());
|
||||
logger::trace("Processing entry {}", archive_entry_pathname(entry));
|
||||
|
||||
r = archive_write_header(this->new_archive, entry);
|
||||
|
@ -200,6 +190,7 @@ void xwim::ArchiveCompressorSys::compress() {
|
|||
throw ArchiveSysException("Could not write header for archive entry",
|
||||
this->new_archive);
|
||||
}
|
||||
|
||||
if (r > ARCHIVE_FAILED) {
|
||||
int fd = open(archive_entry_sourcepath(entry), O_RDONLY);
|
||||
ssize_t len = read(fd, buff, sizeof(buff));
|
||||
|
@ -209,21 +200,84 @@ void xwim::ArchiveCompressorSys::compress() {
|
|||
}
|
||||
close(fd);
|
||||
}
|
||||
logger::trace("Entry written {}", archive_entry_pathname(entry));
|
||||
archive_entry_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
xwim::ArchiveCompressorSys::~ArchiveCompressorSys() {
|
||||
logger::trace("Destructing ArchiveExtractorSys at {:p}", (void*) this->new_archive);
|
||||
if(this->new_archive) {
|
||||
logger::trace("Destructing ArchiveExtractorSys at {:p}",
|
||||
(void *)this->new_archive);
|
||||
if (this->new_archive) {
|
||||
archive_write_close(this->new_archive);
|
||||
archive_write_free(this->new_archive);
|
||||
}
|
||||
}
|
||||
|
||||
static int copy_data(struct archive* ar, struct archive* aw) {
|
||||
/** Creates an archive path from the path to compress and normalizes it
|
||||
*
|
||||
* Note that currently only single arguments are allowed for `xwim` to
|
||||
* minimize ambiguity.
|
||||
*
|
||||
* The archive path is determined from the argument file/directory by:
|
||||
* 1. If file:
|
||||
* 1.1. Stem the filename
|
||||
* 1.2. Append an extension appropriate for the archive format (from the
|
||||
* spec)
|
||||
* 2. If directory:
|
||||
* 2.1. Remove any trailing '/'
|
||||
* 2.2. Append an extension appropriate for the archive format (from the
|
||||
* spec)
|
||||
*/
|
||||
static fs::path archive_path_norm(const fs::path &root,
|
||||
const xwim::CompressSpec &compress_spec) {
|
||||
fs::path archive_path{root};
|
||||
fs::file_status archive_path_stat = fs::status(archive_path);
|
||||
|
||||
std::set known_types = {fs::file_type::directory, fs::file_type::regular};
|
||||
fs::perms flag_mask =
|
||||
fs::perms::owner_read | fs::perms::group_read | fs::perms::others_read;
|
||||
|
||||
if (!fs::exists(archive_path)) {
|
||||
logger::error("Non-existing path: {}", archive_path.string());
|
||||
throw xwim::ArchiveSysException{"Path does not exists"};
|
||||
}
|
||||
|
||||
if (!known_types.count(archive_path_stat.type())) {
|
||||
logger::error("Unknown path type: {}", archive_path_stat.type());
|
||||
throw xwim::ArchiveSysException{"Unknown path type"};
|
||||
}
|
||||
|
||||
if ((archive_path_stat.permissions() & flag_mask) == fs::perms::none) {
|
||||
logger::error("Cannot read path with permissions: {}",
|
||||
archive_path_stat.permissions());
|
||||
throw xwim::ArchiveSysException{"Unreadable path"};
|
||||
}
|
||||
|
||||
if (archive_path_stat.type() == fs::file_type::regular) {
|
||||
while (archive_path.has_extension()) {
|
||||
archive_path.replace_extension();
|
||||
}
|
||||
}
|
||||
|
||||
if (archive_path_stat.type() == fs::file_type::directory) {
|
||||
if (archive_path.string().back() == '/') {
|
||||
logger::trace("Found trailing / in path");
|
||||
std::string ps = archive_path.string();
|
||||
ps.erase(ps.size() - 1, 1);
|
||||
|
||||
archive_path = fs::path{ps};
|
||||
logger::trace("Normalized path to {}", archive_path.string());
|
||||
}
|
||||
}
|
||||
|
||||
archive_path.concat(compress_spec.extension);
|
||||
return archive_path;
|
||||
}
|
||||
|
||||
static int copy_data(struct archive *ar, struct archive *aw) {
|
||||
int r;
|
||||
const void* buff;
|
||||
const void *buff;
|
||||
size_t size;
|
||||
int64_t offset;
|
||||
|
||||
|
|
Loading…
Reference in a new issue