Restructure ExtractIntent
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
92ac6586de
commit
1523f83a6b
2 changed files with 85 additions and 66 deletions
|
@ -120,65 +120,81 @@ unique_ptr<UserIntent> make_intent(const UserOpt &userOpt) {
|
||||||
throw XwimError("Cannot guess intent");
|
throw XwimError("Cannot guess intent");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractIntent::execute() {
|
void ExtractIntent::dwim_reparent(const path &out) {
|
||||||
bool has_out = this->out.has_value();
|
// move extraction if extraction resulted in only one entry and that entries
|
||||||
bool is_single = this->archives.size() == 1;
|
// name is already the stripped archive name, i.e. reduce unnecessary nesting
|
||||||
|
|
||||||
for (const path &p : this->archives) {
|
|
||||||
unique_ptr<Archiver> archiver = make_archiver(p);
|
|
||||||
path out;
|
|
||||||
|
|
||||||
if (has_out) {
|
|
||||||
if (is_single) { // just dump content of archive into `out`
|
|
||||||
std::filesystem::create_directories(this->out.value());
|
|
||||||
out = this->out.value();
|
|
||||||
} else { // create an `out` folder and extract inside there
|
|
||||||
std::filesystem::create_directories(this->out.value());
|
|
||||||
out = this->out.value() / strip_archive_extension(p);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out = std::filesystem::current_path() / strip_archive_extension(p);
|
|
||||||
std::filesystem::create_directories(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
archiver->extract(p, out);
|
|
||||||
|
|
||||||
// move folder if only one entry and that entries name is already
|
|
||||||
// the stripped archive name
|
|
||||||
auto dit = std::filesystem::directory_iterator(out);
|
auto dit = std::filesystem::directory_iterator(out);
|
||||||
|
auto dit_path = dit->path();
|
||||||
|
|
||||||
if (dit == std::filesystem::directory_iterator()) {
|
if (dit == std::filesystem::directory_iterator()) {
|
||||||
spdlog::debug("Archive is empty");
|
spdlog::debug(
|
||||||
} else if (is_directory(dit->path())) {
|
"Cannot flatten extraction folder: extraction folder is empty");
|
||||||
auto first_path = dit->path();
|
return;
|
||||||
auto next_entry = next(dit);
|
}
|
||||||
|
|
||||||
|
if (!is_directory(dit_path)) {
|
||||||
|
spdlog::debug("Cannot flatten extraction folder: {} is not a directory",
|
||||||
|
dit_path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next(dit) != std::filesystem::directory_iterator()) {
|
||||||
|
spdlog::debug("Cannot flatten extraction folder: multiple items extracted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::filesystem::equivalent(dit_path.filename(), out.filename())) {
|
||||||
|
spdlog::debug(
|
||||||
|
"Cannot flatten extraction folder: archive entry differs from archive "
|
||||||
|
"name [extraction folder: {}, archive entry: {}]",
|
||||||
|
out.filename(), dit_path.filename());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::debug("Output folder [{}] is equivalent to archive entry [{}]", out,
|
||||||
|
dit_path);
|
||||||
|
spdlog::info("Flattening extraction folder");
|
||||||
|
|
||||||
if (next_entry == std::filesystem::directory_iterator()) {
|
|
||||||
spdlog::debug("Archive has single entry which is a directory");
|
|
||||||
if (std::filesystem::equivalent(first_path.filename(),
|
|
||||||
out.filename())) {
|
|
||||||
spdlog::debug("Archive entry named like archive");
|
|
||||||
int i = rand_int(0, 100000);
|
int i = rand_int(0, 100000);
|
||||||
|
|
||||||
path tmp_out = path{out};
|
path tmp_out = path{out};
|
||||||
tmp_out.concat(fmt::format(".xwim{}", i));
|
tmp_out.concat(fmt::format(".xwim{}", i));
|
||||||
|
spdlog::debug("Move {} to {}", dit_path, tmp_out);
|
||||||
spdlog::debug("Moving {} to {}", first_path, tmp_out);
|
std::filesystem::rename(dit_path, tmp_out);
|
||||||
std::filesystem::rename(first_path, tmp_out);
|
spdlog::debug("Remove parent path {}", out);
|
||||||
spdlog::debug("Removing parent {}", out);
|
|
||||||
std::filesystem::remove(out);
|
std::filesystem::remove(out);
|
||||||
spdlog::debug("Moving {} to {}", tmp_out, out);
|
spdlog::debug("Moving {} to {}", tmp_out, out);
|
||||||
std::filesystem::rename(tmp_out, out);
|
std::filesystem::rename(tmp_out, out);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
path ExtractIntent::out_path(const path &p) {
|
||||||
spdlog::debug("Archive entry differs from archive name");
|
if (!this->out.has_value()) {
|
||||||
|
// not out path given, create from archive name
|
||||||
|
path out = std::filesystem::current_path() / strip_archive_extension(p);
|
||||||
|
create_directories(out);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
spdlog::debug("Archive has multiple entries");
|
if (this->archives.size() == 1) {
|
||||||
|
// out given and only one archive to extract, just extract into `out`
|
||||||
|
create_directories(this->out.value());
|
||||||
|
return this->out.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// out given and multiple archives to extract, create subfolder
|
||||||
|
// for each archive
|
||||||
|
create_directories(this->out.value());
|
||||||
|
path out = this->out.value() / strip_archive_extension(p);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtractIntent::execute() {
|
||||||
|
for (const path &p : this->archives) {
|
||||||
|
std::unique_ptr<Archiver> archiver = make_archiver(p);
|
||||||
|
path out = this->out_path(p);
|
||||||
|
archiver->extract(p, out);
|
||||||
|
this->dwim_reparent(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
path CompressSingleIntent::out_path() {
|
path CompressSingleIntent::out_path() {
|
||||||
if (this->out.has_value()) {
|
if (this->out.has_value()) {
|
||||||
|
@ -206,5 +222,5 @@ void CompressManyIntent::execute() {
|
||||||
|
|
||||||
unique_ptr<Archiver> archiver = make_archiver(this->out);
|
unique_ptr<Archiver> archiver = make_archiver(this->out);
|
||||||
archiver->compress(this->in_paths, this->out);
|
archiver->compress(this->in_paths, this->out);
|
||||||
};
|
}
|
||||||
} // namespace xwim
|
} // namespace xwim
|
||||||
|
|
|
@ -30,6 +30,9 @@ private:
|
||||||
set<path> archives;
|
set<path> archives;
|
||||||
optional<path> out;
|
optional<path> out;
|
||||||
|
|
||||||
|
void dwim_reparent(const path& out);
|
||||||
|
path out_path(const path& p);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExtractIntent(set<path> archives, optional<path> out): archives(archives), out(out) {};
|
ExtractIntent(set<path> archives, optional<path> out): archives(archives), out(out) {};
|
||||||
~ExtractIntent() override = default;
|
~ExtractIntent() override = default;
|
||||||
|
|
Loading…
Reference in a new issue