# HG changeset patch # User František Kučera # Date 1547655785 -3600 # Node ID d44ed75822e7530682cb8d9060adf350d0b7d434 # Parent 62eac7ab4cf4509bdadf94d901cedce5f660519b modular design diff -r 62eac7ab4cf4 -r d44ed75822e7 nbproject/configurations.xml --- a/nbproject/configurations.xml Sun Jan 13 16:44:11 2019 +0100 +++ b/nbproject/configurations.xml Wed Jan 16 17:23:05 2019 +0100 @@ -42,6 +42,12 @@ + AttributeFinder.h + CLIParser.h + Configuration.h + FileAttributeFinder.h + RequestedField.h + XattrAttributeFinder.h relpipe-in-filesystem.cpp @@ -91,6 +97,18 @@ true + + + + + + + + + + + + @@ -130,6 +148,18 @@ true + + + + + + + + + + + + diff -r 62eac7ab4cf4 -r d44ed75822e7 src/AttributeFinder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/AttributeFinder.h Wed Jan 16 17:23:05 2019 +0100 @@ -0,0 +1,97 @@ +/** + * Relational pipes + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include + +#include +#include +#include + +#include "RequestedField.h" + +namespace relpipe { +namespace in { +namespace filesystem { + +namespace fs = std::filesystem; +using namespace relpipe::writer; + +class AttributeFinder { +public: + + /** + * Single requested fields might generate multiple attributes in the relation. + * But usually it is 1:1. + * @param field requested field from the user (usually from CLI arguments) + * @return attribute metadata to be used in the RelationalWriter.startRelation() + */ + virtual vector toMetadata(const RequestedField& field) = 0; + + /** + * Writing of the record for current file is starting. + * Following writeField() calls are related to this file. + * @param file + */ + virtual void startFile(const fs::path& file) = 0; + + /** + * Writing of the record for current file is finished. All resources linked to this file should be released. + */ + virtual void endFile() = 0; + + /** + * Writes field attribute(s). The attribute count must match with count of AttributeMetadata returned in toMetadata(). + * @param writer + * @param field + */ + virtual void writeField(RelationalWriter* writer, const RequestedField& field) = 0; + + /** + * Writes empty attribute(s) in case of non-existent file or an error. + * The attribute count must match with count of AttributeMetadata returned in toMetadata(). + * @param writer + * @param field + */ + virtual void writeEmptyField(RelationalWriter* writer, const RequestedField& field) { + // TODO: better handling of null values (when null values are supported by the format specification) + for (AttributeMetadata m : toMetadata(field)) { + switch (m.typeId) { + case TypeId::BOOLEAN: + writer->writeAttribute(L"false"); + break; + case TypeId::INTEGER: + writer->writeAttribute(L"0"); + break; + case TypeId::STRING: + writer->writeAttribute(L""); + break; + default: + throw RelpipeWriterException(L"Unsupported attribute type in writeEmptyField()."); + } + } + } + + virtual ~AttributeFinder() { + } +}; + +} +} +} \ No newline at end of file diff -r 62eac7ab4cf4 -r d44ed75822e7 src/CLIParser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/CLIParser.h Wed Jan 16 17:23:05 2019 +0100 @@ -0,0 +1,57 @@ +/** + * Relational pipes + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#include + +#include "Configuration.h" +#include "FileAttributeFinder.h" + +namespace relpipe { +namespace in { +namespace filesystem { + +using namespace relpipe::writer; + +class CLIParser { +public: + + Configuration parse(const std::vector& arguments) { + Configuration c; + // TODO: parse arguments + c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ORIGINAL)); + // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_ABSOLUTE)); + // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_PATH_CANONICAL)); + // c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_NAME)); + c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_TYPE)); + c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_SIZE)); + c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_OWNER)); + c.fields.push_back(RequestedField(RequestedField::GROUP_FILE, FileAttributeFinder::FIELD_GROUP)); + c.fields.push_back(RequestedField(RequestedField::GROUP_XATTR, L"user.xdg.origin.url")); + return c; + } + + virtual ~CLIParser() { + } +}; + +} +} +} diff -r 62eac7ab4cf4 -r d44ed75822e7 src/CMakeLists.txt --- a/src/CMakeLists.txt Sun Jan 13 16:44:11 2019 +0100 +++ b/src/CMakeLists.txt Wed Jan 16 17:23:05 2019 +0100 @@ -1,5 +1,5 @@ # Relational pipes -# Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) +# Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff -r 62eac7ab4cf4 -r d44ed75822e7 src/Configuration.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Configuration.h Wed Jan 16 17:23:05 2019 +0100 @@ -0,0 +1,40 @@ +/** + * Relational pipes + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#include + +#include "RequestedField.h" + +namespace relpipe { +namespace in { +namespace filesystem { + +class Configuration { +public: + std::vector fields; + + virtual ~Configuration() { + } +}; + +} +} +} \ No newline at end of file diff -r 62eac7ab4cf4 -r d44ed75822e7 src/FileAttributeFinder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/FileAttributeFinder.h Wed Jan 16 17:23:05 2019 +0100 @@ -0,0 +1,144 @@ +/** + * Relational pipes + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include + +#include +#include +#include + +#include "RequestedField.h" + +namespace relpipe { +namespace in { +namespace filesystem { + +namespace fs = std::filesystem; +using namespace relpipe::writer; + +class FileAttributeFinder : public AttributeFinder { +private: + std::wstring_convert> convertor; // TODO: support also other encodings. + + fs::path currentFile; + string_t currentOwner; + string_t currentGroup; + + string_t getType(const fs::path& file) { + // TODO: Use whole words? (letters are compatible with find -type) + if (fs::is_regular_file(file)) return L"f"; + else if (fs::is_symlink(file)) return L"l"; // symlinks to directories are both symlinks and directories + else if (fs::is_directory(file)) return L"d"; + else if (fs::is_fifo(file)) return L"p"; + else if (fs::is_socket(file)) return L"s"; + else if (fs::is_block_file(file)) return L"b"; + else if (fs::is_character_file(file)) return L"c"; + else return L"o"; + } + + void fetchOwner(const fs::path& file, string_t& owner, string_t& group) { + // TODO: throw exception on error + // TODO: get user and group in C++ way? + struct stat info; + stat(file.c_str(), &info); + /** + * The return value may point to a static area, and may be + * overwritten by subsequent calls to getpwent(3), getpw‐ + * nam(), or getpwuid(). (Do not pass the returned pointer + * to free(3).) + */ + struct passwd* pw = getpwuid(info.st_uid); + struct group* gr = getgrgid(info.st_gid); + owner = convertor.from_bytes(pw->pw_name); + group = convertor.from_bytes(gr->gr_name); + } +public: + + static const string_t FIELD_PATH_ORIGINAL; + static const string_t FIELD_NAME; + static const string_t FIELD_SIZE; + static const string_t FIELD_PATH_ABSOLUTE; + static const string_t FIELD_PATH_CANONICAL; + static const string_t FIELD_TYPE; + static const string_t FIELD_OWNER; + static const string_t FIELD_GROUP; + + virtual vector toMetadata(const RequestedField& field) override { + if (field.group == RequestedField::GROUP_FILE) { + if (field.name == FIELD_SIZE) return { AttributeMetadata{field.name, TypeId::INTEGER}}; + else return { AttributeMetadata{field.name, TypeId::STRING}}; + } else { + return {}; + } + } + + void startFile(const fs::path& file) override { + currentFile = file; + }; + + void endFile() override { + currentOwner.clear(); + currentGroup.clear(); + }; + + virtual void writeField(RelationalWriter* writer, const RequestedField& field) override { + if (field.group == RequestedField::GROUP_FILE) { + if (field.name == FIELD_NAME) { + writer->writeAttribute(currentFile.filename().wstring()); + } else if (field.name == FIELD_PATH_ORIGINAL) { + writer->writeAttribute(currentFile.wstring()); + } else if (field.name == FIELD_PATH_ABSOLUTE) { + writer->writeAttribute(fs::absolute(currentFile).wstring()); + } else if (field.name == FIELD_PATH_CANONICAL) { + writer->writeAttribute(fs::canonical(currentFile).wstring()); + } else if (field.name == FIELD_TYPE) { + writer->writeAttribute(getType(currentFile)); + } else if (field.name == FIELD_SIZE) { + integer_t size = fs::is_regular_file(currentFile) ? fs::file_size(currentFile) : 0; + writer->writeAttribute(&size, typeid (size)); + } else if (field.name == FIELD_OWNER) { + if (currentOwner.empty()) fetchOwner(currentFile, currentOwner, currentGroup); + writer->writeAttribute(currentOwner); + } else if (field.name == FIELD_GROUP) { + if (currentOwner.empty()) fetchOwner(currentFile, currentOwner, currentGroup); + writer->writeAttribute(currentGroup); + } else { + // TODO: should not happend; check supported attributes in toMetadata()? + writer->writeAttribute(L""); + } + } + } + + virtual ~FileAttributeFinder() override { + } +}; + +const string_t FileAttributeFinder::FIELD_PATH_ORIGINAL = L"path"; +const string_t FileAttributeFinder::FIELD_NAME = L"name"; +const string_t FileAttributeFinder::FIELD_SIZE = L"size"; +const string_t FileAttributeFinder::FIELD_PATH_ABSOLUTE = L"path_absolute"; +const string_t FileAttributeFinder::FIELD_PATH_CANONICAL = L"path_canonical"; +const string_t FileAttributeFinder::FIELD_TYPE = L"type"; +const string_t FileAttributeFinder::FIELD_OWNER = L"owner"; +const string_t FileAttributeFinder::FIELD_GROUP = L"group"; + +} +} +} diff -r 62eac7ab4cf4 -r d44ed75822e7 src/FilesystemCommand.h --- a/src/FilesystemCommand.h Sun Jan 13 16:44:11 2019 +0100 +++ b/src/FilesystemCommand.h Wed Jan 16 17:23:05 2019 +0100 @@ -1,6 +1,6 @@ /** * Relational pipes - * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,9 +19,10 @@ #include #include +#include #include #include -#include +#include #include #include @@ -33,6 +34,11 @@ #include +#include "Configuration.h" +#include "AttributeFinder.h" +#include "FileAttributeFinder.h" +#include "XattrAttributeFinder.h" + namespace relpipe { namespace in { namespace filesystem { @@ -41,8 +47,16 @@ using namespace relpipe::writer; class FilesystemCommand { +private: std::wstring_convert> convertor; // TODO: support also other encodings. + FileAttributeFinder fileAttributeFinder; + XattrAttributeFinder xattrAttributeFinder; + + std::map attributeFinders{ + {RequestedField::GROUP_FILE, &fileAttributeFinder}, + {RequestedField::GROUP_XATTR, &xattrAttributeFinder}}; + void reset(std::stringstream& stream) { stream.str(""); stream.clear(); @@ -56,81 +70,23 @@ return originalName.tellp(); } - string_t getType(const fs::path& file) { - // TODO: Use whole words? (letters are compatible with find -type) - if (fs::is_regular_file(file)) return L"f"; - else if (fs::is_symlink(file)) return L"l"; // symlinks to directories are both symlinks and directories - else if (fs::is_directory(file)) return L"d"; - else if (fs::is_fifo(file)) return L"p"; - else if (fs::is_socket(file)) return L"s"; - else if (fs::is_block_file(file)) return L"b"; - else if (fs::is_character_file(file)) return L"c"; - else return L"o"; - } - - void fetchOwner(const fs::path& file, string_t& owner, string_t& group) { - // TODO: throw exception on error - // TODO: get user and group in C++ way? - struct stat info; - stat(file.c_str(), &info); - /** - * The return value may point to a static area, and may be - * overwritten by subsequent calls to getpwent(3), getpw‐ - * nam(), or getpwuid(). (Do not pass the returned pointer - * to free(3).) - */ - struct passwd* pw = getpwuid(info.st_uid); - struct group* gr = getgrgid(info.st_gid); - owner = convertor.from_bytes(pw->pw_name); - group = convertor.from_bytes(gr->gr_name); - } - - string_t getXattr(const fs::path& file, const string_t& attributeName) { - // TODO: review, test on multiple platforms - // TODO: improve documentation in xattr.h in glibc - // TODO: check XATTR_NAME_MAX in limits.h and if it is reasonably small on our system, allocate buffer for it instead of reading twice - // TODO: avoid race condition (another process might change the attribute between reading its length and its value) - ssize_t length = getxattr(file.c_str(), convertor.to_bytes(attributeName).c_str(), nullptr, 0); - if (length > 0) { - std::vector buffer(length + 1); - getxattr(file.c_str(), convertor.to_bytes(attributeName).c_str(), buffer.data(), buffer.size()); - return convertor.from_bytes(buffer.data()); - } else { - return L""; - } - } - public: - void process(std::istream& input, std::ostream& output) { + void process(std::istream& input, std::ostream& output, Configuration& configuration) { std::shared_ptr writer(Factory::create(output)); - // TODO: redesign: parametrized from CLI + groups of information fetched together and used for multiple attributes - bool enableName = true; - bool enableExists = false; - bool enableNameAbsolute = false; - bool enableNameCanonical = false; - bool enableType = true; - bool enableSize = true; - bool enableOwner = true; - bool enableGroup = true; - bool enableXattrUrl = true; // just a demo - std::vector attributesMetadata; - if (enableName) attributesMetadata.push_back({L"name", TypeId::STRING}); - if (enableExists) attributesMetadata.push_back({L"exists", TypeId::BOOLEAN}); - if (enableNameAbsolute) attributesMetadata.push_back({L"name_absolute", TypeId::STRING}); - if (enableNameCanonical) attributesMetadata.push_back({L"name_canonical", TypeId::STRING}); - if (enableType) attributesMetadata.push_back({L"type", TypeId::STRING}); - if (enableSize) attributesMetadata.push_back({L"size", TypeId::INTEGER}); - if (enableOwner) attributesMetadata.push_back({L"owner", TypeId::STRING}); - if (enableGroup) attributesMetadata.push_back({L"group", TypeId::STRING}); - if (enableXattrUrl) attributesMetadata.push_back({L"xattr_url", TypeId::STRING}); + for (RequestedField field : configuration.fields) { + AttributeFinder* finder = attributeFinders[field.group]; + if (finder) for (AttributeMetadata m : finder->toMetadata(field)) attributesMetadata.push_back(m); + else throw RelpipeWriterException(L"Unsupported field group: " + field.group); + } writer->startRelation(L"filesystem", attributesMetadata, true); + for (std::stringstream originalName; readNext(input, originalName); reset(originalName)) { - if (enableName) writer->writeAttribute(convertor.from_bytes(originalName.str())); + fs::path file(originalName.str()); bool exists = false; @@ -140,46 +96,20 @@ // we probably do not have permissions to given directory → pretend that the file does not exist } - if (exists) { - if (enableExists) writer->writeAttribute(L"true"); - if (enableNameAbsolute) writer->writeAttribute(fs::absolute(file).wstring()); - if (enableNameCanonical) writer->writeAttribute(fs::canonical(file).wstring()); - if (enableType) writer->writeAttribute(getType(file)); - if (enableSize) { - integer_t size = fs::is_regular_file(file) ? fs::file_size(file) : 0; - writer->writeAttribute(&size, typeid (size)); - } + for (auto& finder : attributeFinders) finder.second->startFile(file); - if (enableOwner || enableGroup) { - string_t owner; - string_t group; - fetchOwner(file, owner, group); + for (RequestedField field : configuration.fields) { + AttributeFinder* finder = attributeFinders[field.group]; // should not be nullptr, because already checked while writing the relation metadata - if (enableOwner) writer->writeAttribute(owner); - if (enableGroup) writer->writeAttribute(group); - } - - if (enableXattrUrl) writer->writeAttribute(getXattr(file, L"user.xdg.origin.url")); - - } else { - // Only original name was written → write remaining attributes - // TODO: null values (requires adding null support to the format specification) - for (int i = 1; i < attributesMetadata.size(); i++) { - switch (attributesMetadata[i].typeId) { - case TypeId::BOOLEAN: writer->writeAttribute(L"false"); - break; - case TypeId::INTEGER: writer->writeAttribute(L"0"); - break; - case TypeId::STRING: writer->writeAttribute(L""); - break; - default: - throw RelpipeWriterException(L"Unsupported data type."); - - } + if (exists || (field.group == RequestedField::GROUP_FILE && field.name == FileAttributeFinder::FIELD_PATH_ORIGINAL)) { + finder->writeField(writer.get(), field); + } else { + finder->writeEmptyField(writer.get(), field); } } + + for (auto& finder : attributeFinders) finder.second->endFile(); } - } }; diff -r 62eac7ab4cf4 -r d44ed75822e7 src/RequestedField.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/RequestedField.h Wed Jan 16 17:23:05 2019 +0100 @@ -0,0 +1,51 @@ +/** + * Relational pipes + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#include + +namespace relpipe { +namespace in { +namespace filesystem { + +using namespace relpipe::writer; + +class RequestedField { +public: + static const string_t GROUP_FILE; + static const string_t GROUP_XATTR; + string_t group; + string_t name; + std::vector aliases; + std::map options; + + RequestedField(const string_t& group, const string_t& name, const std::vector& aliases = {}, const std::map& options = {}) : group(group), name(name), aliases(aliases), options(options) { + } + + virtual ~RequestedField() { + } +}; + +const string_t RequestedField::GROUP_FILE = L"file"; +const string_t RequestedField::GROUP_XATTR = L"xattr"; + +} +} +} diff -r 62eac7ab4cf4 -r d44ed75822e7 src/XattrAttributeFinder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/XattrAttributeFinder.h Wed Jan 16 17:23:05 2019 +0100 @@ -0,0 +1,80 @@ +/** + * Relational pipes + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include + +#include +#include +#include + +#include "RequestedField.h" + +namespace relpipe { +namespace in { +namespace filesystem { + +namespace fs = std::filesystem; +using namespace relpipe::writer; + +class XattrAttributeFinder : public AttributeFinder { +private: + std::wstring_convert> convertor; // TODO: support also other encodings. + + fs::path currentFile; + + string_t getXattr(const fs::path& file, const string_t& attributeName) { + // TODO: review, test on multiple platforms + // TODO: improve documentation in xattr.h in glibc + // TODO: check XATTR_NAME_MAX in limits.h and if it is reasonably small on our system, allocate buffer for it instead of reading twice + // TODO: avoid race condition (another process might change the attribute between reading its length and its value) + ssize_t length = getxattr(file.c_str(), convertor.to_bytes(attributeName).c_str(), nullptr, 0); + if (length > 0) { + std::vector buffer(length + 1); + getxattr(file.c_str(), convertor.to_bytes(attributeName).c_str(), buffer.data(), buffer.size()); + return convertor.from_bytes(buffer.data()); + } else { + return L""; + } + } +public: + + virtual vector toMetadata(const RequestedField& field) override { + if (field.group == RequestedField::GROUP_XATTR) return { AttributeMetadata{field.name, TypeId::STRING}}; + else return {}; + } + + void startFile(const fs::path& file) override { + currentFile = file; + }; + + void endFile() override { + }; + + virtual void writeField(RelationalWriter* writer, const RequestedField& field) override { + if (field.group == RequestedField::GROUP_XATTR) writer->writeAttribute(getXattr(currentFile, field.name)); + } + + virtual ~XattrAttributeFinder() override { + } +}; + +} +} +} \ No newline at end of file diff -r 62eac7ab4cf4 -r d44ed75822e7 src/relpipe-in-filesystem.cpp --- a/src/relpipe-in-filesystem.cpp Sun Jan 13 16:44:11 2019 +0100 +++ b/src/relpipe-in-filesystem.cpp Wed Jan 16 17:23:05 2019 +0100 @@ -1,6 +1,6 @@ /** * Relational pipes - * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) + * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ #include #include "FilesystemCommand.h" +#include "CLIParser.h" using namespace relpipe::cli; using namespace relpipe::writer; @@ -43,8 +44,10 @@ int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR; try { + CLIParser cliParser; + Configuration configuration = cliParser.parse(cli.arguments()); FilesystemCommand command; - command.process(cin, cout); + command.process(cin, cout, configuration); resultCode = CLI::EXIT_CODE_SUCCESS; } catch (RelpipeWriterException e) { fwprintf(stderr, L"Caught Writer exception: %ls\n", e.getMessge().c_str());