4#include "Stroika/Frameworks/StroikaPreComp.h"
11#if qStroika_HasComponent_LZMA
14#if qStroika_HasComponent_zlib
20#include "Stroika/Foundation/Execution/CommandLine.h"
25#include "Stroika/Foundation/Streams/MemoryStream.h"
31#if qStroika_HasComponent_LZMA || qStroika_HasComponent_zlib
35using namespace Stroika::Foundation::Streams;
49 filesystem::path fArchiveFileName;
50 optional<filesystem::path> fOutputDirectory;
51 optional<Sequence<String>> fFiles2Add;
52 optional<bool> fNoFailOnMissingLibrary;
55 using StandardCommandLineOptions::kHelp;
58 .fHelpOptionText =
"just warns when we fail because of missing library"sv};
59 const CommandLine::Option kListO_{.fLongName =
"list"sv, .fHelpOptionText =
"prints all the files in the argument archive"sv};
60 const CommandLine::Option kCreateO_{.fLongName =
"create"sv, .fHelpOptionText =
"creates the argument ARCHIVE-FILE and adds the argument FILE(s) to it"sv};
62 .fLongName =
"extract"sv,
63 .fHelpOptionText =
"extracts all the files from the argument ARCHIVE-FILE and to the output directory specified by --ouptutDirectory "sv};
65 .fHelpOptionText =
"adds to the argument ARCHIVE-FILE and adds the argument FILE(s) to it "sv};
68 .fHelpArgName =
"ARCHIVE-FILE"sv,
69 .fHelpOptionText =
"ARCHIVE-FILE can be the single character - to designate stdin"sv
73 .fSkipFirstNArguments = 1,
74 .fHelpArgName =
"FILE"sv,
76 const CommandLine::Option kOutputDirO_{.fLongName =
"outputDirectory"sv, .fSupportsArgument =
true, .fHelpOptionText =
"(defaulting to .)"sv};
78 const initializer_list<CommandLine::Option> kAllOptions_{
79 kHelp, kNoFailOnMissingO_, kListO_, kCreateO_, kExtractO_, kUpdateO_, kOutputDirO_, kArchiveFileO_, kOtherFilenamesO_,
83 optional<Options_> ParseOptions_ (
int argc,
const char* argv[])
92 cerr <<
ToString (current_exception ()) << endl;
93 cerr << cmdLine.GenerateUsage (kAllOptions_);
94 return optional<Options_>{};
96 if (cmdLine.Has (kHelp)) {
97 cerr << cmdLine.GenerateUsage (kAllOptions_);
98 return optional<Options_>{};
101 if (cmdLine.Has (kListO_)) {
102 result.fOperation = Options_::Operation::eList;
104 else if (cmdLine.Has (kCreateO_)) {
105 result.fOperation = Options_::Operation::eCreate;
107 else if (cmdLine.Has (kExtractO_)) {
108 result.fOperation = Options_::Operation::eExtract;
110 else if (cmdLine.Has (kUpdateO_)) {
111 result.fOperation = Options_::Operation::eUpdate;
114 cerr <<
"Missing operation" << endl;
115 cerr << cmdLine.GenerateUsage (kAllOptions_);
116 return optional<Options_>{};
118 result.fArchiveFileName = Memory::ValueOf (cmdLine.GetArgument (kArchiveFileO_)).
As<filesystem::path> ();
119 result.fFiles2Add = cmdLine.GetArguments (kOtherFilenamesO_);
120 if (
auto o = cmdLine.GetArgument (kOutputDirO_)) {
121 result.fOutputDirectory = o->As<filesystem::path> ();
124 result.fNoFailOnMissingLibrary = cmdLine.Has (kNoFailOnMissingO_);
130 DataExchange::Archive::Reader::Ptr OpenArchive_ (
const filesystem::path& archiveName)
133#if qStroika_HasComponent_LZMA
134 if (
String{archiveName}.
EndsWith (
".7z"sv, Characters::eCaseInsensitive)) {
135 return Archive::_7z::Reader::New (IO::FileSystem::FileInputStream::New (archiveName));
138#if qStroika_HasComponent_zlib
139 if (
String{archiveName}.
EndsWith (
".zip"sv, Characters::eCaseInsensitive)) {
140 return Archive::Zip::Reader::New (IO::FileSystem::FileInputStream::New (archiveName));
148 DataExchange::Archive::Writer::Ptr CreateWritingArchive_ (
const filesystem::path& archiveName)
150#if qStroika_HasComponent_zlib
152 if (
String{archiveName}.
EndsWith (
".zip"sv, Characters::eCaseInsensitive)) {
153 return DataExchange::Archive::Zip::Writer::New (IO::FileSystem::FileOutputStream::New (archiveName));
161 void ListArchive_ (
const filesystem::path& archiveName)
163 for (
String i : OpenArchive_ (archiveName).GetContainedFiles ()) {
167 void ExtractArchive_ (
const filesystem::path& archiveName,
const filesystem::path& toDirectory)
171 DataExchange::Archive::Reader::Ptr archive{OpenArchive_ (archiveName)};
172 for (
String i : archive.GetContainedFiles ()) {
174 filesystem::path trgFileName = toDirectory / srcFileName.
As<filesystem::path> ();
175 BLOB b = archive.GetData (srcFileName);
176 create_directories (trgFileName.parent_path ());
177 IO::FileSystem::FileOutputStream::Ptr ostream = IO::FileSystem::FileOutputStream::New (trgFileName);
181 void CreateArchive_ (
const filesystem::path& archiveName,
const Sequence<String>& files2Add)
185 DataExchange::Archive::Writer::Ptr archive = CreateWritingArchive_ (archiveName);
186 for (
String f2a : files2Add) {
187 archive.Add (f2a, IO::FileSystem::FileInputStream::New (f2a.As<filesystem::path> ()).ReadAll ());
192int main (
int argc,
const char* argv[])
195 if (optional<Options_> o = ParseOptions_ (argc, argv)) {
197 switch (o->fOperation) {
198 case Options_::Operation::eList:
199 ListArchive_ (o->fArchiveFileName);
201 case Options_::Operation::eExtract:
202 ExtractArchive_ (o->fArchiveFileName, o->fOutputDirectory.value_or (
"."sv));
204 case Options_::Operation::eCreate:
205 CreateArchive_ (o->fArchiveFileName, o->fFiles2Add.value_or (
Sequence<String>{}));
208 cerr <<
"that option NYI" << endl;
213 cerr <<
"Exception: " << Characters::ToString (current_exception ()) << endl;
217 String exceptMsg = Characters::ToString (current_exception ());
218 cerr <<
"Exception: " << exceptMsg <<
" - terminating..." << endl;
219 if (o->fNoFailOnMissingLibrary.value_or (
false)) {
220#if !qStroika_HasComponent_LZMA || !qStroika_HasComponent_zlib
221 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 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(const Iterable< Option > &options) const
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...