[Cmake-commits] CMake branch, next, updated. v2.8.10.2-1864-gcf15306

Brad King brad.king at kitware.com
Sat Feb 2 07:12:11 EST 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  cf153061aafc919b81cfa75ea92d7a0807014779 (commit)
       via  79d8dc7a3f9859eb1ab52d71507d038a5394df54 (commit)
       via  e2e0d2e3c7108d5ce41f032ad9089155c6b4735c (commit)
       via  ee2abfdc8913e4e9a5bc77c56a9d3dea83fde6f1 (commit)
       via  aa8b2288d320335d28f3777e1bc86ed3df231a09 (commit)
       via  9e518a8169bae33c8a971c146e29b5af20114648 (commit)
       via  175ed02207ea5fe25aa7156acb2554d706611263 (commit)
       via  4befecc77caa97aeb450d9a2b6bcbe0985dc4054 (commit)
       via  bcd25808ac540d279a36a9e0f1b60f152fc0d6bb (commit)
       via  c0cebcb19ae53773f6b21035813c6d58dd829b94 (commit)
       via  52759930bd7a5e1642b16cdc2bde3d23aaaddd2c (commit)
       via  7bb8344d50fa317580068dedd00b019be8a6cb98 (commit)
       via  00d801fbfe9c5170e3a83019cc2e3f6b1ce64200 (commit)
       via  ab26249db107146fc9ad624ac9dddc4052e798d6 (commit)
      from  d36b14199f4757a1d785fe059968dda434552d22 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf153061aafc919b81cfa75ea92d7a0807014779
commit cf153061aafc919b81cfa75ea92d7a0807014779
Merge: d36b141 79d8dc7
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Sat Feb 2 07:12:07 2013 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Sat Feb 2 07:12:07 2013 -0500

    Merge topic 'add-ExternalData-module' into next
    
    79d8dc7 Merge branch 'fix-atomic-rename-on-Windows' into add-ExternalData-module
    e2e0d2e ExternalData: Collapse ../ components in DATA{} paths
    ee2abfd ExternalData: Add support for SHA 1 and 2 hash algorithms
    aa8b228 ExternalData: Generalize hash algo/ext handling
    9e518a8 ExternalData: Allow DATA{} syntax to reference directories
    175ed02 ExternalData: Allow ()-groups in series match regex
    4befecc ExternalData: Add tests covering interfaces and errors
    bcd2580 ExternalData: Improve series matching using an explicit syntax
    c0cebcb ExternalData: Remove unused private interface
    5275993 ExternalData: Cleanup stray TODO and typo in comments
    7bb8344 ExternalData: Do not match directory names when resolving DATA{}
    00d801f ExternalData: Remove compatibility with CMake < 2.8.5
    ab26249 Add ExternalData module


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=79d8dc7a3f9859eb1ab52d71507d038a5394df54
commit 79d8dc7a3f9859eb1ab52d71507d038a5394df54
Merge: e2e0d2e 2e4188e
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 31 15:41:33 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jan 31 15:41:33 2013 -0500

    Merge branch 'fix-atomic-rename-on-Windows' into add-ExternalData-module


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e2e0d2e3c7108d5ce41f032ad9089155c6b4735c
commit e2e0d2e3c7108d5ce41f032ad9089155c6b4735c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Jan 30 14:44:49 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 30 14:55:12 2013 -0500

    ExternalData: Collapse ../ components in DATA{} paths
    
    Relative path components need to be normalized out even if they appear
    in the middle of a caller-supplied string.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 26b0f99..825b7b8 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -334,8 +334,9 @@ function(_ExternalData_arg target arg options var_file)
   if(IS_ABSOLUTE "${data}")
     set(absdata "${data}")
   else()
-    get_filename_component(absdata "${CMAKE_CURRENT_SOURCE_DIR}/${data}" ABSOLUTE)
+    set(absdata "${CMAKE_CURRENT_SOURCE_DIR}/${data}")
   endif()
+  get_filename_component(absdata "${absdata}" ABSOLUTE)
 
   # Convert to relative path under the source tree.
   if(NOT ExternalData_SOURCE_ROOT)
diff --git a/Tests/Module/ExternalData/Data2/CMakeLists.txt b/Tests/Module/ExternalData/Data2/CMakeLists.txt
index e6d8767..c5b79ac 100644
--- a/Tests/Module/ExternalData/Data2/CMakeLists.txt
+++ b/Tests/Module/ExternalData/Data2/CMakeLists.txt
@@ -4,6 +4,7 @@ ExternalData_Add_Test(Data2
   NAME Data2Check
   COMMAND ${CMAKE_COMMAND}
     -D Data2=DATA{../Data2.dat}
+    -D Data2b=DATA{${CMAKE_CURRENT_SOURCE_DIR}/../Data2b.dat}
     -D SeriesC=DATA{SeriesC_1_.my.dat,:}
     -P ${CMAKE_CURRENT_SOURCE_DIR}/Data2Check.cmake
   )
diff --git a/Tests/Module/ExternalData/Data2/Data2Check.cmake b/Tests/Module/ExternalData/Data2/Data2Check.cmake
index a1dd509..d5b0c7b 100644
--- a/Tests/Module/ExternalData/Data2/Data2Check.cmake
+++ b/Tests/Module/ExternalData/Data2/Data2Check.cmake
@@ -1,6 +1,9 @@
-if(NOT EXISTS "${Data2}")
-  message(SEND_ERROR "Input file:\n  ${Data2}\ndoes not exist!")
-endif()
+foreach(d "${Data2}" "${Data2b}")
+  file(STRINGS "${d}" lines LIMIT_INPUT 1024)
+  if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
+    message(SEND_ERROR "Input file:\n  ${d}\ndoes not have expected content, but [[${lines}]]")
+  endif()
+endforeach()
 foreach(n 1 2 3)
   string(REGEX REPLACE "_1_\\.my\\.dat$" "_${n}_.my.dat" SeriesCFile "${SeriesC}")
   if(NOT EXISTS "${SeriesCFile}")
diff --git a/Tests/Module/ExternalData/Data2b.dat.md5 b/Tests/Module/ExternalData/Data2b.dat.md5
new file mode 100644
index 0000000..70e39bd
--- /dev/null
+++ b/Tests/Module/ExternalData/Data2b.dat.md5
@@ -0,0 +1 @@
+8c018830e3efa5caf3c7415028335a57
diff --git a/Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt b/Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt
index 35a8cc1..03924cb 100644
--- a/Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt
+++ b/Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt
@@ -1,2 +1,3 @@
--- Data reference correctly transformed in parent dir!
+-- Data reference correctly transformed in parent dir 1!
+-- Data reference correctly transformed in parent dir 2!
 -- Data reference correctly transformed in current dir!
diff --git a/Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt b/Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt
index 0782460..881ff5c 100644
--- a/Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt
+++ b/Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt
@@ -2,7 +2,17 @@ set(input ../Data.txt)
 set(output ${CMAKE_BINARY_DIR}/Data.txt)
 ExternalData_Expand_Arguments(Data args DATA{${input}})
 if("x${args}" STREQUAL "x${output}")
-  message(STATUS "Data reference correctly transformed in parent dir!")
+  message(STATUS "Data reference correctly transformed in parent dir 1!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
+
+set(input ${CMAKE_CURRENT_SOURCE_DIR}/../Data.txt)
+set(output ${CMAKE_BINARY_DIR}/Data.txt)
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Data reference correctly transformed in parent dir 2!")
 else()
   message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
     "but we expected:\n  ${output}")

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ee2abfdc8913e4e9a5bc77c56a9d3dea83fde6f1
commit ee2abfdc8913e4e9a5bc77c56a9d3dea83fde6f1
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 24 14:12:10 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 30 10:05:07 2013 -0500

    ExternalData: Add support for SHA 1 and 2 hash algorithms
    
    Update the Module.ExternalData and RunCMake.ExternalData tests to cover
    some of them.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index fef8367..26b0f99 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -49,6 +49,11 @@
 #    %(algo)     <ext>     Description
 #    -------     -----     -----------
 #    MD5         .md5      Message-Digest Algorithm 5, RFC 1321
+#    SHA1        .sha1     US Secure Hash Algorithm 1, RFC 3174
+#    SHA224      .sha224   US Secure Hash Algorithms, RFC 4634
+#    SHA256      .sha256   US Secure Hash Algorithms, RFC 4634
+#    SHA384      .sha384   US Secure Hash Algorithms, RFC 4634
+#    SHA512      .sha512   US Secure Hash Algorithms, RFC 4634
 # Note that the hashes are used only for unique data identification and
 # download verification.  This is not security software.
 #
@@ -261,8 +266,8 @@ endfunction()
 #-----------------------------------------------------------------------------
 # Private helper interface
 
-set(_ExternalData_REGEX_ALGO "MD5")
-set(_ExternalData_REGEX_EXT "md5")
+set(_ExternalData_REGEX_ALGO "MD5|SHA1|SHA224|SHA256|SHA384|SHA512")
+set(_ExternalData_REGEX_EXT "md5|sha1|sha224|sha256|sha384|sha512")
 set(_ExternalData_SELF "${CMAKE_CURRENT_LIST_FILE}")
 get_filename_component(_ExternalData_SELF_DIR "${_ExternalData_SELF}" PATH)
 
diff --git a/Tests/Module/ExternalData/CMakeLists.txt b/Tests/Module/ExternalData/CMakeLists.txt
index c9a192b..e69713a 100644
--- a/Tests/Module/ExternalData/CMakeLists.txt
+++ b/Tests/Module/ExternalData/CMakeLists.txt
@@ -22,6 +22,7 @@ ExternalData_Add_Test(Data1
     -D SeriesBn=DATA{SeriesBn_1.dat,:}
     -D SeriesCn=DATA{SeriesCn.1.dat,:}
     -D SeriesDn=DATA{SeriesDn-1.dat,:}
+    -D SeriesMixed=DATA{SeriesMixed.1.dat,:}
     -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}
diff --git a/Tests/Module/ExternalData/Data1Check.cmake b/Tests/Module/ExternalData/Data1Check.cmake
index 972ec46..b99d7ae 100644
--- a/Tests/Module/ExternalData/Data1Check.cmake
+++ b/Tests/Module/ExternalData/Data1Check.cmake
@@ -26,6 +26,12 @@ foreach(s A B C D)
     endif()
   endforeach()
 endforeach()
+foreach(n .1 .2 .3 .4)
+  string(REGEX REPLACE "\\.1\\.dat$" "${n}.dat" file "${SeriesMixed}")
+  if(NOT EXISTS "${file}")
+    message(SEND_ERROR "Input file:\n  ${file}\ndoes not exist!")
+  endif()
+endforeach()
 foreach(n A B)
   string(REGEX REPLACE "A\\.dat$" "${n}.dat" file "${Paired}")
   if(NOT EXISTS "${file}")
diff --git a/Tests/Module/ExternalData/MD5/ce38ea6c3c1e00fa6405dd64b8bf6da0 b/Tests/Module/ExternalData/MD5/ce38ea6c3c1e00fa6405dd64b8bf6da0
new file mode 100644
index 0000000..362d4b4
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/ce38ea6c3c1e00fa6405dd64b8bf6da0
@@ -0,0 +1 @@
+SeriesMixed.1
diff --git a/Tests/Module/ExternalData/SHA1/.gitattributes b/Tests/Module/ExternalData/SHA1/.gitattributes
new file mode 100644
index 0000000..3e51d39
--- /dev/null
+++ b/Tests/Module/ExternalData/SHA1/.gitattributes
@@ -0,0 +1 @@
+*               -crlf
diff --git a/Tests/Module/ExternalData/SHA1/2af59a7022024974f3b8521b7ed8137c996a79f1 b/Tests/Module/ExternalData/SHA1/2af59a7022024974f3b8521b7ed8137c996a79f1
new file mode 100644
index 0000000..a388540
--- /dev/null
+++ b/Tests/Module/ExternalData/SHA1/2af59a7022024974f3b8521b7ed8137c996a79f1
@@ -0,0 +1 @@
+SeriesMixed.2
diff --git a/Tests/Module/ExternalData/SHA224/.gitattributes b/Tests/Module/ExternalData/SHA224/.gitattributes
new file mode 100644
index 0000000..3e51d39
--- /dev/null
+++ b/Tests/Module/ExternalData/SHA224/.gitattributes
@@ -0,0 +1 @@
+*               -crlf
diff --git a/Tests/Module/ExternalData/SHA224/3b679da7908562fe1cc28db47ffb89bae025f4551dceb343a5869174 b/Tests/Module/ExternalData/SHA224/3b679da7908562fe1cc28db47ffb89bae025f4551dceb343a5869174
new file mode 100644
index 0000000..e806d98
--- /dev/null
+++ b/Tests/Module/ExternalData/SHA224/3b679da7908562fe1cc28db47ffb89bae025f4551dceb343a5869174
@@ -0,0 +1 @@
+SeriesMixed.3
diff --git a/Tests/Module/ExternalData/SHA256/.gitattributes b/Tests/Module/ExternalData/SHA256/.gitattributes
new file mode 100644
index 0000000..3e51d39
--- /dev/null
+++ b/Tests/Module/ExternalData/SHA256/.gitattributes
@@ -0,0 +1 @@
+*               -crlf
diff --git a/Tests/Module/ExternalData/SHA256/969171a0dd70d49ce096bd3e8178c7e26c711c9b20dbcaa3853d869d3871f133 b/Tests/Module/ExternalData/SHA256/969171a0dd70d49ce096bd3e8178c7e26c711c9b20dbcaa3853d869d3871f133
new file mode 100644
index 0000000..e3d1e0c
--- /dev/null
+++ b/Tests/Module/ExternalData/SHA256/969171a0dd70d49ce096bd3e8178c7e26c711c9b20dbcaa3853d869d3871f133
@@ -0,0 +1 @@
+SeriesMixed.4
diff --git a/Tests/Module/ExternalData/SeriesMixed.1.dat.md5 b/Tests/Module/ExternalData/SeriesMixed.1.dat.md5
new file mode 100644
index 0000000..f962d8f
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesMixed.1.dat.md5
@@ -0,0 +1 @@
+ce38ea6c3c1e00fa6405dd64b8bf6da0
diff --git a/Tests/Module/ExternalData/SeriesMixed.2.dat.sha1 b/Tests/Module/ExternalData/SeriesMixed.2.dat.sha1
new file mode 100644
index 0000000..43a3540
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesMixed.2.dat.sha1
@@ -0,0 +1 @@
+2af59a7022024974f3b8521b7ed8137c996a79f1
diff --git a/Tests/Module/ExternalData/SeriesMixed.3.dat.sha224 b/Tests/Module/ExternalData/SeriesMixed.3.dat.sha224
new file mode 100644
index 0000000..a18e40e
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesMixed.3.dat.sha224
@@ -0,0 +1 @@
+3b679da7908562fe1cc28db47ffb89bae025f4551dceb343a5869174
diff --git a/Tests/Module/ExternalData/SeriesMixed.4.dat.sha256 b/Tests/Module/ExternalData/SeriesMixed.4.dat.sha256
new file mode 100644
index 0000000..67fc3c2
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesMixed.4.dat.sha256
@@ -0,0 +1 @@
+969171a0dd70d49ce096bd3e8178c7e26c711c9b20dbcaa3853d869d3871f133
diff --git a/Tests/RunCMake/ExternalData/LinkContentSHA1-stdout.txt b/Tests/RunCMake/ExternalData/LinkContentSHA1-stdout.txt
new file mode 100644
index 0000000..9a8eb2e
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/LinkContentSHA1-stdout.txt
@@ -0,0 +1,3 @@
+-- Linked ToLink.txt.sha1 to ExternalData SHA1/114ee5dda251457fd2df63bec91d3b8db43aba58
+-- Raw data correctly transformed to content link!
+-- Staged content exists!
diff --git a/Tests/RunCMake/ExternalData/LinkContentSHA1.cmake b/Tests/RunCMake/ExternalData/LinkContentSHA1.cmake
new file mode 100644
index 0000000..f78501c
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/LinkContentSHA1.cmake
@@ -0,0 +1,22 @@
+include(ExternalData)
+set(ExternalData_LINK_CONTENT SHA1)
+set(ExternalData_SOURCE_ROOT ${CMAKE_CURRENT_BINARY_DIR})
+set(ExternalData_BINARY_ROOT ${CMAKE_CURRENT_BINARY_DIR}/ExternalData)
+set(input ${CMAKE_CURRENT_BINARY_DIR}/ToLink.txt)
+set(output ${CMAKE_CURRENT_BINARY_DIR}/ExternalData/ToLink.txt)
+set(staged "${CMAKE_CURRENT_BINARY_DIR}/.ExternalData_SHA1_114ee5dda251457fd2df63bec91d3b8db43aba58")
+file(REMOVE ${staged})
+file(REMOVE ${input}.sha1)
+file(WRITE ${input} "To be transformed into a content link.")
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Raw data correctly transformed to content link!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
+if(EXISTS "${staged}")
+  message(STATUS "Staged content exists!")
+else()
+  message(FATAL_ERROR "Staged content missing!")
+endif()
diff --git a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
index fc85a21..5ee46c9 100644
--- a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
@@ -12,6 +12,7 @@ run_cmake(Directory3)
 run_cmake(Directory4)
 run_cmake(Directory5)
 run_cmake(LinkContentMD5)
+run_cmake(LinkContentSHA1)
 run_cmake(MissingData)
 run_cmake(NoLinkInSource)
 run_cmake(NoURLTemplates)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aa8b2288d320335d28f3777e1bc86ed3df231a09
commit aa8b2288d320335d28f3777e1bc86ed3df231a09
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 24 14:09:39 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 30 10:05:07 2013 -0500

    ExternalData: Generalize hash algo/ext handling
    
    Use private global variables _ExternalData_REGEX_(ALGO|EXT) to match the
    possible hash algorithm names and extensions in regular expressions.
    Use "file(<algo>)" instead of "cmake -E md5sum" to compute hashes
    without a child process and to support more hash algorithms.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 43ff517..fef8367 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -261,18 +261,16 @@ endfunction()
 #-----------------------------------------------------------------------------
 # Private helper interface
 
+set(_ExternalData_REGEX_ALGO "MD5")
+set(_ExternalData_REGEX_EXT "md5")
 set(_ExternalData_SELF "${CMAKE_CURRENT_LIST_FILE}")
 get_filename_component(_ExternalData_SELF_DIR "${_ExternalData_SELF}" PATH)
 
 function(_ExternalData_compute_hash var_hash algo file)
-  if("${algo}" STREQUAL "MD5")
-    # TODO: Errors
-    execute_process(COMMAND "${CMAKE_COMMAND}" -E md5sum "${file}"
-      OUTPUT_VARIABLE output)
-    string(SUBSTRING "${output}" 0 32 hash)
+  if("${algo}" MATCHES "^${_ExternalData_REGEX_ALGO}$")
+    file("${algo}" "${file}" hash)
     set("${var_hash}" "${hash}" PARENT_SCOPE)
   else()
-    # TODO: Other hashes.
     message(FATAL_ERROR "Hash algorithm ${algo} unimplemented.")
   endif()
 endfunction()
@@ -295,7 +293,7 @@ function(_ExternalData_atomic_write file content)
 endfunction()
 
 function(_ExternalData_link_content name var_ext)
-  if("${ExternalData_LINK_CONTENT}" MATCHES "^(MD5)$")
+  if("${ExternalData_LINK_CONTENT}" MATCHES "^(${_ExternalData_REGEX_ALGO})$")
     set(algo "${ExternalData_LINK_CONTENT}")
   else()
     message(FATAL_ERROR
@@ -305,7 +303,7 @@ function(_ExternalData_link_content name var_ext)
   _ExternalData_compute_hash(hash "${algo}" "${name}")
   get_filename_component(dir "${name}" PATH)
   set(staged "${dir}/.ExternalData_${algo}_${hash}")
-  set(ext ".md5")
+  string(TOLOWER ".${algo}" ext)
   _ExternalData_atomic_write("${name}${ext}" "${hash}\n")
   file(RENAME "${name}" "${staged}")
   set("${var_ext}" "${ext}" PARENT_SCOPE)
@@ -533,7 +531,7 @@ endmacro()
 function(_ExternalData_arg_find_files pattern regex)
   file(GLOB globbed RELATIVE "${top_src}" "${top_src}/${pattern}*")
   foreach(entry IN LISTS globbed)
-    if("x${entry}" MATCHES "^x(.*)(\\.md5)$")
+    if("x${entry}" MATCHES "^x(.*)(\\.(${_ExternalData_REGEX_EXT}))$")
       set(relname "${CMAKE_MATCH_1}")
       set(alg "${CMAKE_MATCH_2}")
     else()
@@ -716,8 +714,8 @@ if("${ExternalData_ACTION}" STREQUAL "fetch")
   file(READ "${name}${ext}" hash)
   string(STRIP "${hash}" hash)
 
-  if("${ext}" STREQUAL ".md5")
-    set(algo "MD5")
+  if("${ext}" MATCHES "^\\.(${_ExternalData_REGEX_EXT})$")
+    string(TOUPPER "${CMAKE_MATCH_1}" algo)
   else()
     message(FATAL_ERROR "Unknown hash algorithm extension \"${ext}\"")
   endif()

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9e518a8169bae33c8a971c146e29b5af20114648
commit 9e518a8169bae33c8a971c146e29b5af20114648
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jan 29 15:12:08 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 30 10:05:07 2013 -0500

    ExternalData: Allow DATA{} syntax to reference directories
    
    Use a trailing slash to reference a directory.  Require that a list
    of associated files be specified to select from within the directory.
    One may simply use DATA{Dir/,REGEX:.*} to reference all files but
    get a directory passed on the command line.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 6442c3e..43ff517 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -97,6 +97,14 @@
 # will pass MyInput.mha and MyFrames00.png on the command line but ensure
 # that the associated files are present next to them.
 #
+# The DATA{} syntax may reference a directory using a trailing slash and a
+# list of associated files.  The form DATA{<name>/,<opt1>,<opt2>,...} adds
+# rules to fetch any files in the directory that match one of the 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.
+#
 # The variable ExternalData_LINK_CONTENT may be set to the name of a supported
 # hash algorithm to enable automatic conversion of real data files referenced
 # by the DATA{} syntax into content links.  For each such <file> a content
@@ -312,11 +320,11 @@ function(_ExternalData_arg target arg options var_file)
   list(GET options 0 data)
   list(REMOVE_AT options 0)
 
-  # Reject trailing slashes.
-  if("x${data}" MATCHES "[/\\]$")
-    message(FATAL_ERROR "Data file reference in argument\n"
-      "  ${arg}\n"
-      "may not end in a slash!")
+  # Interpret trailing slashes as directories.
+  set(data_is_directory 0)
+  if("x${data}" MATCHES "^x(.*)([/\\])$")
+    set(data_is_directory 1)
+    set(data "${CMAKE_MATCH_1}")
   endif()
 
   # Convert to full path.
@@ -338,6 +346,13 @@ function(_ExternalData_arg target arg options var_file)
       "does not lie under the top-level source directory\n"
       "  ${top_src}\n")
   endif()
+  if(data_is_directory AND NOT IS_DIRECTORY "${top_src}/${reldata}")
+    message(FATAL_ERROR "Data directory referenced by argument\n"
+      "  ${arg}\n"
+      "corresponds to source tree path\n"
+      "  ${reldata}\n"
+      "that does not exist as a directory!")
+  endif()
   if(NOT ExternalData_BINARY_ROOT)
     set(ExternalData_BINARY_ROOT "${CMAKE_BINARY_DIR}")
   endif()
@@ -354,7 +369,7 @@ function(_ExternalData_arg target arg options var_file)
 
   set(external "") # Entries external to the source tree.
   set(internal "") # Entries internal to the source tree.
-  set(have_original 0)
+  set(have_original ${data_is_directory})
 
   # Process options.
   set(series_option "")
@@ -378,11 +393,23 @@ function(_ExternalData_arg target arg options var_file)
   endforeach()
 
   if(series_option)
+    if(data_is_directory)
+      message(FATAL_ERROR "Series option \"${series_option}\" not allowed with directories.")
+    endif()
     if(associated_files OR associated_regex)
       message(FATAL_ERROR "Series option \"${series_option}\" not allowed with associated files.")
     endif()
     # Load a whole file series.
     _ExternalData_arg_series()
+  elseif(data_is_directory)
+    if(associated_files OR associated_regex)
+      # Load listed/matching associated files in the directory.
+      _ExternalData_arg_associated()
+    else()
+      message(FATAL_ERROR "Data directory referenced by argument\n"
+        "  ${arg}\n"
+        "must list associated files.")
+    endif()
   else()
     # Load the named data file.
     _ExternalData_arg_single()
@@ -415,7 +442,11 @@ endfunction()
 
 macro(_ExternalData_arg_associated)
   # Associated files lie in the same directory.
-  get_filename_component(reldir "${reldata}" PATH)
+  if(data_is_directory)
+    set(reldir "${reldata}")
+  else()
+    get_filename_component(reldir "${reldata}" PATH)
+  endif()
   if(reldir)
     set(reldir "${reldir}/")
   endif()
diff --git a/Tests/Module/ExternalData/CMakeLists.txt b/Tests/Module/ExternalData/CMakeLists.txt
index 5532610..c9a192b 100644
--- a/Tests/Module/ExternalData/CMakeLists.txt
+++ b/Tests/Module/ExternalData/CMakeLists.txt
@@ -24,6 +24,7 @@ ExternalData_Add_Test(Data1
     -D SeriesDn=DATA{SeriesDn-1.dat,:}
     -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}
     -P ${CMAKE_CURRENT_SOURCE_DIR}/Data1Check.cmake
   )
 ExternalData_Add_Target(Data1)
diff --git a/Tests/Module/ExternalData/Data1Check.cmake b/Tests/Module/ExternalData/Data1Check.cmake
index fd18cdf..972ec46 100644
--- a/Tests/Module/ExternalData/Data1Check.cmake
+++ b/Tests/Module/ExternalData/Data1Check.cmake
@@ -38,3 +38,9 @@ foreach(n Top A B C)
     message(SEND_ERROR "Input file:\n  ${file}\ndoes not exist!")
   endif()
 endforeach()
+foreach(n A B C)
+  set(file "${Directory}/${n}.dat")
+  if(NOT EXISTS "${file}")
+    message(SEND_ERROR "Input file:\n  ${file}\ndoes not exist!")
+  endif()
+endforeach()
diff --git a/Tests/Module/ExternalData/Directory/A.dat.md5 b/Tests/Module/ExternalData/Directory/A.dat.md5
new file mode 100644
index 0000000..4a78fc7
--- /dev/null
+++ b/Tests/Module/ExternalData/Directory/A.dat.md5
@@ -0,0 +1 @@
+9d980b06c2f0fec3d4872d68175b9822
diff --git a/Tests/Module/ExternalData/Directory/B.dat.md5 b/Tests/Module/ExternalData/Directory/B.dat.md5
new file mode 100644
index 0000000..4557a21
--- /dev/null
+++ b/Tests/Module/ExternalData/Directory/B.dat.md5
@@ -0,0 +1 @@
+8f4add4581551facf27237e6577fd662
diff --git a/Tests/Module/ExternalData/Directory/C.dat.md5 b/Tests/Module/ExternalData/Directory/C.dat.md5
new file mode 100644
index 0000000..a7f23dd
--- /dev/null
+++ b/Tests/Module/ExternalData/Directory/C.dat.md5
@@ -0,0 +1 @@
+c1030719c95f3435d8abc39c0d442946
diff --git a/Tests/RunCMake/ExternalData/Directory2-stderr.txt b/Tests/RunCMake/ExternalData/Directory2-stderr.txt
index dc1a59a..92c9a2f 100644
--- a/Tests/RunCMake/ExternalData/Directory2-stderr.txt
+++ b/Tests/RunCMake/ExternalData/Directory2-stderr.txt
@@ -1,9 +1,9 @@
 CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
-  Data file reference in argument
+  Data directory referenced by argument
 
     DATA{Directory2/}
 
-  may not end in a slash!
+  must list associated files.
 Call Stack \(most recent call first\):
   .*
   Directory2.cmake:3 \(ExternalData_Add_Test\)
diff --git a/Tests/RunCMake/ExternalData/Directory4-result.txt b/Tests/RunCMake/ExternalData/Directory4-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/Directory2-stderr.txt b/Tests/RunCMake/ExternalData/Directory4-stderr.txt
similarity index 51%
copy from Tests/RunCMake/ExternalData/Directory2-stderr.txt
copy to Tests/RunCMake/ExternalData/Directory4-stderr.txt
index dc1a59a..dcb8522 100644
--- a/Tests/RunCMake/ExternalData/Directory2-stderr.txt
+++ b/Tests/RunCMake/ExternalData/Directory4-stderr.txt
@@ -1,10 +1,6 @@
 CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
-  Data file reference in argument
-
-    DATA{Directory2/}
-
-  may not end in a slash!
+  Series option ":" not allowed with directories.
 Call Stack \(most recent call first\):
   .*
-  Directory2.cmake:3 \(ExternalData_Add_Test\)
+  Directory4.cmake:3 \(ExternalData_Add_Test\)
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/Directory4.cmake b/Tests/RunCMake/ExternalData/Directory4.cmake
new file mode 100644
index 0000000..7d3d638
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory4.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{Directory4/,:}
+  )
diff --git a/Tests/RunCMake/ExternalData/Directory4/DirData4.txt b/Tests/RunCMake/ExternalData/Directory4/DirData4.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/ExternalData/Directory5-result.txt b/Tests/RunCMake/ExternalData/Directory5-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/Directory5-stderr.txt b/Tests/RunCMake/ExternalData/Directory5-stderr.txt
new file mode 100644
index 0000000..8e54aec
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory5-stderr.txt
@@ -0,0 +1,14 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Data directory referenced by argument
+
+    DATA{Directory5/}
+
+  corresponds to source tree path
+
+    Directory5
+
+  that does not exist as a directory!
+Call Stack \(most recent call first\):
+  .*
+  Directory5.cmake:3 \(ExternalData_Add_Test\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/Directory5.cmake b/Tests/RunCMake/ExternalData/Directory5.cmake
new file mode 100644
index 0000000..931589e
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory5.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{Directory5/}
+  )
diff --git a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
index c61527e..fc85a21 100644
--- a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
@@ -9,6 +9,8 @@ run_cmake(BadSeries3)
 run_cmake(Directory1)
 run_cmake(Directory2)
 run_cmake(Directory3)
+run_cmake(Directory4)
+run_cmake(Directory5)
 run_cmake(LinkContentMD5)
 run_cmake(MissingData)
 run_cmake(NoLinkInSource)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=175ed02207ea5fe25aa7156acb2554d706611263
commit 175ed02207ea5fe25aa7156acb2554d706611263
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jan 29 10:26:11 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 30 10:05:07 2013 -0500

    ExternalData: Allow ()-groups in series match regex
    
    Refactor use of the ExternalData_SERIES_MATCH value to avoid assuming
    that it has no ()-groups that interfere with group indexing.
    
    Extend the Module.ExternalData test to cover this case.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 0ef514c..6442c3e 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -502,11 +502,14 @@ endmacro()
 function(_ExternalData_arg_find_files pattern regex)
   file(GLOB globbed RELATIVE "${top_src}" "${top_src}/${pattern}*")
   foreach(entry IN LISTS globbed)
-    string(REGEX REPLACE "^(${regex})(\\.md5|)$" "\\1;\\2" tuple "${entry}")
-    list(LENGTH tuple len)
-    if("${len}" EQUAL 2 AND NOT IS_DIRECTORY "${top_src}/${entry}")
-      list(GET tuple 0 relname)
-      list(GET tuple 1 alg)
+    if("x${entry}" MATCHES "^x(.*)(\\.md5)$")
+      set(relname "${CMAKE_MATCH_1}")
+      set(alg "${CMAKE_MATCH_2}")
+    else()
+      set(relname "${entry}")
+      set(alg "")
+    endif()
+    if("x${relname}" MATCHES "^x${regex}$" AND NOT IS_DIRECTORY "${top_src}/${entry}")
       set(name "${top_src}/${relname}")
       set(file "${top_bin}/${relname}")
       if(alg)
diff --git a/Tests/Module/ExternalData/Data2/CMakeLists.txt b/Tests/Module/ExternalData/Data2/CMakeLists.txt
index f8eedff..e6d8767 100644
--- a/Tests/Module/ExternalData/Data2/CMakeLists.txt
+++ b/Tests/Module/ExternalData/Data2/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(ExternalData_SERIES_PARSE "([0-9]+)(_\\.my\\.dat)$")
-set(ExternalData_SERIES_MATCH "[0-9]+")
+set(ExternalData_SERIES_MATCH "([0-9]+)")
 ExternalData_Add_Test(Data2
   NAME Data2Check
   COMMAND ${CMAKE_COMMAND}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4befecc77caa97aeb450d9a2b6bcbe0985dc4054
commit 4befecc77caa97aeb450d9a2b6bcbe0985dc4054
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jan 25 16:39:57 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 30 10:04:54 2013 -0500

    ExternalData: Add tests covering interfaces and errors
    
    Add a Module.ExternalData test to verify data retrieval and test
    argument DATA{} references.
    
    Add a RunCMake.ExternalData test to verify error handling and automatic
    transformation of a raw data to a content link and staged object.

diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 0c75892..c21922e 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -312,6 +312,18 @@ if(BUILD_TESTING)
 
   ADD_TEST_MACRO(Module.CheckTypeSize CheckTypeSize)
 
+  add_test(Module.ExternalData ${CMAKE_CTEST_COMMAND}
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/Module/ExternalData"
+    "${CMake_BINARY_DIR}/Tests/Module/ExternalData"
+    --build-generator ${CMAKE_TEST_GENERATOR}
+    --build-project ExternalDataTest
+    --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
+    --force-new-ctest-process
+    --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} -V
+    )
+  list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Module/ExternalData")
+
   ADD_TEST_MACRO(Module.GenerateExportHeader GenerateExportHeader)
 
   if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
diff --git a/Tests/Module/ExternalData/CMakeLists.txt b/Tests/Module/ExternalData/CMakeLists.txt
new file mode 100644
index 0000000..5532610
--- /dev/null
+++ b/Tests/Module/ExternalData/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 2.8.10.20130115)
+project(ExternalDataTest NONE)
+
+include(CTest)
+
+include(ExternalData)
+set(ExternalData_URL_TEMPLATES
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/%(algo)/%(hash)"
+  )
+set(ExternalData_BINARY_ROOT "${CMAKE_CURRENT_BINARY_DIR}/ExternalData")
+file(REMOVE_RECURSE ${ExternalData_BINARY_ROOT}) # clean test
+
+ExternalData_Add_Test(Data1
+  NAME Data1Check
+  COMMAND ${CMAKE_COMMAND}
+    -D Data=DATA{Data.dat}
+    -D SeriesA=DATA{SeriesA.dat,:}
+    -D SeriesB=DATA{SeriesB.dat,:}
+    -D SeriesC=DATA{SeriesC.dat,:}
+    -D SeriesD=DATA{SeriesD.dat,:}
+    -D SeriesAn=DATA{SeriesAn1.dat,:}
+    -D SeriesBn=DATA{SeriesBn_1.dat,:}
+    -D SeriesCn=DATA{SeriesCn.1.dat,:}
+    -D SeriesDn=DATA{SeriesDn-1.dat,:}
+    -D Paired=DATA{PairedA.dat,PairedB.dat}
+    -D Meta=DATA{MetaTop.dat,REGEX:Meta[ABC].dat}
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/Data1Check.cmake
+  )
+ExternalData_Add_Target(Data1)
+
+add_subdirectory(Data2)
+add_subdirectory(Data3)
diff --git a/Tests/Module/ExternalData/Data.dat.md5 b/Tests/Module/ExternalData/Data.dat.md5
new file mode 100644
index 0000000..70e39bd
--- /dev/null
+++ b/Tests/Module/ExternalData/Data.dat.md5
@@ -0,0 +1 @@
+8c018830e3efa5caf3c7415028335a57
diff --git a/Tests/Module/ExternalData/Data1Check.cmake b/Tests/Module/ExternalData/Data1Check.cmake
new file mode 100644
index 0000000..fd18cdf
--- /dev/null
+++ b/Tests/Module/ExternalData/Data1Check.cmake
@@ -0,0 +1,40 @@
+file(STRINGS "${Data}" lines LIMIT_INPUT 1024)
+if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
+  message(SEND_ERROR "Input file:\n  ${Data}\ndoes not have expected content, but [[${lines}]]")
+endif()
+set(SeriesAn1 "1\\.dat")
+set(SeriesBn1 "_1\\.dat")
+set(SeriesCn1 "\\.1\\.dat")
+set(SeriesDn1 "-1\\.dat")
+set(SeriesAl 1 2 3)
+set(SeriesBl _1 _2 _3)
+set(SeriesCl .1 .2 .3)
+set(SeriesDl -1 -2 -3)
+foreach(s A B C D)
+  foreach(n "" ${Series${s}l})
+    string(REGEX REPLACE "\\.dat$" "${n}.dat" file "${Series${s}}")
+    if(NOT EXISTS "${file}")
+      message(SEND_ERROR "Input file:\n  ${file}\ndoes not exist!")
+    endif()
+  endforeach()
+endforeach()
+foreach(s A B C D)
+  foreach(n ${Series${s}l})
+    string(REGEX REPLACE "${Series${s}n1}$" "${n}.dat" file "${Series${s}n}")
+    if(NOT EXISTS "${file}")
+      message(SEND_ERROR "Input file:\n  ${file}\ndoes not exist!")
+    endif()
+  endforeach()
+endforeach()
+foreach(n A B)
+  string(REGEX REPLACE "A\\.dat$" "${n}.dat" file "${Paired}")
+  if(NOT EXISTS "${file}")
+    message(SEND_ERROR "Input file:\n  ${file}\ndoes not exist!")
+  endif()
+endforeach()
+foreach(n Top A B C)
+  string(REGEX REPLACE "Top\\.dat$" "${n}.dat" file "${Meta}")
+  if(NOT EXISTS "${file}")
+    message(SEND_ERROR "Input file:\n  ${file}\ndoes not exist!")
+  endif()
+endforeach()
diff --git a/Tests/Module/ExternalData/Data2.dat.md5 b/Tests/Module/ExternalData/Data2.dat.md5
new file mode 100644
index 0000000..70e39bd
--- /dev/null
+++ b/Tests/Module/ExternalData/Data2.dat.md5
@@ -0,0 +1 @@
+8c018830e3efa5caf3c7415028335a57
diff --git a/Tests/Module/ExternalData/Data2/CMakeLists.txt b/Tests/Module/ExternalData/Data2/CMakeLists.txt
new file mode 100644
index 0000000..f8eedff
--- /dev/null
+++ b/Tests/Module/ExternalData/Data2/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(ExternalData_SERIES_PARSE "([0-9]+)(_\\.my\\.dat)$")
+set(ExternalData_SERIES_MATCH "[0-9]+")
+ExternalData_Add_Test(Data2
+  NAME Data2Check
+  COMMAND ${CMAKE_COMMAND}
+    -D Data2=DATA{../Data2.dat}
+    -D SeriesC=DATA{SeriesC_1_.my.dat,:}
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/Data2Check.cmake
+  )
+ExternalData_Add_Target(Data2)
diff --git a/Tests/Module/ExternalData/Data2/Data2Check.cmake b/Tests/Module/ExternalData/Data2/Data2Check.cmake
new file mode 100644
index 0000000..a1dd509
--- /dev/null
+++ b/Tests/Module/ExternalData/Data2/Data2Check.cmake
@@ -0,0 +1,9 @@
+if(NOT EXISTS "${Data2}")
+  message(SEND_ERROR "Input file:\n  ${Data2}\ndoes not exist!")
+endif()
+foreach(n 1 2 3)
+  string(REGEX REPLACE "_1_\\.my\\.dat$" "_${n}_.my.dat" SeriesCFile "${SeriesC}")
+  if(NOT EXISTS "${SeriesCFile}")
+    message(SEND_ERROR "Input file:\n  ${SeriesCFile}\ndoes not exist!")
+  endif()
+endforeach()
diff --git a/Tests/Module/ExternalData/Data2/SeriesC_1_.my.dat.md5 b/Tests/Module/ExternalData/Data2/SeriesC_1_.my.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/Data2/SeriesC_1_.my.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/Data2/SeriesC_2_.my.dat.md5 b/Tests/Module/ExternalData/Data2/SeriesC_2_.my.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/Data2/SeriesC_2_.my.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/Data2/SeriesC_3_.my.dat.md5 b/Tests/Module/ExternalData/Data2/SeriesC_3_.my.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/Data2/SeriesC_3_.my.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/Data3/CMakeLists.txt b/Tests/Module/ExternalData/Data3/CMakeLists.txt
new file mode 100644
index 0000000..a7c2b6e
--- /dev/null
+++ b/Tests/Module/ExternalData/Data3/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(Store0 ${CMAKE_BINARY_DIR}/ExternalData/Other)
+set(Store1 ${CMAKE_BINARY_DIR}/ExternalData/Objects)
+set(ExternalData_OBJECT_STORES ${Store0} ${Store1})
+ExternalData_Add_Test(Data3
+  NAME Data3Check
+  COMMAND ${CMAKE_COMMAND}
+    -D Data=DATA{Data.dat}
+    -D Other=DATA{Other.dat}
+    -D Store0=${Store0}
+    -D Store1=${Store1}
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/Data3Check.cmake
+  )
+ExternalData_Add_Target(Data3)
+add_dependencies(Data3 Data1 Data2)
diff --git a/Tests/Module/ExternalData/Data3/Data.dat.md5 b/Tests/Module/ExternalData/Data3/Data.dat.md5
new file mode 100644
index 0000000..70e39bd
--- /dev/null
+++ b/Tests/Module/ExternalData/Data3/Data.dat.md5
@@ -0,0 +1 @@
+8c018830e3efa5caf3c7415028335a57
diff --git a/Tests/Module/ExternalData/Data3/Data3Check.cmake b/Tests/Module/ExternalData/Data3/Data3Check.cmake
new file mode 100644
index 0000000..de98839
--- /dev/null
+++ b/Tests/Module/ExternalData/Data3/Data3Check.cmake
@@ -0,0 +1,25 @@
+if(NOT EXISTS "${Data}")
+  message(SEND_ERROR "Input file:\n  ${Data}\ndoes not exist!")
+endif()
+if(NOT EXISTS "${Other}")
+  message(SEND_ERROR "Input file:\n  ${Other}\ndoes not exist!")
+endif()
+# Verify that the 'Data' object was found in the second store location left
+# from Data1 target downloads and that the 'Other' object was downloaded to
+# our first store location.  Neither object should exist in the other store.
+foreach(should_exist
+    "${Store0}/MD5/aaad162b85f60d1eb57ca71a23e8efd7"
+    "${Store1}/MD5/8c018830e3efa5caf3c7415028335a57"
+    )
+  if(NOT EXISTS ${should_exist})
+    message(SEND_ERROR "Store file:\n  ${should_exist}\nshould exist!")
+  endif()
+endforeach()
+foreach(should_not_exist
+    "${Store0}/MD5/8c018830e3efa5caf3c7415028335a57"
+    "${Store1}/MD5/aaad162b85f60d1eb57ca71a23e8efd7"
+    )
+  if(EXISTS ${should_not_exist})
+    message(SEND_ERROR "Store file:\n  ${should_not_exist}\nshould not exist!")
+  endif()
+endforeach()
diff --git a/Tests/Module/ExternalData/Data3/Other.dat.md5 b/Tests/Module/ExternalData/Data3/Other.dat.md5
new file mode 100644
index 0000000..5312faa
--- /dev/null
+++ b/Tests/Module/ExternalData/Data3/Other.dat.md5
@@ -0,0 +1 @@
+aaad162b85f60d1eb57ca71a23e8efd7
diff --git a/Tests/Module/ExternalData/MD5/.gitattributes b/Tests/Module/ExternalData/MD5/.gitattributes
new file mode 100644
index 0000000..3e51d39
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/.gitattributes
@@ -0,0 +1 @@
+*               -crlf
diff --git a/Tests/Module/ExternalData/MD5/08cfcf221f76ace7b906b312284e73d7 b/Tests/Module/ExternalData/MD5/08cfcf221f76ace7b906b312284e73d7
new file mode 100644
index 0000000..a689e3c
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/08cfcf221f76ace7b906b312284e73d7
@@ -0,0 +1 @@
+MetaTop
diff --git a/Tests/Module/ExternalData/MD5/30ba0acdee9096b3b9fc6c69362c6b42 b/Tests/Module/ExternalData/MD5/30ba0acdee9096b3b9fc6c69362c6b42
new file mode 100644
index 0000000..5491241
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/30ba0acdee9096b3b9fc6c69362c6b42
@@ -0,0 +1 @@
+Series.3
diff --git a/Tests/Module/ExternalData/MD5/31eff09e84fca01415f8cd9d82ec432b b/Tests/Module/ExternalData/MD5/31eff09e84fca01415f8cd9d82ec432b
new file mode 100644
index 0000000..4d0475e
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/31eff09e84fca01415f8cd9d82ec432b
@@ -0,0 +1 @@
+Series.1
diff --git a/Tests/Module/ExternalData/MD5/401767f22a456b3522953722090a2c36 b/Tests/Module/ExternalData/MD5/401767f22a456b3522953722090a2c36
new file mode 100644
index 0000000..9dec116
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/401767f22a456b3522953722090a2c36
@@ -0,0 +1 @@
+PairedA
diff --git a/Tests/Module/ExternalData/MD5/8c018830e3efa5caf3c7415028335a57 b/Tests/Module/ExternalData/MD5/8c018830e3efa5caf3c7415028335a57
new file mode 100644
index 0000000..fa701e2
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/8c018830e3efa5caf3c7415028335a57
@@ -0,0 +1 @@
+Input file already transformed.
diff --git a/Tests/Module/ExternalData/MD5/8f4add4581551facf27237e6577fd662 b/Tests/Module/ExternalData/MD5/8f4add4581551facf27237e6577fd662
new file mode 100644
index 0000000..69ba09c
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/8f4add4581551facf27237e6577fd662
@@ -0,0 +1 @@
+MetaB
diff --git a/Tests/Module/ExternalData/MD5/9d980b06c2f0fec3d4872d68175b9822 b/Tests/Module/ExternalData/MD5/9d980b06c2f0fec3d4872d68175b9822
new file mode 100644
index 0000000..000e7b2
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/9d980b06c2f0fec3d4872d68175b9822
@@ -0,0 +1 @@
+MetaA
diff --git a/Tests/Module/ExternalData/MD5/aaad162b85f60d1eb57ca71a23e8efd7 b/Tests/Module/ExternalData/MD5/aaad162b85f60d1eb57ca71a23e8efd7
new file mode 100644
index 0000000..df0510c
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/aaad162b85f60d1eb57ca71a23e8efd7
@@ -0,0 +1 @@
+Another input file already transformed.
diff --git a/Tests/Module/ExternalData/MD5/c1030719c95f3435d8abc39c0d442946 b/Tests/Module/ExternalData/MD5/c1030719c95f3435d8abc39c0d442946
new file mode 100644
index 0000000..3fac5e6
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/c1030719c95f3435d8abc39c0d442946
@@ -0,0 +1 @@
+MetaC
diff --git a/Tests/Module/ExternalData/MD5/ecfa1ecd417d4253af81ae04d1bd6581 b/Tests/Module/ExternalData/MD5/ecfa1ecd417d4253af81ae04d1bd6581
new file mode 100644
index 0000000..8c414f5
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/ecfa1ecd417d4253af81ae04d1bd6581
@@ -0,0 +1 @@
+PairedB
diff --git a/Tests/Module/ExternalData/MD5/f41c94425d01ecbbee70440b951cb058 b/Tests/Module/ExternalData/MD5/f41c94425d01ecbbee70440b951cb058
new file mode 100644
index 0000000..3503da4
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/f41c94425d01ecbbee70440b951cb058
@@ -0,0 +1 @@
+Series
diff --git a/Tests/Module/ExternalData/MD5/f7ab5a04aae9cb9a520e70b20b9c8ed7 b/Tests/Module/ExternalData/MD5/f7ab5a04aae9cb9a520e70b20b9c8ed7
new file mode 100644
index 0000000..29d727b
--- /dev/null
+++ b/Tests/Module/ExternalData/MD5/f7ab5a04aae9cb9a520e70b20b9c8ed7
@@ -0,0 +1 @@
+Series.2
diff --git a/Tests/Module/ExternalData/MetaA.dat.md5 b/Tests/Module/ExternalData/MetaA.dat.md5
new file mode 100644
index 0000000..4a78fc7
--- /dev/null
+++ b/Tests/Module/ExternalData/MetaA.dat.md5
@@ -0,0 +1 @@
+9d980b06c2f0fec3d4872d68175b9822
diff --git a/Tests/Module/ExternalData/MetaB.dat.md5 b/Tests/Module/ExternalData/MetaB.dat.md5
new file mode 100644
index 0000000..4557a21
--- /dev/null
+++ b/Tests/Module/ExternalData/MetaB.dat.md5
@@ -0,0 +1 @@
+8f4add4581551facf27237e6577fd662
diff --git a/Tests/Module/ExternalData/MetaC.dat.md5 b/Tests/Module/ExternalData/MetaC.dat.md5
new file mode 100644
index 0000000..a7f23dd
--- /dev/null
+++ b/Tests/Module/ExternalData/MetaC.dat.md5
@@ -0,0 +1 @@
+c1030719c95f3435d8abc39c0d442946
diff --git a/Tests/Module/ExternalData/MetaTop.dat.md5 b/Tests/Module/ExternalData/MetaTop.dat.md5
new file mode 100644
index 0000000..1906cbf
--- /dev/null
+++ b/Tests/Module/ExternalData/MetaTop.dat.md5
@@ -0,0 +1 @@
+08cfcf221f76ace7b906b312284e73d7
diff --git a/Tests/Module/ExternalData/PairedA.dat.md5 b/Tests/Module/ExternalData/PairedA.dat.md5
new file mode 100644
index 0000000..1ffe035
--- /dev/null
+++ b/Tests/Module/ExternalData/PairedA.dat.md5
@@ -0,0 +1 @@
+401767f22a456b3522953722090a2c36
diff --git a/Tests/Module/ExternalData/PairedB.dat.md5 b/Tests/Module/ExternalData/PairedB.dat.md5
new file mode 100644
index 0000000..89c942b
--- /dev/null
+++ b/Tests/Module/ExternalData/PairedB.dat.md5
@@ -0,0 +1 @@
+ecfa1ecd417d4253af81ae04d1bd6581
diff --git a/Tests/Module/ExternalData/SeriesA.dat.md5 b/Tests/Module/ExternalData/SeriesA.dat.md5
new file mode 100644
index 0000000..be2d687
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesA.dat.md5
@@ -0,0 +1 @@
+f41c94425d01ecbbee70440b951cb058
diff --git a/Tests/Module/ExternalData/SeriesA1.dat.md5 b/Tests/Module/ExternalData/SeriesA1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesA1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesA2.dat.md5 b/Tests/Module/ExternalData/SeriesA2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesA2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesA3.dat.md5 b/Tests/Module/ExternalData/SeriesA3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesA3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/SeriesAn1.dat.md5 b/Tests/Module/ExternalData/SeriesAn1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesAn1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesAn2.dat.md5 b/Tests/Module/ExternalData/SeriesAn2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesAn2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesAn3.dat.md5 b/Tests/Module/ExternalData/SeriesAn3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesAn3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/SeriesB.dat.md5 b/Tests/Module/ExternalData/SeriesB.dat.md5
new file mode 100644
index 0000000..be2d687
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesB.dat.md5
@@ -0,0 +1 @@
+f41c94425d01ecbbee70440b951cb058
diff --git a/Tests/Module/ExternalData/SeriesB_1.dat.md5 b/Tests/Module/ExternalData/SeriesB_1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesB_1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesB_2.dat.md5 b/Tests/Module/ExternalData/SeriesB_2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesB_2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesB_3.dat.md5 b/Tests/Module/ExternalData/SeriesB_3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesB_3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/SeriesBn_1.dat.md5 b/Tests/Module/ExternalData/SeriesBn_1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesBn_1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesBn_2.dat.md5 b/Tests/Module/ExternalData/SeriesBn_2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesBn_2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesBn_3.dat.md5 b/Tests/Module/ExternalData/SeriesBn_3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesBn_3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/SeriesC.1.dat.md5 b/Tests/Module/ExternalData/SeriesC.1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesC.1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesC.2.dat.md5 b/Tests/Module/ExternalData/SeriesC.2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesC.2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesC.3.dat.md5 b/Tests/Module/ExternalData/SeriesC.3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesC.3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/SeriesC.dat.md5 b/Tests/Module/ExternalData/SeriesC.dat.md5
new file mode 100644
index 0000000..be2d687
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesC.dat.md5
@@ -0,0 +1 @@
+f41c94425d01ecbbee70440b951cb058
diff --git a/Tests/Module/ExternalData/SeriesCn.1.dat.md5 b/Tests/Module/ExternalData/SeriesCn.1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesCn.1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesCn.2.dat.md5 b/Tests/Module/ExternalData/SeriesCn.2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesCn.2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesCn.3.dat.md5 b/Tests/Module/ExternalData/SeriesCn.3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesCn.3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/SeriesD-1.dat.md5 b/Tests/Module/ExternalData/SeriesD-1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesD-1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesD-2.dat.md5 b/Tests/Module/ExternalData/SeriesD-2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesD-2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesD-3.dat.md5 b/Tests/Module/ExternalData/SeriesD-3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesD-3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/Module/ExternalData/SeriesD.dat.md5 b/Tests/Module/ExternalData/SeriesD.dat.md5
new file mode 100644
index 0000000..be2d687
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesD.dat.md5
@@ -0,0 +1 @@
+f41c94425d01ecbbee70440b951cb058
diff --git a/Tests/Module/ExternalData/SeriesDn-1.dat.md5 b/Tests/Module/ExternalData/SeriesDn-1.dat.md5
new file mode 100644
index 0000000..f22e266
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesDn-1.dat.md5
@@ -0,0 +1 @@
+31eff09e84fca01415f8cd9d82ec432b
diff --git a/Tests/Module/ExternalData/SeriesDn-2.dat.md5 b/Tests/Module/ExternalData/SeriesDn-2.dat.md5
new file mode 100644
index 0000000..2b917e7
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesDn-2.dat.md5
@@ -0,0 +1 @@
+f7ab5a04aae9cb9a520e70b20b9c8ed7
diff --git a/Tests/Module/ExternalData/SeriesDn-3.dat.md5 b/Tests/Module/ExternalData/SeriesDn-3.dat.md5
new file mode 100644
index 0000000..b9c9760
--- /dev/null
+++ b/Tests/Module/ExternalData/SeriesDn-3.dat.md5
@@ -0,0 +1 @@
+30ba0acdee9096b3b9fc6c69362c6b42
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 35b9a43..e55cf69 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -46,6 +46,7 @@ macro(add_RunCMake_test test)
 endmacro()
 
 add_RunCMake_test(CMP0019)
+add_RunCMake_test(ExternalData)
 add_RunCMake_test(GeneratorExpression)
 add_RunCMake_test(TargetPropertyGeneratorExpressions)
 add_RunCMake_test(Languages)
diff --git a/Tests/RunCMake/ExternalData/BadHashAlgo1-result.txt b/Tests/RunCMake/ExternalData/BadHashAlgo1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadHashAlgo1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/BadHashAlgo1-stderr.txt b/Tests/RunCMake/ExternalData/BadHashAlgo1-stderr.txt
new file mode 100644
index 0000000..f68f0be
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadHashAlgo1-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Unknown hash algorithm specified by ExternalData_LINK_CONTENT:
+
+    BAD
+Call Stack \(most recent call first\):
+  .*
+  BadHashAlgo1.cmake:3 \(ExternalData_Expand_Arguments\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/BadHashAlgo1.cmake b/Tests/RunCMake/ExternalData/BadHashAlgo1.cmake
new file mode 100644
index 0000000..19e2e41
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadHashAlgo1.cmake
@@ -0,0 +1,3 @@
+include(ExternalData)
+set(ExternalData_LINK_CONTENT BAD)
+ExternalData_Expand_Arguments(Data args DATA{BadHashAlgo1.txt})
diff --git a/Tests/RunCMake/ExternalData/BadHashAlgo1.txt b/Tests/RunCMake/ExternalData/BadHashAlgo1.txt
new file mode 100644
index 0000000..bfa2818
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadHashAlgo1.txt
@@ -0,0 +1 @@
+Sample input file that should not be transformed.
diff --git a/Tests/RunCMake/ExternalData/BadOption1-result.txt b/Tests/RunCMake/ExternalData/BadOption1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadOption1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/BadOption1-stderr.txt b/Tests/RunCMake/ExternalData/BadOption1-stderr.txt
new file mode 100644
index 0000000..b63d098
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadOption1-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Unknown option "Bad/Option" in argument
+
+    DATA{Data.txt,Bad/Option}
+
+Call Stack \(most recent call first\):
+  .*
+  BadOption1.cmake:2 \(ExternalData_Add_Test\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/BadOption1.cmake b/Tests/RunCMake/ExternalData/BadOption1.cmake
new file mode 100644
index 0000000..1303d7f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadOption1.cmake
@@ -0,0 +1,5 @@
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{Data.txt,Bad/Option}
+  )
diff --git a/Tests/RunCMake/ExternalData/BadOption2-result.txt b/Tests/RunCMake/ExternalData/BadOption2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadOption2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/BadOption2-stderr.txt b/Tests/RunCMake/ExternalData/BadOption2-stderr.txt
new file mode 100644
index 0000000..d114c8a
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadOption2-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Unknown option "Bad:Option" in argument
+
+    DATA{Data.txt,Bad:Option}
+
+Call Stack \(most recent call first\):
+  .*
+  BadOption2.cmake:2 \(ExternalData_Add_Test\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/BadOption2.cmake b/Tests/RunCMake/ExternalData/BadOption2.cmake
new file mode 100644
index 0000000..6269b06
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadOption2.cmake
@@ -0,0 +1,5 @@
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{Data.txt,Bad:Option}
+  )
diff --git a/Tests/RunCMake/ExternalData/BadSeries1-result.txt b/Tests/RunCMake/ExternalData/BadSeries1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/BadSeries1-stderr.txt b/Tests/RunCMake/ExternalData/BadSeries1-stderr.txt
new file mode 100644
index 0000000..3099be5
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries1-stderr.txt
@@ -0,0 +1,19 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  ExternalData_SERIES_PARSE is set to
+
+    NotASeriesRegex
+
+  which is not of the form
+
+    \(<number>\)\(<suffix>\)\$
+
+  Fix the regular expression or set variables
+
+    ExternalData_SERIES_PARSE_PREFIX = <prefix> regex group number, if any
+    ExternalData_SERIES_PARSE_NUMBER = <number> regex group number
+    ExternalData_SERIES_PARSE_SUFFIX = <suffix> regex group number
+
+Call Stack \(most recent call first\):
+  .*
+  BadSeries1.cmake:3 \(ExternalData_Expand_Arguments\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/BadSeries1.cmake b/Tests/RunCMake/ExternalData/BadSeries1.cmake
new file mode 100644
index 0000000..7d71210
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries1.cmake
@@ -0,0 +1,3 @@
+include(ExternalData)
+set(ExternalData_SERIES_PARSE NotASeriesRegex)
+ExternalData_Expand_Arguments(Data args DATA{Data.txt,:})
diff --git a/Tests/RunCMake/ExternalData/BadSeries2-result.txt b/Tests/RunCMake/ExternalData/BadSeries2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/BadSeries2-stderr.txt b/Tests/RunCMake/ExternalData/BadSeries2-stderr.txt
new file mode 100644
index 0000000..3a02c25
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries2-stderr.txt
@@ -0,0 +1,16 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Data file referenced by argument
+
+    DATA{Data.txt,:}
+
+  corresponds to path
+
+    Data.txt
+
+  that does not match regular expression
+
+    \(x\)\(y\)\$
+Call Stack \(most recent call first\):
+  .*
+  BadSeries2.cmake:3 \(ExternalData_Expand_Arguments\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/BadSeries2.cmake b/Tests/RunCMake/ExternalData/BadSeries2.cmake
new file mode 100644
index 0000000..e81993b
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries2.cmake
@@ -0,0 +1,3 @@
+include(ExternalData)
+set(ExternalData_SERIES_PARSE "(x)(y)$")
+ExternalData_Expand_Arguments(Data args DATA{Data.txt,:})
diff --git a/Tests/RunCMake/ExternalData/BadSeries3-result.txt b/Tests/RunCMake/ExternalData/BadSeries3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/BadSeries3-stderr.txt b/Tests/RunCMake/ExternalData/BadSeries3-stderr.txt
new file mode 100644
index 0000000..594cb6f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries3-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Series option ":" not allowed with associated files.
+Call Stack \(most recent call first\):
+  .*
+  BadSeries3.cmake:2 \(ExternalData_Expand_Arguments\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/BadSeries3.cmake b/Tests/RunCMake/ExternalData/BadSeries3.cmake
new file mode 100644
index 0000000..b640df8
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadSeries3.cmake
@@ -0,0 +1,2 @@
+include(ExternalData)
+ExternalData_Expand_Arguments(Data args DATA{PairA.txt,PairB.txt,:})
diff --git a/Tests/RunCMake/ExternalData/CMakeLists.txt b/Tests/RunCMake/ExternalData/CMakeLists.txt
new file mode 100644
index 0000000..e8db6b0
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/ExternalData/Data.txt.md5 b/Tests/RunCMake/ExternalData/Data.txt.md5
new file mode 100644
index 0000000..93b3485
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Data.txt.md5
@@ -0,0 +1 @@
+e8bb14af900b998b5a3df7e21dd07d58
diff --git a/Tests/RunCMake/ExternalData/Directory1-result.txt b/Tests/RunCMake/ExternalData/Directory1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/Directory1-stderr.txt b/Tests/RunCMake/ExternalData/Directory1-stderr.txt
new file mode 100644
index 0000000..85c250f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory1-stderr.txt
@@ -0,0 +1,14 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Data file referenced by argument
+
+    DATA{Directory1}
+
+  corresponds to source tree path
+
+    Directory1
+
+  that does not exist as a file \(with or without an extension\)!
+Call Stack \(most recent call first\):
+  .*
+  Directory1.cmake:3 \(ExternalData_Add_Test\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/Directory1.cmake b/Tests/RunCMake/ExternalData/Directory1.cmake
new file mode 100644
index 0000000..68f1b54
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory1.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{Directory1}
+  )
diff --git a/Tests/RunCMake/ExternalData/Directory1/DirData1.txt b/Tests/RunCMake/ExternalData/Directory1/DirData1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/ExternalData/Directory2-result.txt b/Tests/RunCMake/ExternalData/Directory2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/Directory2-stderr.txt b/Tests/RunCMake/ExternalData/Directory2-stderr.txt
new file mode 100644
index 0000000..dc1a59a
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory2-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Data file reference in argument
+
+    DATA{Directory2/}
+
+  may not end in a slash!
+Call Stack \(most recent call first\):
+  .*
+  Directory2.cmake:3 \(ExternalData_Add_Test\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/Directory2.cmake b/Tests/RunCMake/ExternalData/Directory2.cmake
new file mode 100644
index 0000000..30b992e
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory2.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{Directory2/}
+  )
diff --git a/Tests/RunCMake/ExternalData/Directory2.md5 b/Tests/RunCMake/ExternalData/Directory2.md5
new file mode 100644
index 0000000..93b3485
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory2.md5
@@ -0,0 +1 @@
+e8bb14af900b998b5a3df7e21dd07d58
diff --git a/Tests/RunCMake/ExternalData/Directory2/DirData2.txt b/Tests/RunCMake/ExternalData/Directory2/DirData2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/ExternalData/Directory3-result.txt b/Tests/RunCMake/ExternalData/Directory3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/Directory3-stderr.txt b/Tests/RunCMake/ExternalData/Directory3-stderr.txt
new file mode 100644
index 0000000..56a341e
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory3-stderr.txt
@@ -0,0 +1,14 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Data file referenced by argument
+
+    DATA{Directory3/\*}
+
+  corresponds to source tree path
+
+    Directory3/.
+
+  that does not exist as a file \(with or without an extension\)!
+Call Stack \(most recent call first\):
+  .*
+  Directory3.cmake:3 \(ExternalData_Add_Test\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/Directory3.cmake b/Tests/RunCMake/ExternalData/Directory3.cmake
new file mode 100644
index 0000000..55d8be9
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/Directory3.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{Directory3/*}
+  )
diff --git a/Tests/RunCMake/ExternalData/Directory3/DirData3.txt b/Tests/RunCMake/ExternalData/Directory3/DirData3.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/ExternalData/LinkContentMD5-stdout.txt b/Tests/RunCMake/ExternalData/LinkContentMD5-stdout.txt
new file mode 100644
index 0000000..f77fca9
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/LinkContentMD5-stdout.txt
@@ -0,0 +1,3 @@
+-- Linked ToLink.txt.md5 to ExternalData MD5/c18ff9804c8deec9eaeb17063cda8b7b
+-- Raw data correctly transformed to content link!
+-- Staged content exists!
diff --git a/Tests/RunCMake/ExternalData/LinkContentMD5.cmake b/Tests/RunCMake/ExternalData/LinkContentMD5.cmake
new file mode 100644
index 0000000..41b4dee
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/LinkContentMD5.cmake
@@ -0,0 +1,22 @@
+include(ExternalData)
+set(ExternalData_LINK_CONTENT MD5)
+set(ExternalData_SOURCE_ROOT ${CMAKE_CURRENT_BINARY_DIR})
+set(ExternalData_BINARY_ROOT ${CMAKE_CURRENT_BINARY_DIR}/ExternalData)
+set(input ${CMAKE_CURRENT_BINARY_DIR}/ToLink.txt)
+set(output ${CMAKE_CURRENT_BINARY_DIR}/ExternalData/ToLink.txt)
+set(staged "${CMAKE_CURRENT_BINARY_DIR}/.ExternalData_MD5_c18ff9804c8deec9eaeb17063cda8b7b")
+file(REMOVE ${staged})
+file(REMOVE ${input}.md5)
+file(WRITE ${input} "To be transformed into a content link.")
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Raw data correctly transformed to content link!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
+if(EXISTS "${staged}")
+  message(STATUS "Staged content exists!")
+else()
+  message(FATAL_ERROR "Staged content missing!")
+endif()
diff --git a/Tests/RunCMake/ExternalData/MissingData-result.txt b/Tests/RunCMake/ExternalData/MissingData-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/MissingData-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/MissingData-stderr.txt b/Tests/RunCMake/ExternalData/MissingData-stderr.txt
new file mode 100644
index 0000000..e794f95
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/MissingData-stderr.txt
@@ -0,0 +1,14 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Data file referenced by argument
+
+    DATA{MissingData.txt}
+
+  corresponds to source tree path
+
+    MissingData.txt
+
+  that does not exist as a file \(with or without an extension\)!
+Call Stack \(most recent call first\):
+  .*
+  MissingData.cmake:2 \(ExternalData_Add_Test\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/MissingData.cmake b/Tests/RunCMake/ExternalData/MissingData.cmake
new file mode 100644
index 0000000..b3c8a5c
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/MissingData.cmake
@@ -0,0 +1,5 @@
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{MissingData.txt}
+  )
diff --git a/Tests/RunCMake/ExternalData/NoLinkInSource-stderr.txt b/Tests/RunCMake/ExternalData/NoLinkInSource-stderr.txt
new file mode 100644
index 0000000..496ad8a
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NoLinkInSource-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  ExternalData_LINK_CONTENT cannot be used in-source
+Call Stack \(most recent call first\):
+  .*
+  NoLinkInSource.cmake:8 \(ExternalData_Expand_Arguments\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/NoLinkInSource-stdout.txt b/Tests/RunCMake/ExternalData/NoLinkInSource-stdout.txt
new file mode 100644
index 0000000..18946f0
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NoLinkInSource-stdout.txt
@@ -0,0 +1 @@
+-- Data reference correctly not transformed!
diff --git a/Tests/RunCMake/ExternalData/NoLinkInSource.cmake b/Tests/RunCMake/ExternalData/NoLinkInSource.cmake
new file mode 100644
index 0000000..cbf45eb
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NoLinkInSource.cmake
@@ -0,0 +1,14 @@
+include(ExternalData)
+set(ExternalData_LINK_CONTENT MD5)
+set(ExternalData_SOURCE_ROOT ${CMAKE_CURRENT_BINARY_DIR})
+set(ExternalData_BINARY_ROOT ${CMAKE_CURRENT_BINARY_DIR})
+set(input ${CMAKE_CURRENT_BINARY_DIR}/ToLink.txt)
+file(REMOVE ${input}.md5)
+file(WRITE ${input} "To be transformed into a content link.")
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${input}")
+  message(STATUS "Data reference correctly not transformed!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected no transformation.")
+endif()
diff --git a/Tests/RunCMake/ExternalData/NoURLTemplates-result.txt b/Tests/RunCMake/ExternalData/NoURLTemplates-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NoURLTemplates-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/NoURLTemplates-stderr.txt b/Tests/RunCMake/ExternalData/NoURLTemplates-stderr.txt
new file mode 100644
index 0000000..ad059d4
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NoURLTemplates-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  ExternalData_URL_TEMPLATES is not set!
+Call Stack \(most recent call first\):
+  NoURLTemplates.cmake:2 \(ExternalData_Add_Target\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ExternalData/NoURLTemplates.cmake b/Tests/RunCMake/ExternalData/NoURLTemplates.cmake
new file mode 100644
index 0000000..8f0e069
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NoURLTemplates.cmake
@@ -0,0 +1,2 @@
+include(ExternalData)
+ExternalData_Add_Target(Data)
diff --git a/Tests/RunCMake/ExternalData/NormalData1-stdout.txt b/Tests/RunCMake/ExternalData/NormalData1-stdout.txt
new file mode 100644
index 0000000..2f2c770
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalData1-stdout.txt
@@ -0,0 +1 @@
+-- Data reference correctly transformed!
diff --git a/Tests/RunCMake/ExternalData/NormalData1.cmake b/Tests/RunCMake/ExternalData/NormalData1.cmake
new file mode 100644
index 0000000..d6cc384
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalData1.cmake
@@ -0,0 +1,13 @@
+include(ExternalData)
+set(ExternalData_URL_TEMPLATES
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/%(algo)/%(hash)"
+  )
+set(input Data.txt)
+set(output ${CMAKE_CURRENT_BINARY_DIR}/Data.txt)
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Data reference correctly transformed!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
diff --git a/Tests/RunCMake/ExternalData/NormalData2-stdout.txt b/Tests/RunCMake/ExternalData/NormalData2-stdout.txt
new file mode 100644
index 0000000..2f2c770
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalData2-stdout.txt
@@ -0,0 +1 @@
+-- Data reference correctly transformed!
diff --git a/Tests/RunCMake/ExternalData/NormalData2.cmake b/Tests/RunCMake/ExternalData/NormalData2.cmake
new file mode 100644
index 0000000..c979b48
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalData2.cmake
@@ -0,0 +1,14 @@
+include(ExternalData)
+set(ExternalData_URL_TEMPLATES
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/%(algo)/%(hash)"
+  )
+set(ExternalData_BINARY_ROOT ${CMAKE_CURRENT_BINARY_DIR}/ExternalData)
+set(input Data.txt)
+set(output ${CMAKE_CURRENT_BINARY_DIR}/ExternalData/Data.txt)
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Data reference correctly transformed!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
diff --git a/Tests/RunCMake/ExternalData/NormalData3-stdout.txt b/Tests/RunCMake/ExternalData/NormalData3-stdout.txt
new file mode 100644
index 0000000..2f2c770
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalData3-stdout.txt
@@ -0,0 +1 @@
+-- Data reference correctly transformed!
diff --git a/Tests/RunCMake/ExternalData/NormalData3.cmake b/Tests/RunCMake/ExternalData/NormalData3.cmake
new file mode 100644
index 0000000..e991122
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalData3.cmake
@@ -0,0 +1,14 @@
+include(ExternalData)
+set(ExternalData_URL_TEMPLATES
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/%(algo)/%(hash)"
+  )
+set(ExternalData_BINARY_ROOT ${CMAKE_CURRENT_BINARY_DIR}/ExternalData)
+set(input ${CMAKE_CURRENT_SOURCE_DIR}/Data.txt)
+set(output ${CMAKE_CURRENT_BINARY_DIR}/ExternalData/Data.txt)
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Data reference correctly transformed!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
diff --git a/Tests/RunCMake/ExternalData/NormalDataSub1-stdout.txt b/Tests/RunCMake/ExternalData/NormalDataSub1-stdout.txt
new file mode 100644
index 0000000..2f2c770
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalDataSub1-stdout.txt
@@ -0,0 +1 @@
+-- Data reference correctly transformed!
diff --git a/Tests/RunCMake/ExternalData/NormalDataSub1.cmake b/Tests/RunCMake/ExternalData/NormalDataSub1.cmake
new file mode 100644
index 0000000..015e94c
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NormalDataSub1.cmake
@@ -0,0 +1,13 @@
+include(ExternalData)
+set(ExternalData_URL_TEMPLATES
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/%(algo)/%(hash)"
+  )
+set(input SubDirectory1/Data.txt)
+set(output ${CMAKE_CURRENT_BINARY_DIR}/SubDirectory1/Data.txt)
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Data reference correctly transformed!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
diff --git a/Tests/RunCMake/ExternalData/NotUnderRoot-result.txt b/Tests/RunCMake/ExternalData/NotUnderRoot-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NotUnderRoot-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ExternalData/NotUnderRoot-stderr.txt b/Tests/RunCMake/ExternalData/NotUnderRoot-stderr.txt
new file mode 100644
index 0000000..1f2eb1c
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NotUnderRoot-stderr.txt
@@ -0,0 +1,12 @@
+CMake Error at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+  Data file referenced by argument
+
+    DATA{../NotUnderRoot.txt}
+
+  does not lie under the top-level source directory
+
+    .*/Tests/RunCMake/ExternalData
+
+Call Stack \(most recent call first\):
+  .*
+  NotUnderRoot.cmake:2 \(ExternalData_Add_Test\)
diff --git a/Tests/RunCMake/ExternalData/NotUnderRoot.cmake b/Tests/RunCMake/ExternalData/NotUnderRoot.cmake
new file mode 100644
index 0000000..c7942d6
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/NotUnderRoot.cmake
@@ -0,0 +1,5 @@
+include(ExternalData)
+ExternalData_Add_Test(Data
+  NAME Test
+  COMMAND ${CMAKE_COMMAND} -E echo DATA{../NotUnderRoot.txt}
+  )
diff --git a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
new file mode 100644
index 0000000..c61527e
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
@@ -0,0 +1,21 @@
+include(RunCMake)
+
+run_cmake(BadHashAlgo1)
+run_cmake(BadOption1)
+run_cmake(BadOption2)
+run_cmake(BadSeries1)
+run_cmake(BadSeries2)
+run_cmake(BadSeries3)
+run_cmake(Directory1)
+run_cmake(Directory2)
+run_cmake(Directory3)
+run_cmake(LinkContentMD5)
+run_cmake(MissingData)
+run_cmake(NoLinkInSource)
+run_cmake(NoURLTemplates)
+run_cmake(NormalData1)
+run_cmake(NormalData2)
+run_cmake(NormalData3)
+run_cmake(NormalDataSub1)
+run_cmake(NotUnderRoot)
+run_cmake(SubDirectory1)
diff --git a/Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt b/Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt
new file mode 100644
index 0000000..35a8cc1
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt
@@ -0,0 +1,2 @@
+-- Data reference correctly transformed in parent dir!
+-- Data reference correctly transformed in current dir!
diff --git a/Tests/RunCMake/ExternalData/SubDirectory1.cmake b/Tests/RunCMake/ExternalData/SubDirectory1.cmake
new file mode 100644
index 0000000..2989471
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/SubDirectory1.cmake
@@ -0,0 +1,5 @@
+include(ExternalData)
+set(ExternalData_URL_TEMPLATES
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/%(algo)/%(hash)"
+  )
+add_subdirectory(SubDirectory1)
diff --git a/Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt b/Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt
new file mode 100644
index 0000000..0782460
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(input ../Data.txt)
+set(output ${CMAKE_BINARY_DIR}/Data.txt)
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Data reference correctly transformed in parent dir!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
+
+set(input Data.txt)
+set(output ${CMAKE_CURRENT_BINARY_DIR}/Data.txt)
+ExternalData_Expand_Arguments(Data args DATA{${input}})
+if("x${args}" STREQUAL "x${output}")
+  message(STATUS "Data reference correctly transformed in current dir!")
+else()
+  message(FATAL_ERROR "Data reference transformed to:\n  ${args}\n"
+    "but we expected:\n  ${output}")
+endif()
diff --git a/Tests/RunCMake/ExternalData/SubDirectory1/Data.txt.md5 b/Tests/RunCMake/ExternalData/SubDirectory1/Data.txt.md5
new file mode 100644
index 0000000..93b3485
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/SubDirectory1/Data.txt.md5
@@ -0,0 +1 @@
+e8bb14af900b998b5a3df7e21dd07d58

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bcd25808ac540d279a36a9e0f1b60f152fc0d6bb
commit bcd25808ac540d279a36a9e0f1b60f152fc0d6bb
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jan 25 16:30:30 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Jan 29 15:23:00 2013 -0500

    ExternalData: Improve series matching using an explicit syntax
    
    Automatic series recognition can generate false positives too easily
    when the default series configuration is flexible enough to handle
    common cases.  Avoid false positives by requiring an explicit syntax to
    activate series recognition.  Choose the syntax DATA{<name>,:} to be
    short, simple, and look like a vertical ellipsis.
    
    This allows us to improve the default series match configuration.  Allow
    series references to contain one of the numbered file names.  Allow '-'
    as a separator in addition to '.' and '_'.  Document what the default
    configuration matches.  Also provide more options to configure series
    <name> parsing.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index d678cf2..0ef514c 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -66,18 +66,26 @@
 # the source tree contains a content link such as "MyInput.png.md5" then the
 # "MyData" target creates a real "MyInput.png" in the build tree.
 #
-# The DATA{} syntax can automatically recognize and fetch a file series.  If
-# the source tree contains a group of files or content links named like a
-# series then a DATA{} reference to one member adds rules to fetch all of
-# them.  Although all members of a series are fetched, only the file
-# originally named by the DATA{} argument is substituted for it.  Two
-# variables configure recognition of a series from DATA{<name>}.  First,
-# ExternalData_SERIES_PARSE is a regex of the form "^(...)(...)(...)$" to
-# parse <prefix>, <number>, and <suffix> parts from <name>.  Second,
-# ExternalData_SERIES_MATCH is a regex matching the <number> part of series
-# members named <prefix><number><suffix>.  Note that the <suffix> of a series
-# does not include a hash-algorithm extension.  Both series configuration
-# variables have default values that work well for common cases.
+# The DATA{} syntax can be told to fetch a file series using the form
+# "DATA{<name>,:}", where the ":" is literal.  If the source tree contains a
+# group of files or content links named like a series then a reference to one
+# member adds rules to fetch all of them.  Although all members of a series
+# are fetched, only the file originally named by the DATA{} argument is
+# substituted for it.  The default configuration recognizes file series names
+# ending with "#.ext", "_#.ext", ".#.ext", or "-#.ext" where "#" is a sequence
+# of decimal digits and ".ext" is any single extension.  Configure it with a
+# regex that parses <number> and <suffix> parts from the end of <name>:
+#  ExternalData_SERIES_PARSE = regex of the form (<number>)(<suffix>)$
+# For more complicated cases set:
+#  ExternalData_SERIES_PARSE = regex with at least two () groups
+#  ExternalData_SERIES_PARSE_PREFIX = <prefix> regex group number, if any
+#  ExternalData_SERIES_PARSE_NUMBER = <number> regex group number
+#  ExternalData_SERIES_PARSE_SUFFIX = <suffix> regex group number
+# Configure series number matching with a regex that matches the
+# <number> part of series members named <prefix><number><suffix>:
+#  ExternalData_SERIES_MATCH = regex matching <number> in all series members
+# Note that the <suffix> of a series does not include a hash-algorithm
+# extension.
 #
 # The DATA{} syntax can alternatively match files associated with the named
 # file and contained in the same directory.  Associated files may be specified
@@ -349,6 +357,7 @@ function(_ExternalData_arg target arg options var_file)
   set(have_original 0)
 
   # Process options.
+  set(series_option "")
   set(associated_files "")
   set(associated_regex "")
   foreach(opt ${options})
@@ -356,6 +365,9 @@ function(_ExternalData_arg target arg options var_file)
       # Regular expression to match associated files.
       string(REGEX REPLACE "^REGEX:" "" regex "${opt}")
       list(APPEND associated_regex "${regex}")
+    elseif("x${opt}" MATCHES "^x:$")
+      # Activate series matching.
+      set(series_option "${opt}")
     elseif("x${opt}" MATCHES "^[^][:/*?]+$")
       # Specific associated file.
       list(APPEND associated_files "${opt}")
@@ -365,16 +377,19 @@ function(_ExternalData_arg target arg options var_file)
     endif()
   endforeach()
 
-  if(associated_files OR associated_regex)
-    # Load the named data file and listed/matching associated files.
-    _ExternalData_arg_single()
-    _ExternalData_arg_associated()
-  elseif("${reldata}" MATCHES "(^|/)[^/.]+$")
-    # Files with no extension cannot be a series.
-    _ExternalData_arg_single()
-  else()
-    # Match a whole file series by default.
+  if(series_option)
+    if(associated_files OR associated_regex)
+      message(FATAL_ERROR "Series option \"${series_option}\" not allowed with associated files.")
+    endif()
+    # Load a whole file series.
     _ExternalData_arg_series()
+  else()
+    # Load the named data file.
+    _ExternalData_arg_single()
+    if(associated_files OR associated_regex)
+      # Load listed/matching associated files.
+      _ExternalData_arg_associated()
+    endif()
   endif()
 
   if(NOT have_original)
@@ -430,27 +445,40 @@ endmacro()
 
 macro(_ExternalData_arg_series)
   # Configure series parsing and matching.
+  set(series_parse_prefix "")
+  set(series_parse_number "\\1")
+  set(series_parse_suffix "\\2")
   if(ExternalData_SERIES_PARSE)
-    if(NOT "${ExternalData_SERIES_PARSE}" MATCHES
-        "^\\^\\([^()]*\\)\\([^()]*\\)\\([^()]*\\)\\$$")
+    if(ExternalData_SERIES_PARSE_NUMBER AND ExternalData_SERIES_PARSE_SUFFIX)
+      if(ExternalData_SERIES_PARSE_PREFIX)
+        set(series_parse_prefix "\\${ExternalData_SERIES_PARSE_PREFIX}")
+      endif()
+      set(series_parse_number "\\${ExternalData_SERIES_PARSE_NUMBER}")
+      set(series_parse_suffix "\\${ExternalData_SERIES_PARSE_SUFFIX}")
+    elseif(NOT "x${ExternalData_SERIES_PARSE}" MATCHES "^x\\([^()]*\\)\\([^()]*\\)\\$$")
       message(FATAL_ERROR
         "ExternalData_SERIES_PARSE is set to\n"
         "  ${ExternalData_SERIES_PARSE}\n"
         "which is not of the form\n"
-        "  ^(...)(...)(...)$\n")
+        "  (<number>)(<suffix>)$\n"
+        "Fix the regular expression or set variables\n"
+        "  ExternalData_SERIES_PARSE_PREFIX = <prefix> regex group number, if any\n"
+        "  ExternalData_SERIES_PARSE_NUMBER = <number> regex group number\n"
+        "  ExternalData_SERIES_PARSE_SUFFIX = <suffix> regex group number\n"
+        )
     endif()
     set(series_parse "${ExternalData_SERIES_PARSE}")
   else()
-    set(series_parse "^(.*)()(\\.[^./]*)$")
+    set(series_parse "([0-9]*)(\\.[^./]*)$")
   endif()
   if(ExternalData_SERIES_MATCH)
     set(series_match "${ExternalData_SERIES_MATCH}")
   else()
-    set(series_match "[_.]?[0-9]*")
+    set(series_match "[_.-]?[0-9]*")
   endif()
 
   # Parse the base, number, and extension components of the series.
-  string(REGEX REPLACE "${series_parse}" "\\1;\\2;\\3" tuple "${reldata}")
+  string(REGEX REPLACE "${series_parse}" "${series_parse_prefix};${series_parse_number};${series_parse_suffix}" tuple "${reldata}")
   list(LENGTH tuple len)
   if(NOT "${len}" EQUAL 3)
     message(FATAL_ERROR "Data file referenced by argument\n"

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c0cebcb19ae53773f6b21035813c6d58dd829b94
commit c0cebcb19ae53773f6b21035813c6d58dd829b94
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 24 14:06:17 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Jan 28 15:31:31 2013 -0500

    ExternalData: Remove unused private interface
    
    The 'store' action was part of an older design and is no longer needed.
    Remove it.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 0800bb3..d678cf2 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -690,16 +690,6 @@ elseif("${ExternalData_ACTION}" STREQUAL "local")
     endif()
   endforeach()
   _ExternalData_link_or_copy("${name}" "${file}")
-elseif("${ExternalData_ACTION}" STREQUAL "store")
-  foreach(v dir file)
-    if(NOT DEFINED "${v}")
-      message(FATAL_ERROR "No \"-D${v}=\" value provided!")
-    endif()
-  endforeach()
-  if(NOT DEFINED algo)
-    set(algo "MD5")
-  endif()
-  _ExternalData_compute_hash(hash "${algo}" "${file}")
 else()
   message(FATAL_ERROR "Unknown ExternalData_ACTION=[${ExternalData_ACTION}]")
 endif()

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=52759930bd7a5e1642b16cdc2bde3d23aaaddd2c
commit 52759930bd7a5e1642b16cdc2bde3d23aaaddd2c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 24 13:37:54 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Jan 28 15:31:31 2013 -0500

    ExternalData: Cleanup stray TODO and typo in comments
    
    Remove an outdated TODO line left from earlier designs.
    Also fix a typo.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 29ddffd..0800bb3 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -315,7 +315,6 @@ function(_ExternalData_arg target arg options var_file)
   if(IS_ABSOLUTE "${data}")
     set(absdata "${data}")
   else()
-    # TODO: If ${data} does not start in "./" or "../" then use search path?
     get_filename_component(absdata "${CMAKE_CURRENT_SOURCE_DIR}/${data}" ABSOLUTE)
   endif()
 
@@ -465,7 +464,7 @@ macro(_ExternalData_arg_series)
   list(GET tuple 2 ext)
 
   # Glob files that might match the series.
-  # Then match match base, number, and extension.
+  # Then match base, number, and extension.
   _ExternalData_exact_regex(series_base "${relbase}")
   _ExternalData_exact_regex(series_ext "${ext}")
   _ExternalData_arg_find_files("${relbase}*${ext}"

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7bb8344d50fa317580068dedd00b019be8a6cb98
commit 7bb8344d50fa317580068dedd00b019be8a6cb98
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 24 13:35:30 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Jan 28 15:31:02 2013 -0500

    ExternalData: Do not match directory names when resolving DATA{}
    
    Our content link and object download infrastructure supports only
    blobs (files), not trees (directories).  Do not allow references
    to end in a slash.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 4ab2186..29ddffd 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -304,6 +304,13 @@ function(_ExternalData_arg target arg options var_file)
   list(GET options 0 data)
   list(REMOVE_AT options 0)
 
+  # Reject trailing slashes.
+  if("x${data}" MATCHES "[/\\]$")
+    message(FATAL_ERROR "Data file reference in argument\n"
+      "  ${arg}\n"
+      "may not end in a slash!")
+  endif()
+
   # Convert to full path.
   if(IS_ABSOLUTE "${data}")
     set(absdata "${data}")
@@ -376,7 +383,7 @@ function(_ExternalData_arg target arg options var_file)
       "  ${arg}\n"
       "corresponds to source tree path\n"
       "  ${reldata}\n"
-      "that does not exist (with or without an extension)!")
+      "that does not exist as a file (with or without an extension)!")
   endif()
 
   if(external)
@@ -470,7 +477,7 @@ function(_ExternalData_arg_find_files pattern regex)
   foreach(entry IN LISTS globbed)
     string(REGEX REPLACE "^(${regex})(\\.md5|)$" "\\1;\\2" tuple "${entry}")
     list(LENGTH tuple len)
-    if("${len}" EQUAL 2)
+    if("${len}" EQUAL 2 AND NOT IS_DIRECTORY "${top_src}/${entry}")
       list(GET tuple 0 relname)
       list(GET tuple 1 alg)
       set(name "${top_src}/${relname}")

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=00d801fbfe9c5170e3a83019cc2e3f6b1ce64200
commit 00d801fbfe9c5170e3a83019cc2e3f6b1ce64200
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 24 13:34:12 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jan 24 13:34:12 2013 -0500

    ExternalData: Remove compatibility with CMake < 2.8.5
    
    Now that the module comes in a sufficiently new CMake it does not need
    to support older versions.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 84020f9..4ab2186 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -119,8 +119,7 @@
 # Variables ExternalData_TIMEOUT_INACTIVITY and ExternalData_TIMEOUT_ABSOLUTE
 # set the download inactivity and absolute timeouts, in seconds.  The defaults
 # are 60 seconds and 300 seconds, respectively.  Set either timeout to 0
-# seconds to disable enforcement.  The inactivity timeout is enforced only
-# with CMake >= 2.8.5.
+# seconds to disable enforcement.
 
 #=============================================================================
 # Copyright 2010-2013 Kitware, Inc.
@@ -263,13 +262,7 @@ function(_ExternalData_compute_hash var_hash algo file)
 endfunction()
 
 function(_ExternalData_random var)
-  if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.5)
-    string(RANDOM LENGTH 6 random)
-  elseif(EXISTS /dev/urandom)
-    file(READ /dev/urandom random LIMIT 4 HEX)
-  else()
-    message(FATAL_ERROR "CMake >= 2.8.5 required in this environment")
-  endif()
+  string(RANDOM LENGTH 6 random)
   set("${var}" "${random}" PARENT_SCOPE)
 endfunction()
 
@@ -550,14 +543,10 @@ function(_ExternalData_download_file url file err_var msg_var)
   set(retry 3)
   while(retry)
     math(EXPR retry "${retry} - 1")
-    if("${CMAKE_VERSION}" VERSION_GREATER 2.8.4.20110602)
-      if(ExternalData_TIMEOUT_INACTIVITY)
-        set(inactivity_timeout INACTIVITY_TIMEOUT ${ExternalData_TIMEOUT_INACTIVITY})
-      elseif(NOT "${ExternalData_TIMEOUT_INACTIVITY}" EQUAL 0)
-        set(inactivity_timeout INACTIVITY_TIMEOUT 60)
-      else()
-        set(inactivity_timeout "")
-      endif()
+    if(ExternalData_TIMEOUT_INACTIVITY)
+      set(inactivity_timeout INACTIVITY_TIMEOUT ${ExternalData_TIMEOUT_INACTIVITY})
+    elseif(NOT "${ExternalData_TIMEOUT_INACTIVITY}" EQUAL 0)
+      set(inactivity_timeout INACTIVITY_TIMEOUT 60)
     else()
       set(inactivity_timeout "")
     endif()

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ab26249db107146fc9ad624ac9dddc4052e798d6
commit ab26249db107146fc9ad624ac9dddc4052e798d6
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 24 13:29:48 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jan 24 13:32:17 2013 -0500

    Add ExternalData module
    
    Take files we previously distributed in ITK 4.3.1:
    
      CMake/ExternalData.cmake
      CMake/ExternalData_config.cmake.in
    
    and add them for distribution in upstream CMake.  Update the copyright
    notice block format to follow CMake conventions.

diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
new file mode 100644
index 0000000..84020f9
--- /dev/null
+++ b/Modules/ExternalData.cmake
@@ -0,0 +1,710 @@
+# - Manage data files stored outside source tree
+# Use this module to unambiguously reference data files stored outside the
+# source tree and fetch them at build time from arbitrary local and remote
+# content-addressed locations.  Functions provided by this module recognize
+# arguments with the syntax "DATA{<name>}" as references to external data,
+# replace them with full paths to local copies of those data, and create build
+# rules to fetch and update the local copies.
+#
+# The DATA{} syntax is literal and the <name> is a full or relative path
+# within the source tree.  The source tree must contain either a real data
+# file at <name> or a "content link" at <name><ext> containing a hash of the
+# real file using a hash algorithm corresponding to <ext>.  For example, the
+# argument "DATA{img.png}" may be satisfied by either a real "img.png" file in
+# the current source directory or a "img.png.md5" file containing its MD5 sum.
+#
+# The 'ExternalData_Expand_Arguments' function evaluates DATA{} references
+# in its arguments and constructs a new list of arguments:
+#  ExternalData_Expand_Arguments(
+#    <target>   # Name of data management target
+#    <outVar>   # Output variable
+#    [args...]  # Input arguments, DATA{} allowed
+#    )
+# It replaces each DATA{} reference in an argument with the full path of a
+# real data file on disk that will exist after the <target> builds.
+#
+# The 'ExternalData_Add_Test' function wraps around the CMake add_test()
+# command but supports DATA{} references in its arguments:
+#  ExternalData_Add_Test(
+#    <target>   # Name of data management target
+#    ...        # Arguments of add_test(), DATA{} allowed
+#    )
+# It passes its arguments through ExternalData_Expand_Arguments and then
+# invokes add_test() using the results.
+#
+# The 'ExternalData_Add_Target' function creates a custom target to manage
+# local instances of data files stored externally:
+#  ExternalData_Add_Target(
+#    <target>   # Name of data management target
+#    )
+# It creates custom commands in the target as necessary to make data files
+# available for each DATA{} reference previously evaluated by other functions
+# provided by this module.  A list of URL templates must be provided in the
+# variable ExternalData_URL_TEMPLATES using the placeholders "%(algo)" and
+# "%(hash)" in each template.  Data fetch rules try each URL template in order
+# by substituting the hash algorithm name for "%(algo)" and the hash value for
+# "%(hash)".
+#
+# The following hash algorithms are supported:
+#    %(algo)     <ext>     Description
+#    -------     -----     -----------
+#    MD5         .md5      Message-Digest Algorithm 5, RFC 1321
+# Note that the hashes are used only for unique data identification and
+# download verification.  This is not security software.
+#
+# Example usage:
+#   include(ExternalData)
+#   set(ExternalData_URL_TEMPLATES "file:///local/%(algo)/%(hash)"
+#                                  "http://data.org/%(algo)/%(hash)")
+#   ExternalData_Add_Test(MyData
+#     NAME MyTest
+#     COMMAND MyExe DATA{MyInput.png}
+#     )
+#   ExternalData_Add_Target(MyData)
+# When test "MyTest" runs the "DATA{MyInput.png}" argument will be replaced by
+# the full path to a real instance of the data file "MyInput.png" on disk.  If
+# the source tree contains a content link such as "MyInput.png.md5" then the
+# "MyData" target creates a real "MyInput.png" in the build tree.
+#
+# The DATA{} syntax can automatically recognize and fetch a file series.  If
+# the source tree contains a group of files or content links named like a
+# series then a DATA{} reference to one member adds rules to fetch all of
+# them.  Although all members of a series are fetched, only the file
+# originally named by the DATA{} argument is substituted for it.  Two
+# variables configure recognition of a series from DATA{<name>}.  First,
+# ExternalData_SERIES_PARSE is a regex of the form "^(...)(...)(...)$" to
+# parse <prefix>, <number>, and <suffix> parts from <name>.  Second,
+# ExternalData_SERIES_MATCH is a regex matching the <number> part of series
+# members named <prefix><number><suffix>.  Note that the <suffix> of a series
+# does not include a hash-algorithm extension.  Both series configuration
+# variables have default values that work well for common cases.
+#
+# The DATA{} syntax can alternatively match files associated with the named
+# file and contained in the same directory.  Associated files may be specified
+# by options using the syntax DATA{<name>,<opt1>,<opt2>,...}.  Each option may
+# specify one file by name or specify a regular expression to match file names
+# using the syntax REGEX:<regex>.  For example, the arguments
+#   DATA{MyData/MyInput.mhd,MyInput.img}                   # File pair
+#   DATA{MyData/MyFrames00.png,REGEX:MyFrames[0-9]+\\.png} # Series
+# will pass MyInput.mha and MyFrames00.png on the command line but ensure
+# that the associated files are present next to them.
+#
+# The variable ExternalData_LINK_CONTENT may be set to the name of a supported
+# hash algorithm to enable automatic conversion of real data files referenced
+# by the DATA{} syntax into content links.  For each such <file> a content
+# link named "<file><ext>" is created.  The original file is renamed to the
+# form ".ExternalData_<algo>_<hash>" to stage it for future transmission to
+# one of the locations in the list of URL templates (by means outside the
+# scope of this module).  The data fetch rule created for the content link
+# will use the staged object if it cannot be found using any URL template.
+#
+# The variable ExternalData_OBJECT_STORES may be set to a list of local
+# directories that store objects using the layout <dir>/%(algo)/%(hash).
+# These directories will be searched first for a needed object.  If the object
+# is not available in any store then it will be fetched remotely using the URL
+# templates and added to the first local store listed.  If no stores are
+# specified the default is a location inside the build tree.
+#
+# The variable ExternalData_SOURCE_ROOT may be set to the highest source
+# directory containing any path named by a DATA{} reference.  The default is
+# CMAKE_SOURCE_DIR.  ExternalData_SOURCE_ROOT and CMAKE_SOURCE_DIR must refer
+# to directories within a single source distribution (e.g. they come together
+# in one tarball).
+#
+# The variable ExternalData_BINARY_ROOT may be set to the directory to hold
+# the real data files named by expanded DATA{} references.  The default is
+# CMAKE_BINARY_DIR.  The directory layout will mirror that of content links
+# under ExternalData_SOURCE_ROOT.
+#
+# Variables ExternalData_TIMEOUT_INACTIVITY and ExternalData_TIMEOUT_ABSOLUTE
+# set the download inactivity and absolute timeouts, in seconds.  The defaults
+# are 60 seconds and 300 seconds, respectively.  Set either timeout to 0
+# seconds to disable enforcement.  The inactivity timeout is enforced only
+# with CMake >= 2.8.5.
+
+#=============================================================================
+# Copyright 2010-2013 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+function(ExternalData_add_test target)
+  ExternalData_expand_arguments("${target}" testArgs ${ARGN})
+  add_test(${testArgs})
+endfunction()
+
+function(ExternalData_add_target target)
+  if(NOT ExternalData_URL_TEMPLATES)
+    message(FATAL_ERROR "ExternalData_URL_TEMPLATES is not set!")
+  endif()
+  if(NOT ExternalData_OBJECT_STORES)
+    set(ExternalData_OBJECT_STORES ${CMAKE_BINARY_DIR}/ExternalData/Objects)
+  endif()
+  set(config ${CMAKE_CURRENT_BINARY_DIR}/${target}_config.cmake)
+  configure_file(${_ExternalData_SELF_DIR}/ExternalData_config.cmake.in ${config} @ONLY)
+
+  set(files "")
+
+  # Set "_ExternalData_FILE_${file}" for each output file to avoid duplicate
+  # rules.  Use local data first to prefer real files over content links.
+
+  # Custom commands to copy or link local data.
+  get_property(data_local GLOBAL PROPERTY _ExternalData_${target}_LOCAL)
+  foreach(entry IN LISTS data_local)
+    string(REPLACE "|" ";" tuple "${entry}")
+    list(GET tuple 0 file)
+    list(GET tuple 1 name)
+    if(NOT DEFINED "_ExternalData_FILE_${file}")
+      set("_ExternalData_FILE_${file}" 1)
+      add_custom_command(
+        COMMENT "Generating ${file}"
+        OUTPUT "${file}"
+        COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR}
+                                 -Dfile=${file} -Dname=${name}
+                                 -DExternalData_ACTION=local
+                                 -DExternalData_CONFIG=${config}
+                                 -P ${_ExternalData_SELF}
+        DEPENDS "${name}"
+        )
+      list(APPEND files "${file}")
+    endif()
+  endforeach()
+
+  # Custom commands to fetch remote data.
+  get_property(data_fetch GLOBAL PROPERTY _ExternalData_${target}_FETCH)
+  foreach(entry IN LISTS data_fetch)
+    string(REPLACE "|" ";" tuple "${entry}")
+    list(GET tuple 0 file)
+    list(GET tuple 1 name)
+    list(GET tuple 2 ext)
+    set(stamp "${ext}-stamp")
+    if(NOT DEFINED "_ExternalData_FILE_${file}")
+      set("_ExternalData_FILE_${file}" 1)
+      add_custom_command(
+        # Users care about the data file, so hide the hash/timestamp file.
+        COMMENT "Generating ${file}"
+        # The hash/timestamp file is the output from the build perspective.
+        # List the real file as a second output in case it is a broken link.
+        # The files must be listed in this order so CMake can hide from the
+        # make tool that a symlink target may not be newer than the input.
+        OUTPUT "${file}${stamp}" "${file}"
+        # Run the data fetch/update script.
+        COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR}
+                                 -Dfile=${file} -Dname=${name} -Dext=${ext}
+                                 -DExternalData_ACTION=fetch
+                                 -DExternalData_CONFIG=${config}
+                                 -P ${_ExternalData_SELF}
+        # Update whenever the object hash changes.
+        DEPENDS "${name}${ext}"
+        )
+      list(APPEND files "${file}${stamp}")
+    endif()
+  endforeach()
+
+  # Custom target to drive all update commands.
+  add_custom_target(${target} ALL DEPENDS ${files})
+endfunction()
+
+function(ExternalData_expand_arguments target outArgsVar)
+  # Replace DATA{} references with real arguments.
+  set(data_regex "DATA{([^{}\r\n]*)}")
+  set(other_regex "([^D]|D[^A]|DA[^T]|DAT[^A]|DATA[^{])+|.")
+  set(outArgs "")
+  foreach(arg IN LISTS ARGN)
+    if("x${arg}" MATCHES "${data_regex}")
+      # Split argument into DATA{}-pieces and other pieces.
+      string(REGEX MATCHALL "${data_regex}|${other_regex}" pieces "${arg}")
+      # Compose output argument with DATA{}-pieces replaced.
+      set(outArg "")
+      foreach(piece IN LISTS pieces)
+        if("x${piece}" MATCHES "^x${data_regex}$")
+          # Replace this DATA{}-piece with a file path.
+          string(REGEX REPLACE "${data_regex}" "\\1" data "${piece}")
+          _ExternalData_arg("${target}" "${piece}" "${data}" file)
+          set(outArg "${outArg}${file}")
+        else()
+          # No replacement needed for this piece.
+          set(outArg "${outArg}${piece}")
+        endif()
+      endforeach()
+      list(APPEND outArgs "${outArg}")
+    else()
+      # No replacements needed in this argument.
+      list(APPEND outArgs "${arg}")
+    endif()
+  endforeach()
+  set("${outArgsVar}" "${outArgs}" PARENT_SCOPE)
+endfunction()
+
+#-----------------------------------------------------------------------------
+# Private helper interface
+
+set(_ExternalData_SELF "${CMAKE_CURRENT_LIST_FILE}")
+get_filename_component(_ExternalData_SELF_DIR "${_ExternalData_SELF}" PATH)
+
+function(_ExternalData_compute_hash var_hash algo file)
+  if("${algo}" STREQUAL "MD5")
+    # TODO: Errors
+    execute_process(COMMAND "${CMAKE_COMMAND}" -E md5sum "${file}"
+      OUTPUT_VARIABLE output)
+    string(SUBSTRING "${output}" 0 32 hash)
+    set("${var_hash}" "${hash}" PARENT_SCOPE)
+  else()
+    # TODO: Other hashes.
+    message(FATAL_ERROR "Hash algorithm ${algo} unimplemented.")
+  endif()
+endfunction()
+
+function(_ExternalData_random var)
+  if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.5)
+    string(RANDOM LENGTH 6 random)
+  elseif(EXISTS /dev/urandom)
+    file(READ /dev/urandom random LIMIT 4 HEX)
+  else()
+    message(FATAL_ERROR "CMake >= 2.8.5 required in this environment")
+  endif()
+  set("${var}" "${random}" PARENT_SCOPE)
+endfunction()
+
+function(_ExternalData_exact_regex regex_var string)
+  string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" regex "${string}")
+  set("${regex_var}" "${regex}" PARENT_SCOPE)
+endfunction()
+
+function(_ExternalData_atomic_write file content)
+  _ExternalData_random(random)
+  set(tmp "${file}.tmp${random}")
+  file(WRITE "${tmp}" "${content}")
+  file(RENAME "${tmp}" "${file}")
+endfunction()
+
+function(_ExternalData_link_content name var_ext)
+  if("${ExternalData_LINK_CONTENT}" MATCHES "^(MD5)$")
+    set(algo "${ExternalData_LINK_CONTENT}")
+  else()
+    message(FATAL_ERROR
+      "Unknown hash algorithm specified by ExternalData_LINK_CONTENT:\n"
+      "  ${ExternalData_LINK_CONTENT}")
+  endif()
+  _ExternalData_compute_hash(hash "${algo}" "${name}")
+  get_filename_component(dir "${name}" PATH)
+  set(staged "${dir}/.ExternalData_${algo}_${hash}")
+  set(ext ".md5")
+  _ExternalData_atomic_write("${name}${ext}" "${hash}\n")
+  file(RENAME "${name}" "${staged}")
+  set("${var_ext}" "${ext}" PARENT_SCOPE)
+
+  file(RELATIVE_PATH relname "${ExternalData_SOURCE_ROOT}" "${name}${ext}")
+  message(STATUS "Linked ${relname} to ExternalData ${algo}/${hash}")
+endfunction()
+
+function(_ExternalData_arg target arg options var_file)
+  # Separate data path from the options.
+  string(REPLACE "," ";" options "${options}")
+  list(GET options 0 data)
+  list(REMOVE_AT options 0)
+
+  # Convert to full path.
+  if(IS_ABSOLUTE "${data}")
+    set(absdata "${data}")
+  else()
+    # TODO: If ${data} does not start in "./" or "../" then use search path?
+    get_filename_component(absdata "${CMAKE_CURRENT_SOURCE_DIR}/${data}" ABSOLUTE)
+  endif()
+
+  # Convert to relative path under the source tree.
+  if(NOT ExternalData_SOURCE_ROOT)
+    set(ExternalData_SOURCE_ROOT "${CMAKE_SOURCE_DIR}")
+  endif()
+  set(top_src "${ExternalData_SOURCE_ROOT}")
+  file(RELATIVE_PATH reldata "${top_src}" "${absdata}")
+  if(IS_ABSOLUTE "${reldata}" OR "${reldata}" MATCHES "^\\.\\./")
+    message(FATAL_ERROR "Data file referenced by argument\n"
+      "  ${arg}\n"
+      "does not lie under the top-level source directory\n"
+      "  ${top_src}\n")
+  endif()
+  if(NOT ExternalData_BINARY_ROOT)
+    set(ExternalData_BINARY_ROOT "${CMAKE_BINARY_DIR}")
+  endif()
+  set(top_bin "${ExternalData_BINARY_ROOT}")
+
+  # Handle in-source builds gracefully.
+  if("${top_src}" STREQUAL "${top_bin}")
+    if(ExternalData_LINK_CONTENT)
+      message(WARNING "ExternalData_LINK_CONTENT cannot be used in-source")
+      set(ExternalData_LINK_CONTENT 0)
+    endif()
+    set(top_same 1)
+  endif()
+
+  set(external "") # Entries external to the source tree.
+  set(internal "") # Entries internal to the source tree.
+  set(have_original 0)
+
+  # Process options.
+  set(associated_files "")
+  set(associated_regex "")
+  foreach(opt ${options})
+    if("x${opt}" MATCHES "^xREGEX:[^:/]+$")
+      # Regular expression to match associated files.
+      string(REGEX REPLACE "^REGEX:" "" regex "${opt}")
+      list(APPEND associated_regex "${regex}")
+    elseif("x${opt}" MATCHES "^[^][:/*?]+$")
+      # Specific associated file.
+      list(APPEND associated_files "${opt}")
+    else()
+      message(FATAL_ERROR "Unknown option \"${opt}\" in argument\n"
+        "  ${arg}\n")
+    endif()
+  endforeach()
+
+  if(associated_files OR associated_regex)
+    # Load the named data file and listed/matching associated files.
+    _ExternalData_arg_single()
+    _ExternalData_arg_associated()
+  elseif("${reldata}" MATCHES "(^|/)[^/.]+$")
+    # Files with no extension cannot be a series.
+    _ExternalData_arg_single()
+  else()
+    # Match a whole file series by default.
+    _ExternalData_arg_series()
+  endif()
+
+  if(NOT have_original)
+    message(FATAL_ERROR "Data file referenced by argument\n"
+      "  ${arg}\n"
+      "corresponds to source tree path\n"
+      "  ${reldata}\n"
+      "that does not exist (with or without an extension)!")
+  endif()
+
+  if(external)
+    # Make the series available in the build tree.
+    set_property(GLOBAL APPEND PROPERTY
+      _ExternalData_${target}_FETCH "${external}")
+    set_property(GLOBAL APPEND PROPERTY
+      _ExternalData_${target}_LOCAL "${internal}")
+    set("${var_file}" "${top_bin}/${reldata}" PARENT_SCOPE)
+  else()
+    # The whole series is in the source tree.
+    set("${var_file}" "${top_src}/${reldata}" PARENT_SCOPE)
+  endif()
+endfunction()
+
+macro(_ExternalData_arg_associated)
+  # Associated files lie in the same directory.
+  get_filename_component(reldir "${reldata}" PATH)
+  if(reldir)
+    set(reldir "${reldir}/")
+  endif()
+  _ExternalData_exact_regex(reldir_regex "${reldir}")
+
+  # Find files named explicitly.
+  foreach(file ${associated_files})
+    _ExternalData_exact_regex(file_regex "${file}")
+    _ExternalData_arg_find_files("${reldir}${file}" "${reldir_regex}${file_regex}")
+  endforeach()
+
+  # Find files matching the given regular expressions.
+  set(all "")
+  set(sep "")
+  foreach(regex ${associated_regex})
+    set(all "${all}${sep}${reldir_regex}${regex}")
+    set(sep "|")
+  endforeach()
+  _ExternalData_arg_find_files("${reldir}" "${all}")
+endmacro()
+
+macro(_ExternalData_arg_single)
+  # Match only the named data by itself.
+  _ExternalData_exact_regex(data_regex "${reldata}")
+  _ExternalData_arg_find_files("${reldata}" "${data_regex}")
+endmacro()
+
+macro(_ExternalData_arg_series)
+  # Configure series parsing and matching.
+  if(ExternalData_SERIES_PARSE)
+    if(NOT "${ExternalData_SERIES_PARSE}" MATCHES
+        "^\\^\\([^()]*\\)\\([^()]*\\)\\([^()]*\\)\\$$")
+      message(FATAL_ERROR
+        "ExternalData_SERIES_PARSE is set to\n"
+        "  ${ExternalData_SERIES_PARSE}\n"
+        "which is not of the form\n"
+        "  ^(...)(...)(...)$\n")
+    endif()
+    set(series_parse "${ExternalData_SERIES_PARSE}")
+  else()
+    set(series_parse "^(.*)()(\\.[^./]*)$")
+  endif()
+  if(ExternalData_SERIES_MATCH)
+    set(series_match "${ExternalData_SERIES_MATCH}")
+  else()
+    set(series_match "[_.]?[0-9]*")
+  endif()
+
+  # Parse the base, number, and extension components of the series.
+  string(REGEX REPLACE "${series_parse}" "\\1;\\2;\\3" tuple "${reldata}")
+  list(LENGTH tuple len)
+  if(NOT "${len}" EQUAL 3)
+    message(FATAL_ERROR "Data file referenced by argument\n"
+      "  ${arg}\n"
+      "corresponds to path\n"
+      "  ${reldata}\n"
+      "that does not match regular expression\n"
+      "  ${series_parse}")
+  endif()
+  list(GET tuple 0 relbase)
+  list(GET tuple 2 ext)
+
+  # Glob files that might match the series.
+  # Then match match base, number, and extension.
+  _ExternalData_exact_regex(series_base "${relbase}")
+  _ExternalData_exact_regex(series_ext "${ext}")
+  _ExternalData_arg_find_files("${relbase}*${ext}"
+    "${series_base}${series_match}${series_ext}")
+endmacro()
+
+function(_ExternalData_arg_find_files pattern regex)
+  file(GLOB globbed RELATIVE "${top_src}" "${top_src}/${pattern}*")
+  foreach(entry IN LISTS globbed)
+    string(REGEX REPLACE "^(${regex})(\\.md5|)$" "\\1;\\2" tuple "${entry}")
+    list(LENGTH tuple len)
+    if("${len}" EQUAL 2)
+      list(GET tuple 0 relname)
+      list(GET tuple 1 alg)
+      set(name "${top_src}/${relname}")
+      set(file "${top_bin}/${relname}")
+      if(alg)
+        list(APPEND external "${file}|${name}|${alg}")
+      elseif(ExternalData_LINK_CONTENT)
+        _ExternalData_link_content("${name}" alg)
+        list(APPEND external "${file}|${name}|${alg}")
+      elseif(NOT top_same)
+        list(APPEND internal "${file}|${name}")
+      endif()
+      if("${relname}" STREQUAL "${reldata}")
+        set(have_original 1)
+      endif()
+    endif()
+  endforeach()
+  set(external "${external}" PARENT_SCOPE)
+  set(internal "${internal}" PARENT_SCOPE)
+  set(have_original "${have_original}" PARENT_SCOPE)
+endfunction()
+
+#-----------------------------------------------------------------------------
+# Private script mode interface
+
+if(CMAKE_GENERATOR OR NOT ExternalData_ACTION)
+  return()
+endif()
+
+if(ExternalData_CONFIG)
+  include(${ExternalData_CONFIG})
+endif()
+if(NOT ExternalData_URL_TEMPLATES)
+  message(FATAL_ERROR "No ExternalData_URL_TEMPLATES set!")
+endif()
+
+function(_ExternalData_link_or_copy src dst)
+  # Create a temporary file first.
+  get_filename_component(dst_dir "${dst}" PATH)
+  file(MAKE_DIRECTORY "${dst_dir}")
+  _ExternalData_random(random)
+  set(tmp "${dst}.tmp${random}")
+  if(UNIX)
+    # Create a symbolic link.
+    set(tgt "${src}")
+    if(relative_top)
+      # Use relative path if files are close enough.
+      file(RELATIVE_PATH relsrc "${relative_top}" "${src}")
+      file(RELATIVE_PATH relfile "${relative_top}" "${dst}")
+      if(NOT IS_ABSOLUTE "${relsrc}" AND NOT "${relsrc}" MATCHES "^\\.\\./" AND
+          NOT IS_ABSOLUTE "${reldst}" AND NOT "${reldst}" MATCHES "^\\.\\./")
+        file(RELATIVE_PATH tgt "${dst_dir}" "${src}")
+      endif()
+    endif()
+    execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${tgt}" "${tmp}" RESULT_VARIABLE result)
+  else()
+    # Create a copy.
+    execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${src}" "${tmp}" RESULT_VARIABLE result)
+  endif()
+  if(result)
+    file(REMOVE "${tmp}")
+    message(FATAL_ERROR "Failed to create\n  ${tmp}\nfrom\n  ${obj}")
+  endif()
+
+  # Atomically create/replace the real destination.
+  file(RENAME "${tmp}" "${dst}")
+endfunction()
+
+function(_ExternalData_download_file url file err_var msg_var)
+  set(retry 3)
+  while(retry)
+    math(EXPR retry "${retry} - 1")
+    if("${CMAKE_VERSION}" VERSION_GREATER 2.8.4.20110602)
+      if(ExternalData_TIMEOUT_INACTIVITY)
+        set(inactivity_timeout INACTIVITY_TIMEOUT ${ExternalData_TIMEOUT_INACTIVITY})
+      elseif(NOT "${ExternalData_TIMEOUT_INACTIVITY}" EQUAL 0)
+        set(inactivity_timeout INACTIVITY_TIMEOUT 60)
+      else()
+        set(inactivity_timeout "")
+      endif()
+    else()
+      set(inactivity_timeout "")
+    endif()
+    if(ExternalData_TIMEOUT_ABSOLUTE)
+      set(absolute_timeout TIMEOUT ${ExternalData_TIMEOUT_ABSOLUTE})
+    elseif(NOT "${ExternalData_TIMEOUT_ABSOLUTE}" EQUAL 0)
+      set(absolute_timeout TIMEOUT 300)
+    else()
+      set(absolute_timeout "")
+    endif()
+    file(DOWNLOAD "${url}" "${file}" STATUS status LOG log ${inactivity_timeout} ${absolute_timeout} SHOW_PROGRESS)
+    list(GET status 0 err)
+    list(GET status 1 msg)
+    if(err)
+      if("${msg}" MATCHES "HTTP response code said error" AND
+          "${log}" MATCHES "error: 503")
+        set(msg "temporarily unavailable")
+      endif()
+    elseif("${log}" MATCHES "\nHTTP[^\n]* 503")
+      set(err TRUE)
+      set(msg "temporarily unavailable")
+    endif()
+    if(NOT err OR NOT "${msg}" MATCHES "partial|timeout|temporarily")
+      break()
+    elseif(retry)
+      message(STATUS "[download terminated: ${msg}, retries left: ${retry}]")
+    endif()
+  endwhile()
+  set("${err_var}" "${err}" PARENT_SCOPE)
+  set("${msg_var}" "${msg}" PARENT_SCOPE)
+endfunction()
+
+function(_ExternalData_download_object name hash algo var_obj)
+  # Search all object stores for an existing object.
+  foreach(dir ${ExternalData_OBJECT_STORES})
+    set(obj "${dir}/${algo}/${hash}")
+    if(EXISTS "${obj}")
+      message(STATUS "Found object: \"${obj}\"")
+      set("${var_obj}" "${obj}" PARENT_SCOPE)
+      return()
+    endif()
+  endforeach()
+
+  # Download object to the first store.
+  list(GET ExternalData_OBJECT_STORES 0 store)
+  set(obj "${store}/${algo}/${hash}")
+
+  _ExternalData_random(random)
+  set(tmp "${obj}.tmp${random}")
+  set(found 0)
+  set(tried "")
+  foreach(url_template IN LISTS ExternalData_URL_TEMPLATES)
+    string(REPLACE "%(hash)" "${hash}" url_tmp "${url_template}")
+    string(REPLACE "%(algo)" "${algo}" url "${url_tmp}")
+    message(STATUS "Fetching \"${url}\"")
+    _ExternalData_download_file("${url}" "${tmp}" err errMsg)
+    set(tried "${tried}\n  ${url}")
+    if(err)
+      set(tried "${tried} (${errMsg})")
+    else()
+      # Verify downloaded object.
+      _ExternalData_compute_hash(dl_hash "${algo}" "${tmp}")
+      if("${dl_hash}" STREQUAL "${hash}")
+        set(found 1)
+        break()
+      else()
+        set(tried "${tried} (wrong hash ${algo}=${dl_hash})")
+        if("$ENV{ExternalData_DEBUG_DOWNLOAD}" MATCHES ".")
+          file(RENAME "${tmp}" "${store}/${algo}/${dl_hash}")
+        endif()
+      endif()
+    endif()
+    file(REMOVE "${tmp}")
+  endforeach()
+
+  get_filename_component(dir "${name}" PATH)
+  set(staged "${dir}/.ExternalData_${algo}_${hash}")
+
+  if(found)
+    file(RENAME "${tmp}" "${obj}")
+    message(STATUS "Downloaded object: \"${obj}\"")
+  elseif(EXISTS "${staged}")
+    set(obj "${staged}")
+    message(STATUS "Staged object: \"${obj}\"")
+  else()
+    message(FATAL_ERROR "Object ${algo}=${hash} not found at:${tried}")
+  endif()
+
+  set("${var_obj}" "${obj}" PARENT_SCOPE)
+endfunction()
+
+if("${ExternalData_ACTION}" STREQUAL "fetch")
+  foreach(v ExternalData_OBJECT_STORES file name ext)
+    if(NOT DEFINED "${v}")
+      message(FATAL_ERROR "No \"-D${v}=\" value provided!")
+    endif()
+  endforeach()
+
+  file(READ "${name}${ext}" hash)
+  string(STRIP "${hash}" hash)
+
+  if("${ext}" STREQUAL ".md5")
+    set(algo "MD5")
+  else()
+    message(FATAL_ERROR "Unknown hash algorithm extension \"${ext}\"")
+  endif()
+
+  _ExternalData_download_object("${name}" "${hash}" "${algo}" obj)
+
+  # Check if file already corresponds to the object.
+  set(stamp "${ext}-stamp")
+  set(file_up_to_date 0)
+  if(EXISTS "${file}" AND EXISTS "${file}${stamp}")
+    file(READ "${file}${stamp}" f_hash)
+    string(STRIP "${f_hash}" f_hash)
+    if("${f_hash}" STREQUAL "${hash}")
+      #message(STATUS "File already corresponds to object")
+      set(file_up_to_date 1)
+    endif()
+  endif()
+
+  if(file_up_to_date)
+    # Touch the file to convince the build system it is up to date.
+    execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${file}")
+  else()
+    _ExternalData_link_or_copy("${obj}" "${file}")
+  endif()
+
+  # Atomically update the hash/timestamp file to record the object referenced.
+  _ExternalData_atomic_write("${file}${stamp}" "${hash}\n")
+elseif("${ExternalData_ACTION}" STREQUAL "local")
+  foreach(v file name)
+    if(NOT DEFINED "${v}")
+      message(FATAL_ERROR "No \"-D${v}=\" value provided!")
+    endif()
+  endforeach()
+  _ExternalData_link_or_copy("${name}" "${file}")
+elseif("${ExternalData_ACTION}" STREQUAL "store")
+  foreach(v dir file)
+    if(NOT DEFINED "${v}")
+      message(FATAL_ERROR "No \"-D${v}=\" value provided!")
+    endif()
+  endforeach()
+  if(NOT DEFINED algo)
+    set(algo "MD5")
+  endif()
+  _ExternalData_compute_hash(hash "${algo}" "${file}")
+else()
+  message(FATAL_ERROR "Unknown ExternalData_ACTION=[${ExternalData_ACTION}]")
+endif()
diff --git a/Modules/ExternalData_config.cmake.in b/Modules/ExternalData_config.cmake.in
new file mode 100644
index 0000000..0858f53
--- /dev/null
+++ b/Modules/ExternalData_config.cmake.in
@@ -0,0 +1,4 @@
+set(ExternalData_OBJECT_STORES "@ExternalData_OBJECT_STORES@")
+set(ExternalData_URL_TEMPLATES "@ExternalData_URL_TEMPLATES@")
+set(ExternalData_TIMEOUT_INACTIVITY "@ExternalData_TIMEOUT_INACTIVITY@")
+set(ExternalData_TIMEOUT_ABSOLUTE "@ExternalData_TIMEOUT_ABSOLUTE@")

-----------------------------------------------------------------------

Summary of changes:
 Modules/ExternalData.cmake                         |  761 ++++++++++++++++++++
 Modules/ExternalData_config.cmake.in               |    4 +
 Tests/CMakeLists.txt                               |   12 +
 Tests/Module/ExternalData/CMakeLists.txt           |   34 +
 Tests/Module/ExternalData/Data.dat.md5             |    1 +
 Tests/Module/ExternalData/Data1Check.cmake         |   52 ++
 Tests/Module/ExternalData/Data2.dat.md5            |    1 +
 Tests/Module/ExternalData/Data2/CMakeLists.txt     |   11 +
 Tests/Module/ExternalData/Data2/Data2Check.cmake   |   12 +
 .../ExternalData/Data2/SeriesC_1_.my.dat.md5       |    1 +
 .../ExternalData/Data2/SeriesC_2_.my.dat.md5       |    1 +
 .../ExternalData/Data2/SeriesC_3_.my.dat.md5       |    1 +
 Tests/Module/ExternalData/Data2b.dat.md5           |    1 +
 Tests/Module/ExternalData/Data3/CMakeLists.txt     |   14 +
 Tests/Module/ExternalData/Data3/Data.dat.md5       |    1 +
 Tests/Module/ExternalData/Data3/Data3Check.cmake   |   25 +
 Tests/Module/ExternalData/Data3/Other.dat.md5      |    1 +
 Tests/Module/ExternalData/Directory/A.dat.md5      |    1 +
 Tests/Module/ExternalData/Directory/B.dat.md5      |    1 +
 Tests/Module/ExternalData/Directory/C.dat.md5      |    1 +
 Tests/Module/ExternalData/MD5/.gitattributes       |    1 +
 .../MD5/08cfcf221f76ace7b906b312284e73d7           |    1 +
 .../MD5/30ba0acdee9096b3b9fc6c69362c6b42           |    1 +
 .../MD5/31eff09e84fca01415f8cd9d82ec432b           |    1 +
 .../MD5/401767f22a456b3522953722090a2c36           |    1 +
 .../MD5/8c018830e3efa5caf3c7415028335a57           |    1 +
 .../MD5/8f4add4581551facf27237e6577fd662           |    1 +
 .../MD5/9d980b06c2f0fec3d4872d68175b9822           |    1 +
 .../MD5/aaad162b85f60d1eb57ca71a23e8efd7           |    1 +
 .../MD5/c1030719c95f3435d8abc39c0d442946           |    1 +
 .../MD5/ce38ea6c3c1e00fa6405dd64b8bf6da0           |    1 +
 .../MD5/ecfa1ecd417d4253af81ae04d1bd6581           |    1 +
 .../MD5/f41c94425d01ecbbee70440b951cb058           |    1 +
 .../MD5/f7ab5a04aae9cb9a520e70b20b9c8ed7           |    1 +
 Tests/Module/ExternalData/MetaA.dat.md5            |    1 +
 Tests/Module/ExternalData/MetaB.dat.md5            |    1 +
 Tests/Module/ExternalData/MetaC.dat.md5            |    1 +
 Tests/Module/ExternalData/MetaTop.dat.md5          |    1 +
 Tests/Module/ExternalData/PairedA.dat.md5          |    1 +
 Tests/Module/ExternalData/PairedB.dat.md5          |    1 +
 Tests/Module/ExternalData/SHA1/.gitattributes      |    1 +
 .../SHA1/2af59a7022024974f3b8521b7ed8137c996a79f1  |    1 +
 Tests/Module/ExternalData/SHA224/.gitattributes    |    1 +
 ...08562fe1cc28db47ffb89bae025f4551dceb343a5869174 |    1 +
 Tests/Module/ExternalData/SHA256/.gitattributes    |    1 +
 ...096bd3e8178c7e26c711c9b20dbcaa3853d869d3871f133 |    1 +
 Tests/Module/ExternalData/SeriesA.dat.md5          |    1 +
 Tests/Module/ExternalData/SeriesA1.dat.md5         |    1 +
 Tests/Module/ExternalData/SeriesA2.dat.md5         |    1 +
 Tests/Module/ExternalData/SeriesA3.dat.md5         |    1 +
 Tests/Module/ExternalData/SeriesAn1.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesAn2.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesAn3.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesB.dat.md5          |    1 +
 Tests/Module/ExternalData/SeriesB_1.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesB_2.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesB_3.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesBn_1.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesBn_2.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesBn_3.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesC.1.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesC.2.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesC.3.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesC.dat.md5          |    1 +
 Tests/Module/ExternalData/SeriesCn.1.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesCn.2.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesCn.3.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesD-1.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesD-2.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesD-3.dat.md5        |    1 +
 Tests/Module/ExternalData/SeriesD.dat.md5          |    1 +
 Tests/Module/ExternalData/SeriesDn-1.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesDn-2.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesDn-3.dat.md5       |    1 +
 Tests/Module/ExternalData/SeriesMixed.1.dat.md5    |    1 +
 Tests/Module/ExternalData/SeriesMixed.2.dat.sha1   |    1 +
 Tests/Module/ExternalData/SeriesMixed.3.dat.sha224 |    1 +
 Tests/Module/ExternalData/SeriesMixed.4.dat.sha256 |    1 +
 Tests/RunCMake/CMakeLists.txt                      |    1 +
 .../BadHashAlgo1-result.txt}                       |    0
 .../RunCMake/ExternalData/BadHashAlgo1-stderr.txt  |    8 +
 Tests/RunCMake/ExternalData/BadHashAlgo1.cmake     |    3 +
 Tests/RunCMake/ExternalData/BadHashAlgo1.txt       |    1 +
 .../BadOption1-result.txt}                         |    0
 Tests/RunCMake/ExternalData/BadOption1-stderr.txt  |    9 +
 Tests/RunCMake/ExternalData/BadOption1.cmake       |    5 +
 .../BadOption2-result.txt}                         |    0
 Tests/RunCMake/ExternalData/BadOption2-stderr.txt  |    9 +
 Tests/RunCMake/ExternalData/BadOption2.cmake       |    5 +
 .../BadSeries1-result.txt}                         |    0
 Tests/RunCMake/ExternalData/BadSeries1-stderr.txt  |   19 +
 Tests/RunCMake/ExternalData/BadSeries1.cmake       |    3 +
 .../BadSeries2-result.txt}                         |    0
 Tests/RunCMake/ExternalData/BadSeries2-stderr.txt  |   16 +
 Tests/RunCMake/ExternalData/BadSeries2.cmake       |    3 +
 .../BadSeries3-result.txt}                         |    0
 Tests/RunCMake/ExternalData/BadSeries3-stderr.txt  |    6 +
 Tests/RunCMake/ExternalData/BadSeries3.cmake       |    2 +
 .../{CMP0004 => ExternalData}/CMakeLists.txt       |    0
 Tests/RunCMake/ExternalData/Data.txt.md5           |    1 +
 .../Directory1-result.txt}                         |    0
 Tests/RunCMake/ExternalData/Directory1-stderr.txt  |   14 +
 Tests/RunCMake/ExternalData/Directory1.cmake       |    6 +
 .../RunCMake/ExternalData/Directory1/DirData1.txt  |    0
 .../Directory2-result.txt}                         |    0
 Tests/RunCMake/ExternalData/Directory2-stderr.txt  |   10 +
 Tests/RunCMake/ExternalData/Directory2.cmake       |    6 +
 Tests/RunCMake/ExternalData/Directory2.md5         |    1 +
 .../RunCMake/ExternalData/Directory2/DirData2.txt  |    0
 .../Directory3-result.txt}                         |    0
 Tests/RunCMake/ExternalData/Directory3-stderr.txt  |   14 +
 Tests/RunCMake/ExternalData/Directory3.cmake       |    6 +
 .../RunCMake/ExternalData/Directory3/DirData3.txt  |    0
 .../Directory4-result.txt}                         |    0
 Tests/RunCMake/ExternalData/Directory4-stderr.txt  |    6 +
 Tests/RunCMake/ExternalData/Directory4.cmake       |    6 +
 .../RunCMake/ExternalData/Directory4/DirData4.txt  |    0
 .../Directory5-result.txt}                         |    0
 Tests/RunCMake/ExternalData/Directory5-stderr.txt  |   14 +
 Tests/RunCMake/ExternalData/Directory5.cmake       |    6 +
 .../ExternalData/LinkContentMD5-stdout.txt         |    3 +
 Tests/RunCMake/ExternalData/LinkContentMD5.cmake   |   22 +
 .../ExternalData/LinkContentSHA1-stdout.txt        |    3 +
 Tests/RunCMake/ExternalData/LinkContentSHA1.cmake  |   22 +
 .../MissingData-result.txt}                        |    0
 Tests/RunCMake/ExternalData/MissingData-stderr.txt |   14 +
 Tests/RunCMake/ExternalData/MissingData.cmake      |    5 +
 .../ExternalData/NoLinkInSource-stderr.txt         |    6 +
 .../ExternalData/NoLinkInSource-stdout.txt         |    1 +
 Tests/RunCMake/ExternalData/NoLinkInSource.cmake   |   14 +
 .../NoURLTemplates-result.txt}                     |    0
 .../ExternalData/NoURLTemplates-stderr.txt         |    5 +
 Tests/RunCMake/ExternalData/NoURLTemplates.cmake   |    2 +
 Tests/RunCMake/ExternalData/NormalData1-stdout.txt |    1 +
 Tests/RunCMake/ExternalData/NormalData1.cmake      |   13 +
 Tests/RunCMake/ExternalData/NormalData2-stdout.txt |    1 +
 Tests/RunCMake/ExternalData/NormalData2.cmake      |   14 +
 Tests/RunCMake/ExternalData/NormalData3-stdout.txt |    1 +
 Tests/RunCMake/ExternalData/NormalData3.cmake      |   14 +
 .../ExternalData/NormalDataSub1-stdout.txt         |    1 +
 Tests/RunCMake/ExternalData/NormalDataSub1.cmake   |   13 +
 .../NotUnderRoot-result.txt}                       |    0
 .../RunCMake/ExternalData/NotUnderRoot-stderr.txt  |   12 +
 Tests/RunCMake/ExternalData/NotUnderRoot.cmake     |    5 +
 Tests/RunCMake/ExternalData/RunCMakeTest.cmake     |   24 +
 .../RunCMake/ExternalData/SubDirectory1-stdout.txt |    3 +
 Tests/RunCMake/ExternalData/SubDirectory1.cmake    |    5 +
 .../ExternalData/SubDirectory1/CMakeLists.txt      |   29 +
 .../ExternalData/SubDirectory1/Data.txt.md5        |    1 +
 149 files changed, 1408 insertions(+), 0 deletions(-)
 create mode 100644 Modules/ExternalData.cmake
 create mode 100644 Modules/ExternalData_config.cmake.in
 create mode 100644 Tests/Module/ExternalData/CMakeLists.txt
 create mode 100644 Tests/Module/ExternalData/Data.dat.md5
 create mode 100644 Tests/Module/ExternalData/Data1Check.cmake
 create mode 100644 Tests/Module/ExternalData/Data2.dat.md5
 create mode 100644 Tests/Module/ExternalData/Data2/CMakeLists.txt
 create mode 100644 Tests/Module/ExternalData/Data2/Data2Check.cmake
 create mode 100644 Tests/Module/ExternalData/Data2/SeriesC_1_.my.dat.md5
 create mode 100644 Tests/Module/ExternalData/Data2/SeriesC_2_.my.dat.md5
 create mode 100644 Tests/Module/ExternalData/Data2/SeriesC_3_.my.dat.md5
 create mode 100644 Tests/Module/ExternalData/Data2b.dat.md5
 create mode 100644 Tests/Module/ExternalData/Data3/CMakeLists.txt
 create mode 100644 Tests/Module/ExternalData/Data3/Data.dat.md5
 create mode 100644 Tests/Module/ExternalData/Data3/Data3Check.cmake
 create mode 100644 Tests/Module/ExternalData/Data3/Other.dat.md5
 create mode 100644 Tests/Module/ExternalData/Directory/A.dat.md5
 create mode 100644 Tests/Module/ExternalData/Directory/B.dat.md5
 create mode 100644 Tests/Module/ExternalData/Directory/C.dat.md5
 create mode 100644 Tests/Module/ExternalData/MD5/.gitattributes
 create mode 100644 Tests/Module/ExternalData/MD5/08cfcf221f76ace7b906b312284e73d7
 create mode 100644 Tests/Module/ExternalData/MD5/30ba0acdee9096b3b9fc6c69362c6b42
 create mode 100644 Tests/Module/ExternalData/MD5/31eff09e84fca01415f8cd9d82ec432b
 create mode 100644 Tests/Module/ExternalData/MD5/401767f22a456b3522953722090a2c36
 create mode 100644 Tests/Module/ExternalData/MD5/8c018830e3efa5caf3c7415028335a57
 create mode 100644 Tests/Module/ExternalData/MD5/8f4add4581551facf27237e6577fd662
 create mode 100644 Tests/Module/ExternalData/MD5/9d980b06c2f0fec3d4872d68175b9822
 create mode 100644 Tests/Module/ExternalData/MD5/aaad162b85f60d1eb57ca71a23e8efd7
 create mode 100644 Tests/Module/ExternalData/MD5/c1030719c95f3435d8abc39c0d442946
 create mode 100644 Tests/Module/ExternalData/MD5/ce38ea6c3c1e00fa6405dd64b8bf6da0
 create mode 100644 Tests/Module/ExternalData/MD5/ecfa1ecd417d4253af81ae04d1bd6581
 create mode 100644 Tests/Module/ExternalData/MD5/f41c94425d01ecbbee70440b951cb058
 create mode 100644 Tests/Module/ExternalData/MD5/f7ab5a04aae9cb9a520e70b20b9c8ed7
 create mode 100644 Tests/Module/ExternalData/MetaA.dat.md5
 create mode 100644 Tests/Module/ExternalData/MetaB.dat.md5
 create mode 100644 Tests/Module/ExternalData/MetaC.dat.md5
 create mode 100644 Tests/Module/ExternalData/MetaTop.dat.md5
 create mode 100644 Tests/Module/ExternalData/PairedA.dat.md5
 create mode 100644 Tests/Module/ExternalData/PairedB.dat.md5
 create mode 100644 Tests/Module/ExternalData/SHA1/.gitattributes
 create mode 100644 Tests/Module/ExternalData/SHA1/2af59a7022024974f3b8521b7ed8137c996a79f1
 create mode 100644 Tests/Module/ExternalData/SHA224/.gitattributes
 create mode 100644 Tests/Module/ExternalData/SHA224/3b679da7908562fe1cc28db47ffb89bae025f4551dceb343a5869174
 create mode 100644 Tests/Module/ExternalData/SHA256/.gitattributes
 create mode 100644 Tests/Module/ExternalData/SHA256/969171a0dd70d49ce096bd3e8178c7e26c711c9b20dbcaa3853d869d3871f133
 create mode 100644 Tests/Module/ExternalData/SeriesA.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesA1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesA2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesA3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesAn1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesAn2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesAn3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesB.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesB_1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesB_2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesB_3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesBn_1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesBn_2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesBn_3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesC.1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesC.2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesC.3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesC.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesCn.1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesCn.2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesCn.3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesD-1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesD-2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesD-3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesD.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesDn-1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesDn-2.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesDn-3.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesMixed.1.dat.md5
 create mode 100644 Tests/Module/ExternalData/SeriesMixed.2.dat.sha1
 create mode 100644 Tests/Module/ExternalData/SeriesMixed.3.dat.sha224
 create mode 100644 Tests/Module/ExternalData/SeriesMixed.4.dat.sha256
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/BadHashAlgo1-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/BadHashAlgo1-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/BadHashAlgo1.cmake
 create mode 100644 Tests/RunCMake/ExternalData/BadHashAlgo1.txt
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/BadOption1-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/BadOption1-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/BadOption1.cmake
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/BadOption2-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/BadOption2-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/BadOption2.cmake
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/BadSeries1-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/BadSeries1-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/BadSeries1.cmake
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/BadSeries2-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/BadSeries2-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/BadSeries2.cmake
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/BadSeries3-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/BadSeries3-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/BadSeries3.cmake
 copy Tests/RunCMake/{CMP0004 => ExternalData}/CMakeLists.txt (100%)
 create mode 100644 Tests/RunCMake/ExternalData/Data.txt.md5
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/Directory1-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/Directory1-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/Directory1.cmake
 copy Modules/IntelVSImplicitPath/hello.f => Tests/RunCMake/ExternalData/Directory1/DirData1.txt (100%)
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/Directory2-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/Directory2-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/Directory2.cmake
 create mode 100644 Tests/RunCMake/ExternalData/Directory2.md5
 copy Modules/IntelVSImplicitPath/hello.f => Tests/RunCMake/ExternalData/Directory2/DirData2.txt (100%)
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/Directory3-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/Directory3-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/Directory3.cmake
 copy Modules/IntelVSImplicitPath/hello.f => Tests/RunCMake/ExternalData/Directory3/DirData3.txt (100%)
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/Directory4-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/Directory4-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/Directory4.cmake
 copy Modules/IntelVSImplicitPath/hello.f => Tests/RunCMake/ExternalData/Directory4/DirData4.txt (100%)
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/Directory5-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/Directory5-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/Directory5.cmake
 create mode 100644 Tests/RunCMake/ExternalData/LinkContentMD5-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/LinkContentMD5.cmake
 create mode 100644 Tests/RunCMake/ExternalData/LinkContentSHA1-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/LinkContentSHA1.cmake
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/MissingData-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/MissingData-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/MissingData.cmake
 create mode 100644 Tests/RunCMake/ExternalData/NoLinkInSource-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/NoLinkInSource-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/NoLinkInSource.cmake
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/NoURLTemplates-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/NoURLTemplates-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/NoURLTemplates.cmake
 create mode 100644 Tests/RunCMake/ExternalData/NormalData1-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/NormalData1.cmake
 create mode 100644 Tests/RunCMake/ExternalData/NormalData2-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/NormalData2.cmake
 create mode 100644 Tests/RunCMake/ExternalData/NormalData3-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/NormalData3.cmake
 create mode 100644 Tests/RunCMake/ExternalData/NormalDataSub1-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/NormalDataSub1.cmake
 copy Tests/RunCMake/{CMP0004/CMP0004-NEW-result.txt => ExternalData/NotUnderRoot-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ExternalData/NotUnderRoot-stderr.txt
 create mode 100644 Tests/RunCMake/ExternalData/NotUnderRoot.cmake
 create mode 100644 Tests/RunCMake/ExternalData/RunCMakeTest.cmake
 create mode 100644 Tests/RunCMake/ExternalData/SubDirectory1-stdout.txt
 create mode 100644 Tests/RunCMake/ExternalData/SubDirectory1.cmake
 create mode 100644 Tests/RunCMake/ExternalData/SubDirectory1/CMakeLists.txt
 create mode 100644 Tests/RunCMake/ExternalData/SubDirectory1/Data.txt.md5


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list