4#include "Stroika/Frameworks/StroikaPreComp.h"
12#include "Stroika/Foundation/Execution/CommandLine.h"
13#if qStroika_HasComponent_LZMA
16#if qStroika_HasComponent_zlib
23#include "Stroika/Foundation/Streams/MemoryStream.h"
29#if qStroika_HasComponent_LZMA || qStroika_HasComponent_zlib
32using namespace Stroika::Foundation::Streams;
46 filesystem::path fArchiveFileName;
47 optional<filesystem::path> fOutputDirectory;
48 optional<Sequence<String>> fFiles2Add;
49 optional<bool> fNoFailOnMissingLibrary;
52 using Execution::StandardCommandLineOptions::kHelp;
55 .fHelpOptionText =
"just warns when we fail because of missing library"sv};
58 .fHelpOptionText =
"creates the argument ARCHIVE-FILE and adds the argument FILE(s) to it"sv};
60 .fLongName =
"extract"sv,
61 .fHelpOptionText =
"extracts all the files from the argument ARCHIVE-FILE and to the output directory specified by --ouptutDirectory "sv};
63 .fHelpOptionText =
"adds to the argument ARCHIVE-FILE and adds the argument FILE(s) to it "sv};
67 .fHelpArgName =
"ARCHIVE-FILE"sv,
68 .fHelpOptionText =
"ARCHIVE-FILE can be the single character - to designate stdin"sv
73 .fHelpArgName =
"FILE"sv,
75 const Execution::CommandLine::Option kOutputDirO_{.fLongName =
"outputDirectory"sv, .fSupportsArgument =
true, .fHelpOptionText =
"(defaulting to .)"sv};
77 const initializer_list<Execution::CommandLine::Option> kAllOptions_{
78 kHelp, kNoFailOnMissingO_, kListO_, kCreateO_, kExtractO_, kUpdateO_, kOutputDirO_, kArchiveFileO_, kOtherFilenamesO_,
82 optional<Options_> ParseOptions_ (
int argc,
const char* argv[])
91 cerr << cmdLine.GenerateUsage (kAllOptions_).AsNarrowSDKString ();
92 return optional<Options_>{};
94 if (cmdLine.Has (kHelp)) {
95 cerr << cmdLine.GenerateUsage (kAllOptions_).AsNarrowSDKString ();
96 return optional<Options_>{};
99 if (cmdLine.Has (kListO_)) {
100 result.fOperation = Options_::Operation::eList;
102 else if (cmdLine.Has (kCreateO_)) {
103 result.fOperation = Options_::Operation::eCreate;
105 else if (cmdLine.Has (kExtractO_)) {
106 result.fOperation = Options_::Operation::eExtract;
108 else if (cmdLine.Has (kUpdateO_)) {
109 result.fOperation = Options_::Operation::eUpdate;
112 cerr <<
"Missing operation" << endl;
113 cerr << cmdLine.GenerateUsage (kAllOptions_).AsNarrowSDKString ();
114 return optional<Options_>{};
116 result.fArchiveFileName = Memory::ValueOf (cmdLine.GetArgument (kArchiveFileO_)).As<filesystem::path> ();
117 if (
auto o = cmdLine.GetArgument (kOutputDirO_)) {
118 result.fOutputDirectory = o->As<filesystem::path> ();
121 result.fNoFailOnMissingLibrary = cmdLine.Has (kNoFailOnMissingO_);
130#if qStroika_HasComponent_LZMA
131 if (
String{archiveName}.
EndsWith (
".7z"sv, Characters::eCaseInsensitive)) {
132 return move (Archive::_7z::Reader{IO::FileSystem::FileInputStream::New (archiveName)});
135#if qStroika_HasComponent_zlib
136 if (
String{archiveName}.
EndsWith (
".zip"sv, Characters::eCaseInsensitive)) {
137 return move (Archive::Zip::Reader{IO::FileSystem::FileInputStream::New (archiveName)});
145 void ListArchive_ (
const filesystem::path& archiveName)
147 for (
String i : OpenArchive_ (archiveName).GetContainedFiles ()) {
148 cout << i.AsNarrowSDKString () << endl;
151 void ExtractArchive_ (
const filesystem::path& archiveName,
const filesystem::path& toDirectory)
154 DbgTrace (
"(archiveName={}, toDir={})"_f, archiveName, toDirectory);
156 for (
String i : archive.GetContainedFiles ()) {
158 filesystem::path trgFileName = toDirectory / srcFileName.
As<filesystem::path> ();
160 BLOB b = archive.GetData (srcFileName);
162 create_directories (trgFileName.parent_path ());
163 IO::FileSystem::FileOutputStream::Ptr ostream = IO::FileSystem::FileOutputStream::New (trgFileName);
169int main (
int argc,
const char* argv[])
172 if (optional<Options_> o = ParseOptions_ (argc, argv)) {
174 switch (o->fOperation) {
175 case Options_::Operation::eList:
176 ListArchive_ (o->fArchiveFileName);
178 case Options_::Operation::eExtract:
179 ExtractArchive_ (o->fArchiveFileName, o->fOutputDirectory.value_or (
"."sv));
182 cerr <<
"that option NYI" << endl;
187 String exceptMsg = Characters::ToString (current_exception ());
192 String exceptMsg = Characters::ToString (current_exception ());
193 cerr <<
"Exception: " << exceptMsg.
AsNarrowSDKString () <<
" - terminating..." << endl;
194 if (o->fNoFailOnMissingLibrary.value_or (
false)) {
195#if !qStroika_HasComponent_LZMA || !qStroika_HasComponent_zlib
196 if (exceptMsg.
Contains (
"Unrecognized format"sv)) {
variant< Equals > Operation
#define Stroika_Foundation_Debug_OptionalizeTraceArgs(...)
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual bool Contains(Character c, CompareOptions co=eWithCase) const
nonvirtual string AsNarrowSDKString() const
nonvirtual bool EndsWith(const Character &c, CompareOptions co=eWithCase) const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
nonvirtual void Validate(Iterable< Option > options) const
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...