This commit is contained in:
Armin Friedl 2021-05-10 18:49:01 +02:00
parent 0663f42aec
commit d95f3d0f32
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
5 changed files with 97 additions and 86 deletions

View file

@ -1,59 +1,46 @@
#include <tclap/ArgException.h> #pragma once
#include <tclap/CmdLine.h>
#include <tclap/StdOutput.h> #include <fmt/core.h>
#include <tclap/SwitchArg.h> #include <fmt/format.h>
#include <tclap/UnlabeledMultiArg.h>
#include <tclap/ValueArg.h>
#include <filesystem> #include <filesystem>
#include <optional>
template <> #include <set>
struct TCLAP::ArgTraits<std::filesystem::path> {
typedef ValueLike ValueCategory;
};
namespace xwim { namespace xwim {
namespace fs = std::filesystem; enum class Action { EXTRACT, COMPRESS };
class Opt { struct UserOpt {
private: std::optional<Action> action;
// clang-format off bool interactive;
TCLAP::CmdLine cmd_line std::optional<std::filesystem::path> out;
{"xwim - Do What I Mean Extractor", ' ', "0.5.0"}; std::set<std::filesystem::path> paths;
TCLAP::SwitchArg arg_compress
{"c", "compress", "Compress <files>", cmd_line, false};
TCLAP::SwitchArg arg_extract
{"x", "extract", "Extract <file>", cmd_line, false};
TCLAP::ValueArg<fs::path> arg_out
{"o", "out", "Out <path>", false, fs::path{}, "A path on the filesystem", cmd_line};
TCLAP::UnlabeledMultiArg<fs::path> arg_paths
{"Paths", "Filesystem paths to extract or compress", true, "A path on the filesystem", cmd_line};
// clang-format on
public:
void parse(int argc, char** argv) { cmd_line.parse(argc, argv); }
void validate() {
if (arg_extract.isSet() && arg_compress.isSet()) {
// This is a bit ugly but `none-or-xor` only available in
// tclap-1.4 which is not well supported in current
// distributions
auto out = TCLAP::StdOutput{};
TCLAP::ArgException e{
"Cannot compress `-c` and extract `-x` simultaneously"};
try {
out.failure(cmd_line, e);
} catch (TCLAP::ExitException& e) {
exit(e.getExitStatus());
}
}
}
}; };
struct XwimConfig {
Action action;
std::filesystem::path output;
std::set<std::filesystem::path> input;
};
XwimConfig guess_wim(UserOpt user_opt);
void do_wim(XwimConfig);
} // namespace xwim } // namespace xwim
template <>
struct fmt::formatter<xwim::Action> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
auto format(const xwim::Action& action, FormatContext& ctx) {
switch (action) {
case xwim::Action::EXTRACT:
return format_to(ctx.out(), "EXTRACT");
case xwim::Action::COMPRESS:
return format_to(ctx.out(), "COMPRESS");
};
return format_to(ctx.out(), "");
}
};

View file

@ -14,10 +14,6 @@
#include "Archiver.hpp" #include "Archiver.hpp"
#include "Common.hpp" #include "Common.hpp"
namespace xwim {
using namespace std;
namespace fs = std::filesystem;
#if defined(unix) || defined(__unix__) || defined(__unix) #if defined(unix) || defined(__unix__) || defined(__unix)
std::string default_extension = ".tar.gz"; std::string default_extension = ".tar.gz";
#elif defined(_win32) || defined(__win32__) || defined(__windows__) #elif defined(_win32) || defined(__win32__) || defined(__windows__)
@ -26,6 +22,10 @@ std::string default_extension = ".zip";
std::string default_extension = ".zip"; std::string default_extension = ".zip";
#endif #endif
namespace xwim {
using namespace std;
namespace fs = std::filesystem;
Xwim::Xwim() : action{Action::UNKNOWN} {} Xwim::Xwim() : action{Action::UNKNOWN} {}
void Xwim::try_infer() { void Xwim::try_infer() {

View file

@ -9,13 +9,14 @@
#include <stdexcept> #include <stdexcept>
#include "Common.hpp" #include "Common.hpp"
#include "Opt.hpp"
#include "Archiver.hpp" #include "Archiver.hpp"
namespace xwim { namespace xwim {
using namespace std; using namespace std;
namespace fs = std::filesystem; namespace fs = std::filesystem;
enum class Action { UNKNOWN, EXTRACT, COMPRESS }; Xwim xwim(UserOpt user_opt);
class Xwim { class Xwim {
private: private:
@ -43,21 +44,3 @@ class Xwim {
}; };
} // namespace xwim } // namespace xwim
template <>
struct fmt::formatter<xwim::Action> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
auto format(const xwim::Action& action, FormatContext& ctx) {
switch (action) {
case xwim::Action::UNKNOWN:
return format_to(ctx.out(), "UNKNOWN");
case xwim::Action::EXTRACT:
return format_to(ctx.out(), "EXTRACT");
case xwim::Action::COMPRESS:
return format_to(ctx.out(), "COMPRESS");
};
return format_to(ctx.out(), "");
}
};

View file

@ -1,31 +1,69 @@
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/logger.h> #include <spdlog/logger.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <tclap/ArgException.h>
#include <tclap/CmdLine.h>
#include <tclap/StdOutput.h>
#include <tclap/SwitchArg.h>
#include <tclap/UnlabeledMultiArg.h>
#include <tclap/ValueArg.h>
#include <cstdlib> #include <cstdlib>
#include <filesystem> #include <filesystem>
#include <memory> #include <memory>
#include <optional>
#include "Common.hpp" #include "Common.hpp"
#include "Opt.hpp"
#include "Log.hpp" #include "Log.hpp"
#include "Opt.hpp"
#include "Xwim.hpp" #include "Xwim.hpp"
using namespace xwim; using namespace xwim;
using namespace std; using namespace std;
template <>
struct TCLAP::ArgTraits<std::filesystem::path> {
typedef ValueLike ValueCategory;
};
UserOpt parse_args(int argc, char** argv) {
// clang-format off
TCLAP::CmdLine cmd_line
{"xwim - Do What I Mean Extractor", ' ', "0.5.0"};
TCLAP::SwitchArg arg_compress
{"c", "compress", "Compress <files>", cmd_line, false};
TCLAP::SwitchArg arg_extract
{"x", "extract", "Extract <files>", cmd_line, false};
TCLAP::SwitchArg arg_noninteractive
{"ni", "noninteractive", "Fail if action cannot be determined", cmd_line, false};
TCLAP::ValueArg<std::filesystem::path> arg_out
{"o", "out", "Out <path>", false, std::filesystem::path{}, "A path on the filesystem", cmd_line};
TCLAP::UnlabeledMultiArg<std::filesystem::path> arg_paths
{"Paths", "Filesystem paths to extract or compress", true, "A path on the filesystem", cmd_line};
// clang-format on
cmd_line.parse(argc, argv);
UserOpt user_opt;
if(arg_compress.getValue()) user_opt.action = Action::COMPRESS;
if(arg_extract.getValue()) user_opt.action = Action::EXTRACT;
if(arg_out.isSet()) user_opt.out = arg_out.getValue();
user_opt.interactive = !arg_noninteractive.getValue();
user_opt.paths = std::set<fs::path>{arg_paths.getValue().begin(), arg_paths.getValue().end()};
return user_opt;
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
log::init(); log::init();
Opt opt; UserOpt user_opt = parse_args(argc, argv);
opt.parse(argc, argv); XwimConfig xwim_config = guess_wim(user_opt);
opt.validate(); do_wim(xwim_config);
Xwim xwim{};
try {
xwim.dwim();
} catch (XwimError& e) {
spdlog::error(e.what());
}
} }

View file

@ -1,4 +1,5 @@
xwim_src = ['main.cpp', 'Xwim.cpp', 'Archiver.cpp'] xwim_src = ['main.cpp', 'Xwim.cpp', 'Archiver.cpp']
xwim_dwim = ['dwim/Opt.cpp']
xwim_archiver = ['archiver/LibArchiver.cpp'] xwim_archiver = ['archiver/LibArchiver.cpp']
is_static = get_option('default_library')=='static' is_static = get_option('default_library')=='static'
@ -8,4 +9,6 @@ xwim_libs = [dependency('libarchive', required: true, static: is_static),
dependency('spdlog', required: true, static: is_static), dependency('spdlog', required: true, static: is_static),
dependency('tclap', required: true, static: is_static)] dependency('tclap', required: true, static: is_static)]
executable('xwim', xwim_src+xwim_archiver, dependencies: xwim_libs) executable('xwim',
xwim_src+xwim_archiver+xwim_dwim,
dependencies: xwim_libs)