From 1e933cc490738517b1177f5a377cd5c18ce07d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Tue, 20 Aug 2024 15:28:46 +0200 Subject: [PATCH] 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. --- repos/libports/src/app/extract/README | 12 ++++++++++ repos/libports/src/app/extract/main.cc | 33 +++++++++++++++++++++----- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/repos/libports/src/app/extract/README b/repos/libports/src/app/extract/README index f0e9e566f2..ccc6ebdd62 100644 --- a/repos/libports/src/app/extract/README +++ b/repos/libports/src/app/extract/README @@ -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. diff --git a/repos/libports/src/app/extract/main.cc b/repos/libports/src/app/extract/main.cc index 0e949c909b..f86cc2ebe8 100644 --- a/repos/libports/src/app/extract/main.cc +++ b/repos/libports/src/app/extract/main.cc @@ -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); } };