diff --git a/Help/release/dev/ExternalData-recursive-match.rst b/Help/release/dev/ExternalData-recursive-match.rst new file mode 100644 index 000000000..4d8c7899f --- /dev/null +++ b/Help/release/dev/ExternalData-recursive-match.rst @@ -0,0 +1,7 @@ +ExternalData-recursive-match +---------------------------- + +* The :module:`ExternalData` module learned a new ``RECURSE:`` + option in ``DATA{}`` references specifying directories. + This allows an entire directory tree of associated files + to be matched. diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index eab266f28..883ab6935 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -244,7 +244,8 @@ associated file options. For example, the argument ``DATA{MyDataDir/,REGEX:.*}`` will pass the full path to a ``MyDataDir`` directory on the command line and ensure that the directory contains files corresponding to every file or content link in the ``MyDataDir`` -source directory. +source directory. In order to match associated files in subdirectories, +specify a ``RECURSE:`` option, e.g. ``DATA{MyDataDir/,RECURSE:,REGEX:.*}``. Hash Algorithms ^^^^^^^^^^^^^^^ @@ -597,6 +598,7 @@ function(_ExternalData_arg target arg options var_file) # Process options. set(series_option "") + set(recurse_option "") set(associated_files "") set(associated_regex "") foreach(opt ${options}) @@ -606,6 +608,9 @@ function(_ExternalData_arg target arg options var_file) elseif(opt STREQUAL ":") # Activate series matching. set(series_option "${opt}") + elseif(opt STREQUAL "RECURSE:") + # Activate recursive matching in directories. + set(recurse_option "${opt}") elseif("x${opt}" MATCHES "^[^][:/*?]+$") # Specific associated file. list(APPEND associated_files "${opt}") @@ -622,6 +627,9 @@ function(_ExternalData_arg target arg options var_file) if(associated_files OR associated_regex) message(FATAL_ERROR "Series option \"${series_option}\" not allowed with associated files.") endif() + if(recurse_option) + message(FATAL_ERROR "Recurse option \"${recurse_option}\" allowed only with directories.") + endif() # Load a whole file series. _ExternalData_arg_series() elseif(data_is_directory) @@ -634,6 +642,9 @@ function(_ExternalData_arg target arg options var_file) "must list associated files.") endif() else() + if(recurse_option) + message(FATAL_ERROR "Recurse option \"${recurse_option}\" allowed only with directories.") + endif() # Load the named data file. _ExternalData_arg_single() if(associated_files OR associated_regex) @@ -681,11 +692,17 @@ macro(_ExternalData_arg_associated) set(reldir "${reldir}/") endif() _ExternalData_exact_regex(reldir_regex "${reldir}") + if(recurse_option) + set(glob GLOB_RECURSE) + set(reldir_regex "${reldir_regex}(.+/)?") + else() + set(glob GLOB) + endif() # Find files named explicitly. foreach(file ${associated_files}) _ExternalData_exact_regex(file_regex "${file}") - _ExternalData_arg_find_files(GLOB "${reldir}${file}" + _ExternalData_arg_find_files(${glob} "${reldir}${file}" "${reldir_regex}${file_regex}") endforeach() @@ -696,7 +713,7 @@ macro(_ExternalData_arg_associated) set(all "${all}${sep}${reldir_regex}${regex}") set(sep "|") endforeach() - _ExternalData_arg_find_files(GLOB "${reldir}" "${all}") + _ExternalData_arg_find_files(${glob} "${reldir}" "${all}") endmacro() macro(_ExternalData_arg_single) diff --git a/Tests/Module/ExternalData/CMakeLists.txt b/Tests/Module/ExternalData/CMakeLists.txt index 6c5e59c69..b6e24d247 100644 --- a/Tests/Module/ExternalData/CMakeLists.txt +++ b/Tests/Module/ExternalData/CMakeLists.txt @@ -44,6 +44,7 @@ ExternalData_Add_Test(Data1 -D Paired=DATA{PairedA.dat,PairedB.dat} -D Meta=DATA{MetaTop.dat,REGEX:Meta[ABC].dat} -D Directory=DATA{Directory/,A.dat,REGEX:[BC].dat} + -D DirRecurse=DATA{DirRecurse/,RECURSE:,A.dat,REGEX:[BC].dat} -D "Semicolons=DATA{Data.dat}\\;DATA{Data.dat}" -P ${CMAKE_CURRENT_SOURCE_DIR}/Data1Check.cmake ) diff --git a/Tests/Module/ExternalData/Data1Check.cmake b/Tests/Module/ExternalData/Data1Check.cmake index 9845a3b83..f60c2094d 100644 --- a/Tests/Module/ExternalData/Data1Check.cmake +++ b/Tests/Module/ExternalData/Data1Check.cmake @@ -90,6 +90,12 @@ foreach(n A B C) message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!") endif() endforeach() +foreach(n A Sub1/A Sub2/Dir/A B Sub1/B Sub2/Dir/B C Sub1/C Sub2/Dir/C) + set(file "${DirRecurse}/${n}.dat") + if(NOT EXISTS "${file}") + message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!") + endif() +endforeach() list(LENGTH Semicolons len) if("${len}" EQUAL 2) foreach(file ${Semicolons}) diff --git a/Tests/Module/ExternalData/DirRecurse/A.dat.md5 b/Tests/Module/ExternalData/DirRecurse/A.dat.md5 new file mode 100644 index 000000000..4a78fc783 --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/A.dat.md5 @@ -0,0 +1 @@ +9d980b06c2f0fec3d4872d68175b9822 diff --git a/Tests/Module/ExternalData/DirRecurse/B.dat.md5 b/Tests/Module/ExternalData/DirRecurse/B.dat.md5 new file mode 100644 index 000000000..4557a216a --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/B.dat.md5 @@ -0,0 +1 @@ +8f4add4581551facf27237e6577fd662 diff --git a/Tests/Module/ExternalData/DirRecurse/C.dat.md5 b/Tests/Module/ExternalData/DirRecurse/C.dat.md5 new file mode 100644 index 000000000..a7f23dd7f --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/C.dat.md5 @@ -0,0 +1 @@ +c1030719c95f3435d8abc39c0d442946 diff --git a/Tests/Module/ExternalData/DirRecurse/Sub1/A.dat.md5 b/Tests/Module/ExternalData/DirRecurse/Sub1/A.dat.md5 new file mode 100644 index 000000000..4a78fc783 --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/Sub1/A.dat.md5 @@ -0,0 +1 @@ +9d980b06c2f0fec3d4872d68175b9822 diff --git a/Tests/Module/ExternalData/DirRecurse/Sub1/B.dat.md5 b/Tests/Module/ExternalData/DirRecurse/Sub1/B.dat.md5 new file mode 100644 index 000000000..4557a216a --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/Sub1/B.dat.md5 @@ -0,0 +1 @@ +8f4add4581551facf27237e6577fd662 diff --git a/Tests/Module/ExternalData/DirRecurse/Sub1/C.dat.md5 b/Tests/Module/ExternalData/DirRecurse/Sub1/C.dat.md5 new file mode 100644 index 000000000..a7f23dd7f --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/Sub1/C.dat.md5 @@ -0,0 +1 @@ +c1030719c95f3435d8abc39c0d442946 diff --git a/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/A.dat.md5 b/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/A.dat.md5 new file mode 100644 index 000000000..4a78fc783 --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/A.dat.md5 @@ -0,0 +1 @@ +9d980b06c2f0fec3d4872d68175b9822 diff --git a/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/B.dat.md5 b/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/B.dat.md5 new file mode 100644 index 000000000..4557a216a --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/B.dat.md5 @@ -0,0 +1 @@ +8f4add4581551facf27237e6577fd662 diff --git a/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/C.dat.md5 b/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/C.dat.md5 new file mode 100644 index 000000000..a7f23dd7f --- /dev/null +++ b/Tests/Module/ExternalData/DirRecurse/Sub2/Dir/C.dat.md5 @@ -0,0 +1 @@ +c1030719c95f3435d8abc39c0d442946 diff --git a/Tests/RunCMake/ExternalData/BadRecurse1-result.txt b/Tests/RunCMake/ExternalData/BadRecurse1-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ExternalData/BadRecurse1-stderr.txt b/Tests/RunCMake/ExternalData/BadRecurse1-stderr.txt new file mode 100644 index 000000000..aedc33015 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse1-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\): + Recurse option "RECURSE:" allowed only with directories. +Call Stack \(most recent call first\): + .* + BadRecurse1.cmake:2 \(ExternalData_Expand_Arguments\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ExternalData/BadRecurse1.cmake b/Tests/RunCMake/ExternalData/BadRecurse1.cmake new file mode 100644 index 000000000..f70b9f9d5 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse1.cmake @@ -0,0 +1,2 @@ +include(ExternalData) +ExternalData_Expand_Arguments(Data args DATA{Series.txt,:,RECURSE:}) diff --git a/Tests/RunCMake/ExternalData/BadRecurse2-result.txt b/Tests/RunCMake/ExternalData/BadRecurse2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ExternalData/BadRecurse2-stderr.txt b/Tests/RunCMake/ExternalData/BadRecurse2-stderr.txt new file mode 100644 index 000000000..3f809ca69 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse2-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\): + Recurse option "RECURSE:" allowed only with directories. +Call Stack \(most recent call first\): + .* + BadRecurse2.cmake:2 \(ExternalData_Expand_Arguments\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ExternalData/BadRecurse2.cmake b/Tests/RunCMake/ExternalData/BadRecurse2.cmake new file mode 100644 index 000000000..c4dc35d54 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse2.cmake @@ -0,0 +1,2 @@ +include(ExternalData) +ExternalData_Expand_Arguments(Data args DATA{Data.txt,RECURSE:}) diff --git a/Tests/RunCMake/ExternalData/BadRecurse3-result.txt b/Tests/RunCMake/ExternalData/BadRecurse3-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ExternalData/BadRecurse3-stderr.txt b/Tests/RunCMake/ExternalData/BadRecurse3-stderr.txt new file mode 100644 index 000000000..37740e0f7 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse3-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\): + Unknown option "RECURSE:x" in argument + + DATA{Directory1/,RECURSE:x,Data.dat} + +Call Stack \(most recent call first\): + .* + BadRecurse3.cmake:2 \(ExternalData_Expand_Arguments\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ExternalData/BadRecurse3.cmake b/Tests/RunCMake/ExternalData/BadRecurse3.cmake new file mode 100644 index 000000000..9a22f6218 --- /dev/null +++ b/Tests/RunCMake/ExternalData/BadRecurse3.cmake @@ -0,0 +1,2 @@ +include(ExternalData) +ExternalData_Expand_Arguments(Data args DATA{Directory1/,RECURSE:x,Data.dat}) diff --git a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake index 241fa1fba..b5ab22d1a 100644 --- a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake @@ -9,6 +9,9 @@ run_cmake(BadCustom4) run_cmake(BadHashAlgo1) run_cmake(BadOption1) run_cmake(BadOption2) +run_cmake(BadRecurse1) +run_cmake(BadRecurse2) +run_cmake(BadRecurse3) run_cmake(BadSeries1) run_cmake(BadSeries2) run_cmake(BadSeries3)