Restructure to util
add split Intent and Options
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
89dd5186f5
commit
70ae623a1d
17 changed files with 405 additions and 87 deletions
|
@ -5,7 +5,9 @@ project('xwim', 'cpp',
|
||||||
'b_ndebug=if-release'])
|
'b_ndebug=if-release'])
|
||||||
|
|
||||||
add_global_arguments('-DVERSION='+meson.version(), language: 'cpp')
|
add_global_arguments('-DVERSION='+meson.version(), language: 'cpp')
|
||||||
|
add_global_arguments('-DSPDLOG_FMT_EXTERNAL', language: 'cpp')
|
||||||
|
add_global_arguments('-DFMT_HEADER_ONLY', language: 'cpp')
|
||||||
|
|
||||||
subdir('src')
|
subdir('src')
|
||||||
subdir('doc')
|
subdir('doc')
|
||||||
# subdir('test')
|
subdir('test')
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "Common.hpp"
|
#include "util/Common.hpp"
|
||||||
|
|
||||||
namespace xwim {
|
namespace xwim {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "Common.hpp"
|
#include "util/Common.hpp"
|
||||||
|
|
||||||
namespace xwim {
|
namespace xwim {
|
||||||
|
|
||||||
|
|
52
src/UserOpt.cpp
Normal file
52
src/UserOpt.cpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#include "UserOpt.hpp"
|
||||||
|
|
||||||
|
#include <tclap/ArgException.h>
|
||||||
|
#include <tclap/CmdLine.h>
|
||||||
|
#include <tclap/StdOutput.h>
|
||||||
|
#include <tclap/SwitchArg.h>
|
||||||
|
#include <tclap/UnlabeledMultiArg.h>
|
||||||
|
#include <tclap/ValueArg.h>
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct TCLAP::ArgTraits<std::filesystem::path> {
|
||||||
|
// We use `operator=` here for path construction
|
||||||
|
// because `operator>>` (`ValueLike`) causes a split at
|
||||||
|
// whitespace
|
||||||
|
typedef StringLike ValueCategory;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace xwim {
|
||||||
|
UserOpt::UserOpt(int argc, char** argv) {
|
||||||
|
// clang-format off
|
||||||
|
TCLAP::CmdLine cmd
|
||||||
|
{"xwim - Do What I Mean Extractor", ' ', "0.3.0"};
|
||||||
|
|
||||||
|
TCLAP::SwitchArg arg_compress
|
||||||
|
{"c", "compress", "Compress <files>", cmd, false};
|
||||||
|
|
||||||
|
TCLAP::SwitchArg arg_extract
|
||||||
|
{"x", "extract", "Extract <file>", cmd, false};
|
||||||
|
|
||||||
|
TCLAP::SwitchArg arg_noninteractive
|
||||||
|
{"i", "non-interactive", "Non-interactive, fail on ambiguity", cmd, false};
|
||||||
|
|
||||||
|
TCLAP::ValueArg<fs::path> arg_outfile
|
||||||
|
{"o", "out", "Out <file-or-path>", false, fs::path{}, "A path on the filesystem", cmd};
|
||||||
|
|
||||||
|
TCLAP::UnlabeledMultiArg<fs::path> arg_paths
|
||||||
|
{"files", "Archive to extract or files to compress", true, "A path on the filesystem", cmd};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
cmd.parse(argc, argv);
|
||||||
|
|
||||||
|
this->compress = arg_compress.getValue();
|
||||||
|
this->extract = arg_extract.getValue();
|
||||||
|
this->interactive = arg_extract.getValue();
|
||||||
|
if (arg_outfile.isSet()) this->out = arg_outfile.getValue();
|
||||||
|
|
||||||
|
if (arg_paths.isSet()) {
|
||||||
|
this->paths =
|
||||||
|
set<fs::path>{arg_paths.getValue().begin(), arg_paths.getValue().end()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace xwim
|
22
src/UserOpt.hpp
Normal file
22
src/UserOpt.hpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "util/Common.hpp"
|
||||||
|
|
||||||
|
namespace xwim {
|
||||||
|
using namespace std;
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
struct UserOpt {
|
||||||
|
bool compress;
|
||||||
|
bool extract;
|
||||||
|
bool interactive;
|
||||||
|
std::optional<fs::path> out;
|
||||||
|
std::set<fs::path> paths;
|
||||||
|
|
||||||
|
UserOpt(int argc, char** argv);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xwim
|
|
@ -12,7 +12,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Archiver.hpp"
|
#include "Archiver.hpp"
|
||||||
#include "Common.hpp"
|
#include "util/Common.hpp"
|
||||||
|
|
||||||
namespace xwim {
|
namespace xwim {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
48
src/Xwim.hpp
48
src/Xwim.hpp
|
@ -5,17 +5,61 @@
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "Common.hpp"
|
|
||||||
#include "Archiver.hpp"
|
#include "Archiver.hpp"
|
||||||
|
#include "util/Common.hpp"
|
||||||
|
#include "UserOpt.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 };
|
enum class Action { EXTRACT, COMPRESS };
|
||||||
|
|
||||||
|
struct XwimIntent {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class XwimBuilder {
|
||||||
|
private:
|
||||||
|
UserOpt user_opt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
XwimBuilder(UserOpt user_opt) : user_opt(user_opt){};
|
||||||
|
Xwim build();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Xwim {
|
||||||
|
public:
|
||||||
|
virtual XwimResult dwim() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class XwimCompressor : public Xwim {
|
||||||
|
private:
|
||||||
|
fs::path archive;
|
||||||
|
std::set<fs::path> paths;
|
||||||
|
};
|
||||||
|
|
||||||
|
class XwimExtractor : public Xwim {};
|
||||||
|
|
||||||
|
class XwimConfig {
|
||||||
|
public:
|
||||||
|
Action get_action();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Xwim {
|
||||||
|
private:
|
||||||
|
XwimEngine xwim_engine;
|
||||||
|
UserOpt user_opt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Xwim(UserOpt user_opt);
|
||||||
|
void dwim();
|
||||||
|
}
|
||||||
|
|
||||||
class Xwim {
|
class Xwim {
|
||||||
private:
|
private:
|
||||||
|
|
15
src/XwimConfig.hpp
Normal file
15
src/XwimConfig.hpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace xwim {
|
||||||
|
|
||||||
|
enum class Action { COMPRESS, EXTRACT };
|
||||||
|
|
||||||
|
class XwimConfig {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Action get_action();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
122
src/XwimIntent.cpp
Normal file
122
src/XwimIntent.cpp
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
#include "XwimIntent.hpp"
|
||||||
|
|
||||||
|
#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 <algorithm>
|
||||||
|
#include <exception>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "Archiver.hpp"
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct::TCLAP::ArgTraits<std::filesystem::path> {
|
||||||
|
// `operator=` here for path construction because `operator>>`
|
||||||
|
// (`ValueLike`) causes a split at whitespace
|
||||||
|
typedef StringLike ValueCategory;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace xwim {
|
||||||
|
|
||||||
|
void UserOpt::parse_args(int argc, char** argv) {
|
||||||
|
// clang-format off
|
||||||
|
// TODO: read version from -DVERSION during compilation
|
||||||
|
TCLAP::CmdLine cmd {"xwim - Do What I Mean Extractor", ' ', "0.3.0"};
|
||||||
|
|
||||||
|
TCLAP::SwitchArg arg_compress
|
||||||
|
{"c", "compress", "Compress <files>", cmd, false};
|
||||||
|
|
||||||
|
TCLAP::SwitchArg arg_extract
|
||||||
|
{"x", "extract", "Extract <file>", cmd, false};
|
||||||
|
|
||||||
|
TCLAP::SwitchArg arg_noninteractive
|
||||||
|
{"i", "non-interactive", "Non-interactive, fail on ambiguity", cmd, false};
|
||||||
|
|
||||||
|
TCLAP::ValueArg<path> arg_outfile
|
||||||
|
{"o", "out", "Out <file-or-path>", false, path{}, "A path on the filesystem", cmd};
|
||||||
|
|
||||||
|
TCLAP::UnlabeledMultiArg<path> arg_paths
|
||||||
|
{"files", "Archive to extract or files to compress", true, "A path on the filesystem", cmd};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// TODO: ideally we'd make sure during parsing that compress and extract
|
||||||
|
// cannot both be true
|
||||||
|
|
||||||
|
cmd.parse(argc, argv);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
// Only set things if they are actually parsed from args. Otherwise we'd
|
||||||
|
// override settings set through other means, e.g. config files
|
||||||
|
if (arg_compress.isSet()) { this->compress = arg_compress.getValue(); }
|
||||||
|
if (arg_extract.isSet()) { this->extract = arg_extract.getValue(); }
|
||||||
|
if (arg_noninteractive.isSet()) { this->interactive = !arg_noninteractive.getValue(); }
|
||||||
|
if (arg_outfile.isSet()) { this->out = arg_outfile.getValue(); }
|
||||||
|
if (arg_paths.isSet()) { this->paths = arg_paths.getValue(); }
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserOpt::parse_config(path config) { // TODO
|
||||||
|
spdlog::warn("Config parsing is not implemented");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserIntent UserOpt::guess_intent() {
|
||||||
|
return UserIntent{action_intent(), out_intent(), paths_intent()};
|
||||||
|
}
|
||||||
|
|
||||||
|
Action UserOpt::action_intent() {
|
||||||
|
if (compress && extract) {
|
||||||
|
throw XwimError("Cannot compress and extract simultaneously");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compress) return Action::COMPRESS;
|
||||||
|
if (extract) return Action::EXTRACT;
|
||||||
|
|
||||||
|
bool can_extract_all = std::all_of(
|
||||||
|
paths.begin(), paths.end(), [](path path) { return can_extract(path); });
|
||||||
|
|
||||||
|
if (can_extract_all && !out) {
|
||||||
|
return Action::EXTRACT;
|
||||||
|
} // else if can_extract_all && !is_archive(out) -> EXTRACT
|
||||||
|
|
||||||
|
if (!can_extract_all && out /* && is_archive(out) */) {
|
||||||
|
return Action::COMPRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactive) {
|
||||||
|
std::cout << "Do you want to compress (y/n)? [y] ";
|
||||||
|
char c;
|
||||||
|
std::cin >> c;
|
||||||
|
|
||||||
|
if (c != 'y' && c != 'n' && c != '\n') {
|
||||||
|
throw XwimError("Cannot guess action. Please answer 'y' or 'n'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 'y' || c == '\n') {
|
||||||
|
return Action::COMPRESS;
|
||||||
|
} else if (c == 'n') {
|
||||||
|
return Action::EXTRACT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw XwimError("Cannot guess action (compress/extract)");
|
||||||
|
}
|
||||||
|
|
||||||
|
path UserOpt::out_intent() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
set<path> UserOpt::paths_intent() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xwim
|
38
src/XwimIntent.hpp
Normal file
38
src/XwimIntent.hpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "util/Common.hpp"
|
||||||
|
|
||||||
|
namespace xwim {
|
||||||
|
using namespace std;
|
||||||
|
using std::filesystem::path;
|
||||||
|
|
||||||
|
enum class Action { COMPRESS, EXTRACT };
|
||||||
|
struct UserIntent {
|
||||||
|
Action action;
|
||||||
|
path out;
|
||||||
|
set<path> paths;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UserOpt {
|
||||||
|
private:
|
||||||
|
bool compress = true;
|
||||||
|
bool extract = false;
|
||||||
|
bool interactive = true;
|
||||||
|
optional<path> out = nullopt;
|
||||||
|
vector<path> paths = std::vector<path>{};
|
||||||
|
|
||||||
|
Action action_intent();
|
||||||
|
path out_intent();
|
||||||
|
set<path> paths_intent();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void parse_config(path config);
|
||||||
|
void parse_args(int argc, char** argv);
|
||||||
|
|
||||||
|
UserIntent guess_intent();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xwim
|
|
@ -9,8 +9,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "Archiver.hpp"
|
#include "../Archiver.hpp"
|
||||||
#include "Common.hpp"
|
#include "../util/Common.hpp"
|
||||||
|
|
||||||
namespace xwim {
|
namespace xwim {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
65
src/main.cpp
65
src/main.cpp
|
@ -1,75 +1,20 @@
|
||||||
#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 <optional>
|
||||||
|
|
||||||
#include "Common.hpp"
|
#include "UserOpt.hpp"
|
||||||
#include "Log.hpp"
|
#include "util/Common.hpp"
|
||||||
#include "Xwim.hpp"
|
#include "util/Log.hpp"
|
||||||
|
|
||||||
using namespace xwim;
|
using namespace xwim;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct TCLAP::ArgTraits<std::filesystem::path> {
|
|
||||||
typedef ValueLike ValueCategory;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
log::init();
|
log::init();
|
||||||
|
|
||||||
TCLAP::CmdLine cmd{"xwim - Do What I Mean Extractor", ' ', "0.3.0"};
|
UserOpt user_opt = UserOpt{argc, argv};
|
||||||
|
|
||||||
TCLAP::SwitchArg arg_compress{"c", "compress", "Compress <files>", cmd,
|
|
||||||
false};
|
|
||||||
TCLAP::SwitchArg arg_extract{"x", "extract", "Extract <file>", cmd, false};
|
|
||||||
|
|
||||||
TCLAP::ValueArg<fs::path> arg_outfile{
|
|
||||||
"o", "out", "Out <file-or-path>",
|
|
||||||
false, fs::path{}, "A path on the filesystem",
|
|
||||||
cmd};
|
|
||||||
TCLAP::UnlabeledMultiArg<fs::path> arg_infiles{
|
|
||||||
"Files", "Archive to extract or files to compress", true,
|
|
||||||
"A path on the filesystem", cmd};
|
|
||||||
|
|
||||||
Xwim xwim;
|
|
||||||
|
|
||||||
cmd.parse(argc, argv);
|
|
||||||
|
|
||||||
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, e);
|
|
||||||
} catch (TCLAP::ExitException& e) {
|
|
||||||
exit(e.getExitStatus());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// `none-or-xor` ensured already
|
|
||||||
if (arg_extract.isSet()) xwim.setExtract();
|
|
||||||
if (arg_compress.isSet()) xwim.setCompress();
|
|
||||||
|
|
||||||
if (arg_outfile.isSet()) xwim.setOut(arg_outfile.getValue());
|
|
||||||
if (arg_infiles.isSet()) xwim.setIns(arg_infiles.getValue());
|
|
||||||
|
|
||||||
try {
|
|
||||||
xwim.try_infer();
|
|
||||||
xwim.dwim();
|
|
||||||
} catch (XwimError& e) {
|
|
||||||
spdlog::error(e.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
xwim_src = ['main.cpp', 'Xwim.cpp', 'Archiver.cpp']
|
xwim_src = ['main.cpp', 'Xwim.cpp', 'Archiver.cpp', 'UserOpt.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'
|
||||||
|
|
||||||
xwim_libs = [dependency('libarchive', required: true, static: is_static),
|
xwim_libs = [dependency('libarchive', required: true, static: is_static),
|
||||||
dependency('fmt', required: true, static: is_static),
|
|
||||||
dependency('spdlog', required: true, static: is_static),
|
dependency('spdlog', required: true, static: is_static),
|
||||||
|
dependency('fmt', 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, dependencies: xwim_libs)
|
||||||
|
|
|
@ -2,22 +2,10 @@
|
||||||
gtest_proj = subproject('gtest')
|
gtest_proj = subproject('gtest')
|
||||||
gtest_dep = gtest_proj.get_variable('gtest_main_dep')
|
gtest_dep = gtest_proj.get_variable('gtest_main_dep')
|
||||||
|
|
||||||
xwim_src = ['../src/archive.cpp',
|
# subdir('archives')
|
||||||
'../src/archive_sys.cpp']
|
user_opt_test_exe = executable('user_opt_test_exe',
|
||||||
|
sources: ['user_opt_test.cpp', '../src/UserOpt.cpp'],
|
||||||
subdir('archives')
|
|
||||||
|
|
||||||
archive_test_exe = executable('archive_test_exe',
|
|
||||||
sources: ['archive_test.cpp', xwim_src],
|
|
||||||
include_directories: ['../src'],
|
include_directories: ['../src'],
|
||||||
dependencies: [gtest_dep, xwim_libs])
|
dependencies: [gtest_dep])
|
||||||
|
|
||||||
|
test('user opt parsing test', user_opt_test_exe)
|
||||||
test('archive test', archive_test_exe)
|
|
||||||
|
|
||||||
fileformats_test_exe = executable('fileformats_test_exe',
|
|
||||||
sources: ['fileformats_test.cpp', xwim_src],
|
|
||||||
include_directories: ['../src'],
|
|
||||||
dependencies: [gtest_dep, xwim_libs])
|
|
||||||
|
|
||||||
test('fileformats test', fileformats_test_exe)
|
|
||||||
|
|
90
test/user_opt_test.cpp
Normal file
90
test/user_opt_test.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#include <gtest/gtest-death-test.h>
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "UserOpt.hpp"
|
||||||
|
|
||||||
|
TEST(UserOpt, compress) {
|
||||||
|
using namespace xwim;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
char* args[] = {
|
||||||
|
const_cast<char*>("xwim"),
|
||||||
|
const_cast<char*>("-c"),
|
||||||
|
const_cast<char*>("mandator_paths"),
|
||||||
|
nullptr};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
UserOpt uo = UserOpt{3, args};
|
||||||
|
ASSERT_TRUE(uo.compress);
|
||||||
|
ASSERT_FALSE(uo.extract);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UserOpt, exclusive_actions) {
|
||||||
|
using namespace xwim;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
char* args[] = {
|
||||||
|
const_cast<char*>("xwim"),
|
||||||
|
const_cast<char*>("-c"),
|
||||||
|
const_cast<char*>("-x"),
|
||||||
|
const_cast<char*>("mandatory_paths"),
|
||||||
|
nullptr};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
UserOpt uo = UserOpt{4, args};
|
||||||
|
ASSERT_TRUE(uo.compress);
|
||||||
|
ASSERT_TRUE(uo.extract);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UserOpt, whitespace_in_path) {
|
||||||
|
using namespace xwim;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
char* args[] = {
|
||||||
|
const_cast<char*>("xwim"),
|
||||||
|
const_cast<char*>("-c"),
|
||||||
|
const_cast<char*>("/foo/bar baz/a file"),
|
||||||
|
nullptr};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
UserOpt uo = UserOpt{3, args};
|
||||||
|
ASSERT_TRUE(uo.paths.find(std::filesystem::path("/foo/bar baz/a file")) !=
|
||||||
|
uo.paths.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UserOpt, mixed_output_and_paths) {
|
||||||
|
using namespace xwim;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
char* args[] = {
|
||||||
|
const_cast<char*>("xwim"),
|
||||||
|
const_cast<char*>("-o"),
|
||||||
|
const_cast<char*>("/foo/bar baz/output"),
|
||||||
|
const_cast<char*>("/foo/bar baz/a path"),
|
||||||
|
const_cast<char*>("/foo/bar baz/another path"),
|
||||||
|
nullptr};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
UserOpt uo = UserOpt{5, args};
|
||||||
|
ASSERT_TRUE(uo.paths.find(std::filesystem::path("/foo/bar baz/a path")) !=
|
||||||
|
uo.paths.end());
|
||||||
|
ASSERT_TRUE(uo.paths.find(std::filesystem::path("/foo/bar baz/another path")) !=
|
||||||
|
uo.paths.end());
|
||||||
|
ASSERT_TRUE(uo.out == std::filesystem::path("/foo/bar baz/output"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UserOpt, output_defaults_to_nullopt) {
|
||||||
|
using namespace xwim;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
char* args[] = {
|
||||||
|
const_cast<char*>("xwim"),
|
||||||
|
const_cast<char*>("/foo/bar"),
|
||||||
|
nullptr};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
UserOpt uo = UserOpt{2, args};
|
||||||
|
ASSERT_FALSE(uo.out);
|
||||||
|
}
|
Loading…
Reference in a new issue