extract: add options to operate batch-processing

This commit allows for suppressing failed extract operations by
setting the 'ignore_failures' attribute in the 'config' node.
It is intended for operating the component in batch-mode where
multiple archives need to be extracted but failing to extract
some of them can by ignored. The default value of this option
is 'false'.

It also adds the 'stop_on_failure' attribute that instructs
the component to stop processing any following archives after
it already has failed to do so. The default value of this
option is 'true' to preserve the current behavior.

Issue #5326.
This commit is contained in:
Josef Söntgen 2024-08-20 15:28:46 +02:00 committed by Christian Helmuth
parent 9b01ca3086
commit 1e933cc490
2 changed files with 39 additions and 6 deletions

View File

@ -26,3 +26,15 @@ how many path elements should be removed from the files stored in the archive
during extraction. In this example the top directory would be omitted. The
'name' attribute is used for naming compressed files that are not part of an
archive.
The 'ignore_failures' attribute of the 'config' node instructs the component
to attempt to extract all given archives and even in the case of failures to
report success. This option is intended for batch-operations where only the
overall success is of importance.
The 'stop_on_failure' attribute of the 'config' node instructs the component
to stop processing any archive after the extraction of one has already failed.
In the default configuration 'ignore_failures' is 'false' while 'stop_on_failure'
is 'true' so processing a batch of archives will stop on the first failure and
leads to exiting with a non-zero exit-value.

View File

@ -242,14 +242,28 @@ struct Extract::Main
bool _verbose = false;
void _process_config()
bool _ignore_failures = false;
bool _stop_on_failure = false;
bool _process_config()
{
Xml_node const config = _config.xml();
_verbose = config.attribute_value("verbose", false);
_ignore_failures = config.attribute_value("ignore_failures", false);
_stop_on_failure = config.attribute_value("stop_on_failure", true);
bool overall_success = true;
config.for_each_sub_node("extract", [&] (Xml_node node) {
/* ignore any following archives after one failed */
if (!overall_success && _stop_on_failure)
return;
Path const src_path = node.attribute_value("archive", Path());
Path const dst_path = node.attribute_value("to", Path());
Raw_name const raw_name = node.attribute_value("name", Raw_name());
@ -280,20 +294,27 @@ struct Extract::Main
catch (Extracted_archive::Write_failed) {
warning("writing to directory ", dst_path, " failed"); }
/* abort on first error */
if (!success)
throw Exception();
if (!success) {
overall_success = false;
return;
}
if (_verbose)
log("extracted '", src_path, "' to '", dst_path, "'");
});
return overall_success;
}
Main(Env &env) : _env(env)
{
Libc::with_libc([&] () { _process_config(); });
bool success = false;
env.parent().exit(0);
Libc::with_libc([&] () { success = _process_config(); });
env.parent().exit(_ignore_failures ? 0
: success ? 0
: 1);
}
};