diff --git a/src/UserIntent.cpp b/src/UserIntent.cpp index ed0f4b5..f49ba2e 100644 --- a/src/UserIntent.cpp +++ b/src/UserIntent.cpp @@ -7,97 +7,113 @@ #include "Archiver.hpp" namespace xwim { + unique_ptr make_compress_intent(const UserOpt &userOpt) { + if (userOpt.paths.size() == 1) { + return make_unique( + CompressSingleIntent{ + *userOpt.paths.begin(), + userOpt.out + }); + } + + if (!userOpt.out.has_value()) { + throw XwimError("Cannot guess output for multiple targets"); + } + + return make_unique( + CompressManyIntent{ + userOpt.paths, + userOpt.out.value() + }); + } + + unique_ptr make_extract_intent(const UserOpt &userOpt) { + for (const path& p: userOpt.paths) { + if (!can_handle_archive(p)) { + throw XwimError("Cannot extract path {}", p); + } + } + + return make_unique( + ExtractIntent{ + userOpt.paths, + userOpt.out + }); + } + + unique_ptr try_infer_compress_intent(const UserOpt &userOpt) { + if(!userOpt.out.has_value()) { + spdlog::debug("No provided"); + if(userOpt.paths.size() != 1) { + spdlog::debug("Not a single-path compression. Cannot guess for many-path compression"); + return nullptr; + } + + spdlog::debug("Only one provided. Assume single-path compression."); + return make_unique(CompressSingleIntent{*userOpt.paths.begin(), userOpt.out}); + } + + spdlog::debug(" provided: {}", userOpt.out.value()); + if(can_handle_archive(userOpt.out.value())) { + spdlog::debug("{} given and a known archive format, assume compression", userOpt.out.value()); + return make_compress_intent(userOpt); + } + + spdlog::debug("Cannot compress multiple paths without a user-provided output archive"); + return nullptr; + } + + unique_ptr try_infer_extract_intent(const UserOpt &userOpt) { + bool can_extract_all = std::all_of( + userOpt.paths.begin(), userOpt.paths.end(), + [](const path &path) { return can_handle_archive(path); }); + + if(!can_extract_all) { + spdlog::debug("Cannot extract all provided . Assume this is not an extraction."); + for(const path& p: userOpt.paths) { + if(!can_handle_archive(p)) { + spdlog::debug("Cannot handle {}", p); + } + } + + return nullptr; + } + + if(userOpt.out.has_value() && can_handle_archive(userOpt.out.value())) { + spdlog::debug("Could extract all provided . But also {} looks like an archive. Ambiguous intent. Assume this is not an extraction.", userOpt.out.value()); + return nullptr; + } + + spdlog::debug("Could extract all provided . But also looks like an archive. Ambiguous intent. Assume this is not an extraction."); + return make_extract_intent(userOpt); + } unique_ptr make_intent(const UserOpt &userOpt) { if (userOpt.wants_compress() && userOpt.wants_extract()) { throw XwimError("Cannot compress and extract simultaneously"); } - if(userOpt.paths.size() == 0) { + if(userOpt.paths.empty()) { throw XwimError("No input given..."); } - // compression intent explicitly specified - if (userOpt.wants_compress()) { - if (userOpt.paths.size() == 1) { - return make_unique( - CompressSingleIntent{ - *userOpt.paths.begin(), - userOpt.out - }); - } + // explicitly specified intent + if (userOpt.wants_compress()) return make_compress_intent(userOpt); + if (userOpt.wants_extract()) return make_extract_intent(userOpt); - if (!userOpt.out.has_value()) { - throw XwimError("Cannot guess output for multiple targets"); - } + spdlog::info("Intent not explicitly provided, trying to infer intent"); - return make_unique( - CompressManyIntent{ - userOpt.paths, - userOpt.out.value() - }); + if(auto intent = try_infer_extract_intent(userOpt)) { + spdlog::info("Extraction intent inferred"); + return intent; } + spdlog::info("Cannot infer extraction intent"); - // extraction intent explicitly specified - if (userOpt.wants_extract()) { - for (path p: userOpt.paths) { - if (!can_handle_archive(p)) { - throw XwimError("Cannot extract path {}", p); - } - } - - return make_unique( - ExtractIntent{ - userOpt.paths, - userOpt.out - }); + if(auto intent = try_infer_compress_intent(userOpt)) { + spdlog::info("Compression intent inferred"); + return intent; } + spdlog::info("Cannot infer compression intent"); - // no intent explicitly specified, try to infer from input - - bool can_extract_all = std::all_of( - userOpt.paths.begin(), userOpt.paths.end(), - [](path path) { - return can_handle_archive(path); - }); - - bool is_out_archive = userOpt.out.has_value() && can_handle_archive(userOpt.out.value()); - - // out is explicitly specified and an archive, assume we want compression - if(is_out_archive) { - if(userOpt.paths.size() == 1) { - return make_unique( - CompressSingleIntent{ - *userOpt.paths.begin(), - userOpt.out - }); - } - - return make_unique( - CompressManyIntent{ - userOpt.paths, - userOpt.out.value() // this is ok is_out_archive checks for has_value() - } - ); - } - - // all inputs are extractable archives, assume extraction intent - if (can_extract_all) { - return make_unique( - ExtractIntent{ - userOpt.paths, - userOpt.out - }); - } - - // at this point all we can hope for is that the intention is a single-path compression: - // we don't know how to extract it; we don't know (and can't guess) output for many-path compression; - if(userOpt.paths.size() == 1) { - return make_unique( - CompressSingleIntent{ - *userOpt.paths.begin(), - userOpt.out - }); - } throw XwimError("Cannot guess intent"); } diff --git a/src/UserIntent.hpp b/src/UserIntent.hpp index 567050d..4750199 100644 --- a/src/UserIntent.hpp +++ b/src/UserIntent.hpp @@ -32,9 +32,9 @@ private: public: ExtractIntent(set archives, optional out): archives(archives), out(out) {}; - ~ExtractIntent() = default; + ~ExtractIntent() override = default; - void execute(); + void execute() override; }; /** @@ -55,14 +55,13 @@ public: class CompressSingleIntent : public UserIntent { private: path in; - optional out; + optional out; public: - CompressSingleIntent(path in, optional out) : UserIntent(), in(in), out(out) {}; + CompressSingleIntent(path in, optional out) : UserIntent(), in(in), out(out) {}; + ~CompressSingleIntent() override = default; - ~CompressSingleIntent() = default; - - void execute(); + void execute() override; }; /** @@ -81,9 +80,9 @@ private: public: CompressManyIntent(set in_paths, path out): UserIntent(), in_paths(in_paths), out(out) {}; - ~CompressManyIntent() = default; + ~CompressManyIntent() override = default; - void execute(); + void execute() override; }; } // namespace xwim