IfcConvert: add --fail-on-error to exit non-zero when conversion logs errors (#1118)

IfcConvert returned a success exit code even when geometry conversion logged
errors and silently dropped elements (for example a failed TopoDS::Shell build
under layerset slicing produced valid looking output with most objects
missing), so CI and scripts could not detect a partial conversion.

Add an opt-in --fail-on-error flag that makes IfcConvert exit non-zero when any
error was logged during processing, reusing the existing MaxSeverity based
failure check already used for --validate. The default exit behaviour is
unchanged, so pipelines that tolerate individual element failures are
unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit eb7324e7fc)
This commit is contained in:
Petru Conduraru
2026-07-10 20:38:15 +03:00
committed by Dion Moult
parent 345eb18124
commit cb610cfdef
+10
View File
@@ -295,6 +295,10 @@ int main(int argc, char** argv) {
("stderr-progress", "output progress to stderr stream") ("stderr-progress", "output progress to stderr stream")
("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)") ("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)")
("no-progress", "suppress possible progress bar type of prints that use carriage return") ("no-progress", "suppress possible progress bar type of prints that use carriage return")
("fail-on-error", "return a non-zero exit code when one or more errors were logged during "
"geometry conversion (e.g. an element failed to convert). By default IfcConvert exits "
"successfully as long as an output file could be written, even if some elements were "
"silently dropped. Enable this flag so scripts and CI can detect partial conversions.")
("log-format", po::value<std::string>(&log_format), "log format: plain or json") ("log-format", po::value<std::string>(&log_format), "log format: plain or json")
("log-file", new po::typed_value<path_t, char_t>(&log_file), "redirect log output to file"); ("log-file", new po::typed_value<path_t, char_t>(&log_file), "redirect log output to file");
@@ -438,6 +442,7 @@ int main(int argc, char** argv) {
const bool mmap = vmap.count("mmap") != 0; const bool mmap = vmap.count("mmap") != 0;
const bool no_progress = vmap.count("no-progress") != 0; const bool no_progress = vmap.count("no-progress") != 0;
const bool fail_on_error = vmap.count("fail-on-error") != 0;
const bool quiet = vmap.count("quiet") != 0; const bool quiet = vmap.count("quiet") != 0;
const bool stderr_progress = vmap.count("stderr-progress") != 0; const bool stderr_progress = vmap.count("stderr-progress") != 0;
@@ -1027,6 +1032,11 @@ int main(int argc, char** argv) {
successful = false; successful = false;
} }
if (fail_on_error && logger.max_severity() >= ::logger::LOG_ERROR) {
logger.error("SYS", 26, "Errors encountered during processing, failing due to --fail-on-error.");
successful = false;
}
if (logger.verbosity() == ::logger::LOG_PERF) { if (logger.verbosity() == ::logger::LOG_PERF) {
logger.print_performance_stats(); logger.print_performance_stats();
} }