From 222a078d270ee111aad5f5db1b452703d5798a52 Mon Sep 17 00:00:00 2001 From: "Victor A. P. Magri" Date: Sat, 15 Aug 2026 11:14:49 -0400 Subject: [PATCH 1/4] Add XML format checks --- .github/workflows/ci_tests.yml | 2 +- scripts/ci_build_and_test_in_container.sh | 8 +- scripts/formatXMLFiles.bash | 200 +++++++++++++----- src/CMakeLists.txt | 15 ++ src/cmake/GeosxMacros.cmake | 2 +- .../developerGuide/Contributing/CodeStyle.rst | 16 ++ 6 files changed, 181 insertions(+), 62 deletions(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index f2ae3dacf60..6fa4d429077 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -97,7 +97,7 @@ jobs: fail-fast : false matrix: include: - # Validates the code-style using uncrustify + # Validates C++ style (uncrustify) and XML formatting (format_xml) - name: Check code style BUILD_AND_TEST_ARGS: --test-code-style # Validates that the documentation generated using doxygen has no hole. diff --git a/scripts/ci_build_and_test_in_container.sh b/scripts/ci_build_and_test_in_container.sh index de142e22e06..dad6a549a31 100755 --- a/scripts/ci_build_and_test_in_container.sh +++ b/scripts/ci_build_and_test_in_container.sh @@ -198,6 +198,7 @@ Usage: $0 --sccache-credentials credentials.json Basename of the json credentials file to connect to the sccache cloud cache. --test-code-style + Check C++ style (uncrustify) and XML formatting (format_xml). --test-documentation -h | --help EOF @@ -485,7 +486,8 @@ or_die cd ${GEOS_BUILD_DIR} # Code style check if [[ "${TEST_CODE_STYLE}" = true ]]; then - or_die ctest --output-on-failure -R "testUncrustifyCheck" + or_die cmake --build . --target geosx_python_tools + or_die ctest --output-on-failure -R "testUncrustifyCheck|testXmlFormatCheck" exit 0 fi @@ -536,9 +538,9 @@ fi # Run the unit tests (excluding previously ran checks). if [[ "${RUN_UNIT_TESTS}" = true ]]; then if [ ${HOSTNAME} == 'streak.llnl.gov' ] || [ ${HOSTNAME} == 'streak2.llnl.gov' ]; then - or_die ctest --output-on-failure -E "testUncrustifyCheck|testDoxygenCheck|testExternalSolvers" + or_die ctest --output-on-failure -E "testUncrustifyCheck|testDoxygenCheck|testXmlFormatCheck|testExternalSolvers" else - or_die ctest --output-on-failure -E "testUncrustifyCheck|testDoxygenCheck" + or_die ctest --output-on-failure -E "testUncrustifyCheck|testDoxygenCheck|testXmlFormatCheck" fi fi diff --git a/scripts/formatXMLFiles.bash b/scripts/formatXMLFiles.bash index 52c3c7997a3..9ebe510c5f0 100755 --- a/scripts/formatXMLFiles.bash +++ b/scripts/formatXMLFiles.bash @@ -1,79 +1,165 @@ -#!/bin/bash +#!/usr/bin/env bash +# Format GEOS XML files with the Python format_xml tool (geos-xml-tools). +# Used by `make geosx_format_all_xml_files` and the XML formatting CI check. +# This is not schema validation. -# check if -a or --all is provided as 1st arg +set -uo pipefail + +MODE=fix METHOD=all -case $1 in - -a|--all) METHOD=all; shift - ;; - -g|--git) METHOD=git; shift - ;; - *) -esac - -# nothing to do if formatting script not specified -if [ -z "$1" ]; then - echo "Usage: $0 [-a|--all|-g|--git] [...]" - exit -fi +MAX_DIFFS=20 -FORMAT_SCRIPT=$1; shift -LOGFILE=xml_formatting_results.log +usage() { + cat < [...] -# "-r" in GNU xargs omits the call if input is empty -# OS X xargs does not support it, but does the same by default -if [ "$(uname)" == "Darwin" ]; then - XARGS="xargs" -else - XARGS="xargs -r" + --check Fail if any XML file is malformed or not in format_xml form + --fix Rewrite XML files in place (default) + -a, --all Search all *.xml files under each path + -g, --git Search git-tracked *.xml files under each path +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --check) + MODE=check + shift + ;; + --fix) + MODE=fix + shift + ;; + -a|--all) + METHOD=all + shift + ;; + -g|--git) + METHOD=git + shift + ;; + -h|--help) + usage + exit 0 + ;; + --) + shift + break + ;; + -*) + echo "Error: unknown option: $1" >&2 + usage >&2 + exit 1 + ;; + *) + break + ;; + esac +done + +if [[ -z "${1:-}" ]]; then + usage >&2 + exit 1 fi -# check to see if the formatting script exists -if [ ! -f $FORMAT_SCRIPT ]; then - >&2 echo "Error: the format_xml script was not found" - exit +FORMAT_SCRIPT=$1 +shift + +if [[ ! -f "${FORMAT_SCRIPT}" && ! -x "${FORMAT_SCRIPT}" ]]; then + if ! command -v "${FORMAT_SCRIPT}" >/dev/null 2>&1; then + echo "Error: the format_xml script was not found: ${FORMAT_SCRIPT}" >&2 + exit 1 + fi fi -# check if git is present, if needed -if [ "$METHOD" = "git" ] && ! (hash git &> /dev/null); then - >&2 echo "Error: git is required when -g or --git is specified" - exit +if [[ "${METHOD}" = "git" ]] && ! command -v git >/dev/null 2>&1; then + echo "Error: git is required when -g or --git is specified" >&2 + exit 1 fi -abs_path () -{ - if [ "$#" -gt 0 ]; then - realpath -s "$@" - fi +list_xml_files_all() { + local search_path=$1 + find "${search_path}" -type f -name "*.xml" -not -path "*/.*" -print } -list_xml_files_all () -{ - abs_path $(find $1 -name "*.xml" -not -path "*/\.*") +list_xml_files_git() { + local search_path=$1 + local git_root prefix + git_root=$(cd "${search_path}" && git rev-parse --show-toplevel 2>/dev/null) || { + echo "Error: ${search_path} does not appear to be part of a git repository" >&2 + return 1 + } + prefix=$(cd "${search_path}" && git rev-parse --show-prefix 2>/dev/null) + git --git-dir="${git_root}/.git" ls-files "${prefix}" | grep -e '.*[.]xml$' | sed "s|^|${git_root}/|g" || true } -# git does not have -C flag prior to 1.8.5, so we emulate it with cd -# this is actually the most reliable way, although not the fastest -# run in a subprocess so as to avoid having to cd back -list_xml_files_git () -{ - local git_root=$(cd $path; git rev-parse --show-toplevel 2>/dev/null) - if ! [ $? -eq 0 ]; then - >&2 echo "Error: $path does not appear to be part of a git repository" - exit 1 +LOGFILE=xml_formatting_results.log +echo -n > "${LOGFILE}" + +status=0 +n_checked=0 +n_invalid=0 +n_unformatted=0 +n_fixed=0 +n_diffs_shown=0 + +process_file() { + local file=$1 + + if [[ "${MODE}" == "fix" ]]; then + if ! "${FORMAT_SCRIPT}" "${file}" &>> "${LOGFILE}"; then + echo "Invalid XML: ${file}" + n_invalid=$((n_invalid + 1)) + status=1 + else + n_fixed=$((n_fixed + 1)) + fi + return fi - local prefix=$(cd $path; git rev-parse --show-prefix 2>/dev/null) - git --git-dir=$git_root/.git ls-files $prefix | grep -e .*[.]xml$ | sed "s|^|$git_root/|g" + + local tmp + tmp="$(mktemp)" + cp "${file}" "${tmp}" + if ! "${FORMAT_SCRIPT}" "${tmp}" &>> "${LOGFILE}"; then + echo "Invalid XML: ${file}" + n_invalid=$((n_invalid + 1)) + status=1 + elif ! cmp -s "${file}" "${tmp}"; then + echo "Incorrect XML formatting: ${file}" + if [[ ${n_diffs_shown} -lt ${MAX_DIFFS} ]]; then + diff -u "${file}" "${tmp}" || true + n_diffs_shown=$((n_diffs_shown + 1)) + fi + n_unformatted=$((n_unformatted + 1)) + status=1 + fi + rm -f "${tmp}" } -# create/nullify the log file -echo -n > $LOGFILE +if [[ $# -eq 0 ]]; then + echo "Error: no search paths given" >&2 + exit 1 +fi -# validate each path separately and write results in the log for path in "$@"; do - for file in $(list_xml_files_$METHOD $path); do - $FORMAT_SCRIPT $file &>> $LOGFILE - done + if [[ ! -d "${path}" ]]; then + echo "Error: directory not found: ${path}" >&2 + exit 1 + fi + while IFS= read -r file; do + [[ -z "${file}" ]] && continue + n_checked=$((n_checked + 1)) + process_file "${file}" + done < <(list_xml_files_${METHOD} "${path}") done +if [[ "${MODE}" == "fix" ]]; then + echo "XML formatting: ${n_checked} file(s) processed, ${n_invalid} invalid." +else + echo "XML formatting: ${n_checked} file(s) checked, ${n_unformatted} incorrectly formatted, ${n_invalid} invalid." + if [[ ${status} -ne 0 ]]; then + echo "Run: make geosx_format_all_xml_files" + fi +fi - +exit "${status}" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36dc61610ac..f6f29dd8b71 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -279,12 +279,27 @@ if ( Python3_EXECUTABLE ) DEPENDS geosx_python_tools ) + # Format / check XML with the existing Python format_xml tool. + # This is not a replacement for geosx_validate_all_xml_files (schema validation). add_custom_target( geosx_format_all_xml_files COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash -g ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS geosx_python_tools ) + add_custom_target( geosx_check_xml_files + COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash --check -g ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS geosx_python_tools + ) + + set_property( TARGET geosx_check_xml_files PROPERTY EXCLUDE_FROM_ALL TRUE ) + set_property( TARGET geosx_check_xml_files PROPERTY EXCLUDE_FROM_DEFAULT_BUILD TRUE ) + + add_test( NAME testXmlFormatCheck + COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash --check -g ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) + else() message(WARNING "Building the GEOSX python tools requires Python >= 3.6.") message(STATUS "If you need these, try setting Python3_ROOT_DIR and/or Python3_EXECUTABLE in your host config.") diff --git a/src/cmake/GeosxMacros.cmake b/src/cmake/GeosxMacros.cmake index bb9f670f2e6..e6beb37ed06 100644 --- a/src/cmake/GeosxMacros.cmake +++ b/src/cmake/GeosxMacros.cmake @@ -57,7 +57,7 @@ macro( geosx_add_code_checks ) if (ENABLE_COVERAGE) blt_add_code_coverage_target( NAME ${arg_PREFIX}_coverage - RUNNER ctest --progress --output-on-failure -E 'blt_gtest_smoke|blt_mpi_smoke|testUncrustifyCheck|testDoxygenCheck' + RUNNER ctest --progress --output-on-failure -E 'blt_gtest_smoke|blt_mpi_smoke|testUncrustifyCheck|testDoxygenCheck|testXmlFormatCheck' SOURCE_DIRECTORIES ${PROJECT_SOURCE_DIR}/coreComponents ) endif() diff --git a/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst b/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst index 6d7f78d9b46..8e1338f5c7c 100644 --- a/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst +++ b/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst @@ -171,6 +171,22 @@ While quite extensive, uncrustify does not enforce every example of the preferre In cases where uncrusitfy is unable to enforce code style, it will ignore formatting rules. In these cases it is acceptable to proceed with pull requests, as there is no logical recourse. +XML input files +=============== +GEOS XML files under ``src`` and ``examples`` are formatted with the Python +``format_xml`` tool from geos-xml-tools. CI runs this as +``testXmlFormatCheck`` alongside the uncrustify code-style job. + +From the build directory: + +.. code-block:: bash + + make geosx_check_xml_files + make geosx_format_all_xml_files + +XML formatting is not a replacement for schema validation +(``make geosx_validate_all_xml_files``). + Header Guards ============= Header guard names should consist of the name `GEOS`, followed by the component name (e.g. dataRepository), From 5f7fef1c971a06f360127a27e22b5390e51cdaeb Mon Sep 17 00:00:00 2001 From: "Victor A. P. Magri" Date: Sat, 15 Aug 2026 11:34:39 -0400 Subject: [PATCH 2/4] Fix CI --- scripts/ci_build_and_test_in_container.sh | 6 ++++++ scripts/formatXMLFiles.bash | 3 +++ scripts/setupPythonEnvironment.bash | 24 +++++++++++++++++++++++ src/CMakeLists.txt | 2 ++ 4 files changed, 35 insertions(+) diff --git a/scripts/ci_build_and_test_in_container.sh b/scripts/ci_build_and_test_in_container.sh index dad6a549a31..61a3894051d 100755 --- a/scripts/ci_build_and_test_in_container.sh +++ b/scripts/ci_build_and_test_in_container.sh @@ -486,6 +486,12 @@ or_die cd ${GEOS_BUILD_DIR} # Code style check if [[ "${TEST_CODE_STYLE}" = true ]]; then + # Ubuntu 24.04 system Python is PEP 668-managed. geosx_python_tools then + # creates a venv, which needs the stdlib venv/ensurepip modules. + if ! python3 -c "import venv, ensurepip" >/dev/null 2>&1; then + or_die apt-get update + or_die apt-get install -y python3-venv + fi or_die cmake --build . --target geosx_python_tools or_die ctest --output-on-failure -R "testUncrustifyCheck|testXmlFormatCheck" exit 0 diff --git a/scripts/formatXMLFiles.bash b/scripts/formatXMLFiles.bash index 9ebe510c5f0..514b6833411 100755 --- a/scripts/formatXMLFiles.bash +++ b/scripts/formatXMLFiles.bash @@ -148,6 +148,9 @@ for path in "$@"; do fi while IFS= read -r file; do [[ -z "${file}" ]] && continue + # examples/ contains git-tracked symlinks into inputFiles/. Skip them + # so this check does not rewrite or require formatting that tree. + [[ -L "${file}" ]] && continue n_checked=$((n_checked + 1)) process_file "${file}" done < <(list_xml_files_${METHOD} "${path}") diff --git a/scripts/setupPythonEnvironment.bash b/scripts/setupPythonEnvironment.bash index c25a0026f9c..d7dfbb7680d 100755 --- a/scripts/setupPythonEnvironment.bash +++ b/scripts/setupPythonEnvironment.bash @@ -117,6 +117,30 @@ then exit 1 fi +# Ubuntu 24.04+ marks the system interpreter as EXTERNALLY-MANAGED (PEP 668). +# geosx_python_tools_test already expects packages in ${CMAKE_BINARY_DIR}/python/geosx. +if "${PYTHON_TARGET}" -c 'import os, sysconfig; raise SystemExit(0 if os.path.isfile(os.path.join(sysconfig.get_path("stdlib"), "EXTERNALLY-MANAGED")) else 1)' +then + if [[ -z "${BIN_DIR}" ]] + then + echo "The target python (${PYTHON_TARGET}) is externally managed (PEP 668)." + echo "Pass -b/--bin-dir so a virtual environment can be created." + exit 1 + fi + + VENV_DIR="$(cd "$(dirname "${BIN_DIR}")" && pwd)/python/geosx" + echo "The target python (${PYTHON_TARGET}) is externally managed (PEP 668)." + echo "Creating a virtual environment at ${VENV_DIR}" + mkdir -p "$(dirname "${VENV_DIR}")" + if ! "${PYTHON_TARGET}" -m venv "${VENV_DIR}" + then + echo "Failed to create a virtual environment at ${VENV_DIR}." + echo "On Debian/Ubuntu, install the python3-venv package and retry." + exit 1 + fi + PYTHON_TARGET="${VENV_DIR}/bin/python" +fi + # Check for a predefined package directory echo "Checking for python packages..." diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f6f29dd8b71..28e57f3e887 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -262,6 +262,8 @@ if ( Python3_EXECUTABLE ) "${CMAKE_BINARY_DIR}/bin/preprocess_xml" "${CMAKE_BINARY_DIR}/bin/format_xml" ) + # setupPythonEnvironment.bash installs into a build-tree venv when the + # target interpreter is PEP 668 externally-managed (Ubuntu 24.04+). add_custom_command( OUTPUT ${GEOS_PYTHON_TOOLS_BINS} COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/setupPythonEnvironment.bash -p ${PYTHON_POST_EXECUTABLE} -b ${CMAKE_BINARY_DIR}/bin --python-pkg-branch ${GEOS_PYTHON_PACKAGES_BRANCH} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) From d7c5b039ef0ec8a0085c9a6f1fe153e1f411e4ef Mon Sep 17 00:00:00 2001 From: "Victor A. P. Magri" Date: Sat, 15 Aug 2026 14:30:48 -0400 Subject: [PATCH 3/4] Use new xml format --- scripts/formatXMLFiles.bash | 43 ++++++++++++++----- src/CMakeLists.txt | 13 +++--- .../developerGuide/Contributing/CodeStyle.rst | 4 ++ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/scripts/formatXMLFiles.bash b/scripts/formatXMLFiles.bash index 514b6833411..7c9a2ffc498 100755 --- a/scripts/formatXMLFiles.bash +++ b/scripts/formatXMLFiles.bash @@ -15,7 +15,7 @@ Usage: $0 [--check|--fix] [-a|--all|-g|--git] [...] --check Fail if any XML file is malformed or not in format_xml form --fix Rewrite XML files in place (default) - -a, --all Search all *.xml files under each path + -a, --all Search all regular *.xml files under each path (default) -g, --git Search git-tracked *.xml files under each path EOF } @@ -77,20 +77,26 @@ if [[ "${METHOD}" = "git" ]] && ! command -v git >/dev/null 2>&1; then exit 1 fi +# Regular files only. Do not follow directory symlinks, and do not match +# symlink-to-file entries (examples/ has links into inputFiles/). list_xml_files_all() { local search_path=$1 - find "${search_path}" -type f -name "*.xml" -not -path "*/.*" -print + find -P "${search_path}" -type f -name "*.xml" -not -path "*/.*" -print } list_xml_files_git() { local search_path=$1 - local git_root prefix - git_root=$(cd "${search_path}" && git rev-parse --show-toplevel 2>/dev/null) || { + local git_root prefix tracked + git_root=$(cd "${search_path}" && git rev-parse --show-toplevel) || { echo "Error: ${search_path} does not appear to be part of a git repository" >&2 return 1 } - prefix=$(cd "${search_path}" && git rev-parse --show-prefix 2>/dev/null) - git --git-dir="${git_root}/.git" ls-files "${prefix}" | grep -e '.*[.]xml$' | sed "s|^|${git_root}/|g" || true + prefix=$(cd "${search_path}" && git rev-parse --show-prefix) || return 1 + tracked=$(git -C "${git_root}" ls-files -- "${prefix}") || { + echo "Error: git ls-files failed under ${search_path}" >&2 + return 1 + } + printf '%s\n' "${tracked}" | grep -e '.*[.]xml$' | sed "s|^|${git_root}/|g" || true } LOGFILE=xml_formatting_results.log @@ -117,8 +123,10 @@ process_file() { return fi - local tmp - tmp="$(mktemp)" + # Keep a .xml suffix: format_xml may ignore extensionless temp files. + local tmpdir tmp + tmpdir="$(mktemp -d)" + tmp="${tmpdir}/check.xml" cp "${file}" "${tmp}" if ! "${FORMAT_SCRIPT}" "${tmp}" &>> "${LOGFILE}"; then echo "Invalid XML: ${file}" @@ -133,7 +141,7 @@ process_file() { n_unformatted=$((n_unformatted + 1)) status=1 fi - rm -f "${tmp}" + rm -rf "${tmpdir}" } if [[ $# -eq 0 ]]; then @@ -146,6 +154,14 @@ for path in "$@"; do echo "Error: directory not found: ${path}" >&2 exit 1 fi + + list_file="$(mktemp)" + if ! list_xml_files_${METHOD} "${path}" > "${list_file}"; then + rm -f "${list_file}" + echo "Error: failed to list XML files under ${path}" >&2 + exit 1 + fi + while IFS= read -r file; do [[ -z "${file}" ]] && continue # examples/ contains git-tracked symlinks into inputFiles/. Skip them @@ -153,9 +169,16 @@ for path in "$@"; do [[ -L "${file}" ]] && continue n_checked=$((n_checked + 1)) process_file "${file}" - done < <(list_xml_files_${METHOD} "${path}") + done < "${list_file}" + rm -f "${list_file}" done +if [[ ${n_checked} -eq 0 ]]; then + echo "Error: no XML files were found under: $*" >&2 + echo "The format check must not pass when it inspected nothing." >&2 + exit 1 +fi + if [[ "${MODE}" == "fix" ]]; then echo "XML formatting: ${n_checked} file(s) processed, ${n_invalid} invalid." else diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 28e57f3e887..bb5f9e38349 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -225,8 +225,8 @@ install( FILES ${CMAKE_BINARY_DIR}/schema.xsd ################################ # Add python environment setup ################################ -message(WARNING "Temporarily changing the geosPythonBranch to feature/remove-dndx-detj") -set(GEOS_PYTHON_PACKAGES_BRANCH "feature/remove-dndx-detj" CACHE STRING "" FORCE) +message(WARNING "Temporarily changing the geosPythonBranch to feature/paludettomag1/compact-xml-leaves") +set(GEOS_PYTHON_PACKAGES_BRANCH "feature/paludettomag1/compact-xml-leaves" CACHE STRING "" FORCE) if ( Python3_EXECUTABLE ) @@ -282,15 +282,18 @@ if ( Python3_EXECUTABLE ) ) # Format / check XML with the existing Python format_xml tool. + # Walk the filesystem (-a), not git (-g): the CI container often cannot + # use the mounted checkout as root (safe.directory), and a git listing + # failure must not look like a clean pass. # This is not a replacement for geosx_validate_all_xml_files (schema validation). add_custom_target( geosx_format_all_xml_files - COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash -g ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples + COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash -a ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS geosx_python_tools ) add_custom_target( geosx_check_xml_files - COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash --check -g ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples + COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash --check -a ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS geosx_python_tools ) @@ -299,7 +302,7 @@ if ( Python3_EXECUTABLE ) set_property( TARGET geosx_check_xml_files PROPERTY EXCLUDE_FROM_DEFAULT_BUILD TRUE ) add_test( NAME testXmlFormatCheck - COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash --check -g ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples + COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash --check -a ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) else() diff --git a/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst b/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst index 8e1338f5c7c..12861a0c9b3 100644 --- a/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst +++ b/src/docs/sphinx/developerGuide/Contributing/CodeStyle.rst @@ -176,6 +176,10 @@ XML input files GEOS XML files under ``src`` and ``examples`` are formatted with the Python ``format_xml`` tool from geos-xml-tools. CI runs this as ``testXmlFormatCheck`` alongside the uncrustify code-style job. +The check walks those directories on disk (it does not use git) and skips +symlinks, so it does not follow ``examples/`` links into ``inputFiles``. +Leaf blocks that fit in 100 columns are kept on one line; longer blocks and +parent elements stay multi-line. From the build directory: From 314dc06808256e3f3c6c89e19774261a40a011ce Mon Sep 17 00:00:00 2001 From: "Victor A. P. Magri" Date: Sat, 15 Aug 2026 15:06:16 -0400 Subject: [PATCH 4/4] Fix XMLs with new formatter --- examples/GPU/beamBending.xml | 26 ++---- .../included/included_a.xml | 14 +-- .../included/included_b.xml | 31 ++----- .../included_files_example.xml | 9 +- .../parameters_example.xml | 55 +++-------- .../symbolic_math_example.xml | 55 +++-------- examples/event_examples.xml | 44 +++------ .../function_examples/function_examples.xml | 10 +- .../hydraulicFracture.xml | 8 +- .../modifyBoundaryCondition/pkn_example.xml | 93 +++++-------------- .../parametricMesh.xml | 28 ++---- .../modified_sedov.xml | 11 +-- examples/sedovKernelTest.xml | 27 ++---- .../constitutiveTests/testReactiveFluid.xml | 21 ++--- .../integrationTests/xmlTests/basic_input.xml | 27 ++---- .../xmlTests/include_input.xml | 12 +-- .../xmlTests/multifile_input/fieldspec.xml | 6 +- .../xmlTests/multifile_input/mesh.xml | 5 +- .../xmlTests/multifile_input/outputs.xml | 8 +- .../xmlTests/multifile_input/solver.xml | 14 +-- src/pygeosx/pyssle.xml | 22 +---- .../dataRepositoryTests/pygeosx_only.xml | 20 ++-- 22 files changed, 140 insertions(+), 406 deletions(-) diff --git a/examples/GPU/beamBending.xml b/examples/GPU/beamBending.xml index 2d5c3852bed..fa00000d237 100644 --- a/examples/GPU/beamBending.xml +++ b/examples/GPU/beamBending.xml @@ -12,9 +12,7 @@ discretization="FE1" targetRegions="{ Region2 }"> - + - + - + - + @@ -145,12 +135,8 @@ - + - + diff --git a/examples/advanced_xml_features/included/included_a.xml b/examples/advanced_xml_features/included/included_a.xml index 66f4abed35e..11fb9aa0960 100644 --- a/examples/advanced_xml_features/included/included_a.xml +++ b/examples/advanced_xml_features/included/included_a.xml @@ -7,9 +7,7 @@ name="SinglePhaseFlow" discretization="singlePhaseTPFA" targetRegions="{ Region1 }"> - + @@ -27,14 +25,8 @@ - + - + diff --git a/examples/advanced_xml_features/included/included_b.xml b/examples/advanced_xml_features/included/included_b.xml index ba2aa87baed..b0bd9da3a2c 100644 --- a/examples/advanced_xml_features/included/included_b.xml +++ b/examples/advanced_xml_features/included/included_b.xml @@ -3,15 +3,9 @@ - + - + - + - + @@ -49,8 +39,7 @@ porosityModelName="rockPorosity" permeabilityModelName="rockPerm"/> - + - + - + - + diff --git a/examples/advanced_xml_features/included_files_example.xml b/examples/advanced_xml_features/included_files_example.xml index 1e36184f8ff..191249136f3 100644 --- a/examples/advanced_xml_features/included_files_example.xml +++ b/examples/advanced_xml_features/included_files_example.xml @@ -17,13 +17,10 @@ using the following rules: Otherwise insert the target into the xml structure as-is --> - + - + - + diff --git a/examples/advanced_xml_features/parameters_example.xml b/examples/advanced_xml_features/parameters_example.xml index fa31e5d4bd3..a8b92c7a1ad 100644 --- a/examples/advanced_xml_features/parameters_example.xml +++ b/examples/advanced_xml_features/parameters_example.xml @@ -17,17 +17,11 @@ XML Units: - These use a python-style format e.g. (0.1 [m/s**2]) --> - + - + - + - + @@ -56,28 +48,16 @@ XML Units: - - - + + + - + - + - + - + @@ -115,8 +91,7 @@ XML Units: porosityModelName="rockPorosity" permeabilityModelName="rockPerm"/> - + - + - + diff --git a/examples/advanced_xml_features/symbolic_math_example.xml b/examples/advanced_xml_features/symbolic_math_example.xml index e4d3f4942dd..573c801f714 100644 --- a/examples/advanced_xml_features/symbolic_math_example.xml +++ b/examples/advanced_xml_features/symbolic_math_example.xml @@ -27,17 +27,11 @@ XML Symbolic Math: - This constraint can be relaxed to allow more complicated functions (sin, cos, etc.) --> - + - + - + - + @@ -66,28 +58,16 @@ XML Symbolic Math: - - - + + + - + - + - + - + @@ -125,8 +101,7 @@ XML Symbolic Math: porosityModelName="rockPorosity" permeabilityModelName="rockPerm"/> - + - + - + diff --git a/examples/event_examples.xml b/examples/event_examples.xml index 582343b5875..0059c9f4ae8 100644 --- a/examples/event_examples.xml +++ b/examples/event_examples.xml @@ -5,40 +5,27 @@ maxTime="10" logLevel="1"> - + - + - + - - + + - + - + - + - + - + - + - + - + diff --git a/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml b/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml index 8d861acab42..5afe9514205 100644 --- a/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml +++ b/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml @@ -23,15 +23,10 @@ solidSolverName="lagsolve" logLevel="1" flowSolverName="SinglePhaseFlow" - surfaceGeneratorName="SurfaceGen" + surfaceGeneratorName="SurfaceGen" targetRegions="{ Domain, Fracture }"> - - + + - - + + - - + + - + - + - + - + - + - + - + - + - - - - - + + + + + @@ -162,9 +126,7 @@ - + - + - + - + diff --git a/examples/pygeosxExamples/parametricSurfaceMapping/parametricMesh.xml b/examples/pygeosxExamples/parametricSurfaceMapping/parametricMesh.xml index afd6d585819..37abebebcc3 100644 --- a/examples/pygeosxExamples/parametricSurfaceMapping/parametricMesh.xml +++ b/examples/pygeosxExamples/parametricSurfaceMapping/parametricMesh.xml @@ -8,11 +8,8 @@ timeIntegrationOption="QuasiStatic" discretization="FE1" targetRegions="{ Region2 }"> - - + + @@ -35,10 +32,7 @@ maxTime="1.0e-3"> - + - + - + @@ -97,11 +86,8 @@ - + - + diff --git a/examples/pygeosxExamples/sedovWithStressFunction/modified_sedov.xml b/examples/pygeosxExamples/sedovWithStressFunction/modified_sedov.xml index 0e5c1e4e52c..2ad1af3f675 100644 --- a/examples/pygeosxExamples/sedovWithStressFunction/modified_sedov.xml +++ b/examples/pygeosxExamples/sedovWithStressFunction/modified_sedov.xml @@ -3,22 +3,17 @@ - + - + - + diff --git a/examples/sedovKernelTest.xml b/examples/sedovKernelTest.xml index 86d6665f189..9e8fc1294b8 100644 --- a/examples/sedovKernelTest.xml +++ b/examples/sedovKernelTest.xml @@ -26,10 +26,7 @@ maxTime="1.0e-2"> - + - + @@ -102,15 +92,10 @@ - + - + diff --git a/src/coreComponents/integrationTests/xmlTests/include_input.xml b/src/coreComponents/integrationTests/xmlTests/include_input.xml index 3749cd9290f..15514d80b15 100644 --- a/src/coreComponents/integrationTests/xmlTests/include_input.xml +++ b/src/coreComponents/integrationTests/xmlTests/include_input.xml @@ -2,16 +2,12 @@ - + - + - + - + diff --git a/src/coreComponents/integrationTests/xmlTests/multifile_input/fieldspec.xml b/src/coreComponents/integrationTests/xmlTests/multifile_input/fieldspec.xml index 251a5993fab..9eb454bd4d3 100644 --- a/src/coreComponents/integrationTests/xmlTests/multifile_input/fieldspec.xml +++ b/src/coreComponents/integrationTests/xmlTests/multifile_input/fieldspec.xml @@ -2,10 +2,8 @@ - + - + diff --git a/src/coreComponents/integrationTests/xmlTests/multifile_input/mesh.xml b/src/coreComponents/integrationTests/xmlTests/multifile_input/mesh.xml index 8b8da84f49c..45afb742fe2 100644 --- a/src/coreComponents/integrationTests/xmlTests/multifile_input/mesh.xml +++ b/src/coreComponents/integrationTests/xmlTests/multifile_input/mesh.xml @@ -15,9 +15,6 @@ - + diff --git a/src/coreComponents/integrationTests/xmlTests/multifile_input/outputs.xml b/src/coreComponents/integrationTests/xmlTests/multifile_input/outputs.xml index 371078f74c9..9d186e357fb 100644 --- a/src/coreComponents/integrationTests/xmlTests/multifile_input/outputs.xml +++ b/src/coreComponents/integrationTests/xmlTests/multifile_input/outputs.xml @@ -2,14 +2,10 @@ - + - + diff --git a/src/coreComponents/integrationTests/xmlTests/multifile_input/solver.xml b/src/coreComponents/integrationTests/xmlTests/multifile_input/solver.xml index 66124970c74..25972a3060b 100644 --- a/src/coreComponents/integrationTests/xmlTests/multifile_input/solver.xml +++ b/src/coreComponents/integrationTests/xmlTests/multifile_input/solver.xml @@ -11,26 +11,18 @@ - + - + - + diff --git a/src/pygeosx/pyssle.xml b/src/pygeosx/pyssle.xml index b5dd7aedee0..1624d8ed78d 100644 --- a/src/pygeosx/pyssle.xml +++ b/src/pygeosx/pyssle.xml @@ -26,10 +26,7 @@ maxTime="1.0e-3"> - + - + - + @@ -115,14 +107,10 @@ - + - + diff --git a/src/pygeosx/unitTests/dataRepositoryTests/pygeosx_only.xml b/src/pygeosx/unitTests/dataRepositoryTests/pygeosx_only.xml index 085db97cd7d..fcdadc9f9a0 100644 --- a/src/pygeosx/unitTests/dataRepositoryTests/pygeosx_only.xml +++ b/src/pygeosx/unitTests/dataRepositoryTests/pygeosx_only.xml @@ -1,17 +1,13 @@ - - - + + - + @@ -28,10 +24,6 @@ - + - - \ No newline at end of file +