It's a little bit tricky to split refactor/new functionality exact but I've created several patches with step-by-step changes. Hope this helps in review.

Ruslo

On 18-May-16 22:50, Brad King wrote:
On 05/18/2016 03:30 PM, Ruslan Baratov via cmake-developers wrote:
I've attached patch with applying retry logic in cases when status code
is not zero.
Thanks.  Please split the patch to perform the refactoring into
the ExternalProject-$step.cmake.in files first and then make the
logic changes as a second patch.  Also please add an explanation
of the logic change to the second commit message similar to what
you wrote in the original email.

-Brad


>From 5b4149ddc436f83bff4b7636884f86e9200b9fe7 Mon Sep 17 00:00:00 2001
From: Ruslan Baratov <ruslan_bara...@yahoo.com>
Date: Thu, 19 May 2016 14:38:06 +0300
Subject: [PATCH 1/6] ExternalProject refactoring: uppercase variables

Use uppercase variables for future 'configure_file' command.
---
 Modules/ExternalProject.cmake | 54 +++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 7dad6e5..a7fc1f9 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -847,25 +847,25 @@ endif()
 
 endfunction(_ep_write_gitupdate_script)
 
-function(_ep_write_downloadfile_script script_filename remote local timeout no_progress hash tls_verify tls_cainfo)
+function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout no_progress hash tls_verify tls_cainfo)
   if(timeout)
-    set(timeout_args TIMEOUT ${timeout})
-    set(timeout_msg "${timeout} seconds")
+    set(TIMEOUT_ARGS TIMEOUT ${timeout})
+    set(TIMEOUT_MSG "${timeout} seconds")
   else()
-    set(timeout_args "# no TIMEOUT")
-    set(timeout_msg "none")
+    set(TIMEOUT_ARGS "# no TIMEOUT")
+    set(TIMEOUT_MSG "none")
   endif()
 
   if(no_progress)
-    set(show_progress "")
+    set(SHOW_PROGRESS "")
   else()
-    set(show_progress "SHOW_PROGRESS")
+    set(SHOW_PROGRESS "SHOW_PROGRESS")
   endif()
 
   if("${hash}" MATCHES "${_ep_hash_regex}")
     string(CONCAT hash_check
-      "if(EXISTS \"${local}\")\n"
-      "  file(\"${CMAKE_MATCH_1}\" \"${local}\" hash_value)\n"
+      "if(EXISTS \"${LOCAL}\")\n"
+      "  file(\"${CMAKE_MATCH_1}\" \"${LOCAL}\" hash_value)\n"
       "  if(\"x\${hash_value}\" STREQUAL \"x${CMAKE_MATCH_2}\")\n"
       "    return()\n"
       "  endif()\n"
@@ -875,15 +875,15 @@ function(_ep_write_downloadfile_script script_filename remote local timeout no_p
     set(hash_check "")
   endif()
 
-  set(tls_verify_code "")
-  set(tls_cainfo_code "")
+  set(TLS_VERIFY_CODE "")
+  set(TLS_CAINFO_CODE "")
 
   # check for curl globals in the project
   if(DEFINED CMAKE_TLS_VERIFY)
-    set(tls_verify_code "set(CMAKE_TLS_VERIFY ${CMAKE_TLS_VERIFY})")
+    set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY ${CMAKE_TLS_VERIFY})")
   endif()
   if(DEFINED CMAKE_TLS_CAINFO)
-    set(tls_cainfo_code "set(CMAKE_TLS_CAINFO \"${CMAKE_TLS_CAINFO}\")")
+    set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${CMAKE_TLS_CAINFO}\")")
   endif()
 
   # now check for curl locals so that the local values
@@ -892,28 +892,28 @@ function(_ep_write_downloadfile_script script_filename remote local timeout no_p
   # check for tls_verify argument
   string(LENGTH "${tls_verify}" tls_verify_len)
   if(tls_verify_len GREATER 0)
-    set(tls_verify_code "set(CMAKE_TLS_VERIFY ${tls_verify})")
+    set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY ${tls_verify})")
   endif()
   # check for tls_cainfo argument
   string(LENGTH "${tls_cainfo}" tls_cainfo_len)
   if(tls_cainfo_len GREATER 0)
-    set(tls_cainfo_code "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")")
+    set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")")
   endif()
 
   file(WRITE ${script_filename}
 "${hash_check}message(STATUS \"downloading...
-     src='${remote}'
-     dst='${local}'
-     timeout='${timeout_msg}'\")
+     src='${REMOTE}'
+     dst='${LOCAL}'
+     timeout='${TIMEOUT_MSG}'\")
 
-${tls_verify_code}
-${tls_cainfo_code}
+${TLS_VERIFY_CODE}
+${TLS_CAINFO_CODE}
 
 file(DOWNLOAD
-  \"${remote}\"
-  \"${local}\"
-  ${show_progress}
-  ${timeout_args}
+  \"${REMOTE}\"
+  \"${LOCAL}\"
+  ${SHOW_PROGRESS}
+  ${TIMEOUT_ARGS}
   STATUS status
   LOG log)
 
@@ -921,7 +921,7 @@ list(GET status 0 status_code)
 list(GET status 1 status_string)
 
 if(NOT status_code EQUAL 0)
-  message(FATAL_ERROR \"error: downloading '${remote}' failed
+  message(FATAL_ERROR \"error: downloading '${REMOTE}' failed
   status_code: \${status_code}
   status_string: \${status_string}
   log: \${log}
@@ -935,7 +935,7 @@ message(STATUS \"downloading... done\")
 endfunction()
 
 
-function(_ep_write_verifyfile_script script_filename local hash retries download_script)
+function(_ep_write_verifyfile_script script_filename LOCAL hash retries download_script)
   if("${hash}" MATCHES "${_ep_hash_regex}")
     set(algo "${CMAKE_MATCH_1}")
     string(TOLOWER "${CMAKE_MATCH_2}" expect_value)
@@ -972,7 +972,7 @@ endif()")
   else()
     set(script_content "message(STATUS \"verifying file... warning: did not verify file - no URL_HASH specified?\")")
   endif()
-  file(WRITE ${script_filename} "set(file \"${local}\")
+  file(WRITE ${script_filename} "set(file \"${LOCAL}\")
 message(STATUS \"verifying file...
      file='\${file}'\")
 ${script_content}
-- 
1.9.1

>From 1fe814619bfb7998c56cd014e8db321c5ab73232 Mon Sep 17 00:00:00 2001
From: Ruslan Baratov <ruslan_bara...@yahoo.com>
Date: Thu, 19 May 2016 14:41:52 +0300
Subject: [PATCH 2/6] ExternalProject refactoring: remove 'retries'

There is no retries for local files and retry logic is broken for downloads.
Will be implemented in '*-download.cmake' script.
---
 Modules/ExternalProject.cmake | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index a7fc1f9..f3b0a4d 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -935,7 +935,8 @@ message(STATUS \"downloading... done\")
 endfunction()
 
 
-function(_ep_write_verifyfile_script script_filename LOCAL hash retries download_script)
+function(_ep_write_verifyfile_script script_filename LOCAL hash download_script)
+  set(retries 0)
   if("${hash}" MATCHES "${_ep_hash_regex}")
     set(algo "${CMAKE_MATCH_1}")
     string(TOLOWER "${CMAKE_MATCH_2}" expect_value)
@@ -1898,7 +1899,6 @@ function(_ep_add_download_command name)
     set(repository "external project URL")
     set(module "${url}")
     set(tag "${hash}")
-    set(retries 0)
     set(download_script "")
     configure_file(
       "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
@@ -1937,7 +1937,6 @@ function(_ep_add_download_command name)
         _ep_write_downloadfile_script("${download_script}" "${url}" "${file}" "${timeout}" "${no_progress}" "${hash}" "${tls_verify}" "${tls_cainfo}")
         set(cmd ${CMAKE_COMMAND} -P "${download_script}"
           COMMAND)
-        set(retries 3)
         if (no_extract)
           set(steps "download and verify")
         else ()
@@ -1953,7 +1952,7 @@ function(_ep_add_download_command name)
         endif ()
         set(comment "Performing download step (${steps}) for '${name}'")
       endif()
-      _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}" "${retries}" "${download_script}")
+      _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}" "${download_script}")
       list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake
         COMMAND)
       if (NOT no_extract)
-- 
1.9.1

>From 610bfdf13b04c544d35470377dbd5882a2094dd9 Mon Sep 17 00:00:00 2001
From: Ruslan Baratov <ruslan_bara...@yahoo.com>
Date: Thu, 19 May 2016 14:48:49 +0300
Subject: [PATCH 3/6] ExternalProject: remove unused logic

---
 Modules/ExternalProject.cmake | 19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index f3b0a4d..0efe0fb 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -935,30 +935,16 @@ message(STATUS \"downloading... done\")
 endfunction()
 
 
-function(_ep_write_verifyfile_script script_filename LOCAL hash download_script)
-  set(retries 0)
+function(_ep_write_verifyfile_script script_filename LOCAL hash)
   if("${hash}" MATCHES "${_ep_hash_regex}")
     set(algo "${CMAKE_MATCH_1}")
     string(TOLOWER "${CMAKE_MATCH_2}" expect_value)
     set(script_content "set(expect_value \"${expect_value}\")
-set(attempt 0)
 set(succeeded 0)
-while(\${attempt} LESS ${retries} OR \${attempt} EQUAL ${retries} AND NOT \${succeeded})
   file(${algo} \"\${file}\" actual_value)
   if(\"\${actual_value}\" STREQUAL \"\${expect_value}\")
     set(succeeded 1)
-  elseif(\${attempt} LESS ${retries})
-    message(STATUS \"${algo} hash of \${file}
-does not match expected value
-  expected: \${expect_value}
-    actual: \${actual_value}
-Retrying download.
-\")
-    file(REMOVE \"\${file}\")
-    execute_process(COMMAND \${CMAKE_COMMAND} -P \"${download_script}\")
   endif()
-  math(EXPR attempt \"\${attempt} + 1\")
-endwhile()
 
 if(\${succeeded})
   message(STATUS \"verifying file... done\")
@@ -1899,7 +1885,6 @@ function(_ep_add_download_command name)
     set(repository "external project URL")
     set(module "${url}")
     set(tag "${hash}")
-    set(download_script "")
     configure_file(
       "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
       "${stamp_dir}/${name}-urlinfo.txt"
@@ -1952,7 +1937,7 @@ function(_ep_add_download_command name)
         endif ()
         set(comment "Performing download step (${steps}) for '${name}'")
       endif()
-      _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}" "${download_script}")
+      _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
       list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake
         COMMAND)
       if (NOT no_extract)
-- 
1.9.1

>From 216437266ac5111177fed1e3c0979df69accb0b6 Mon Sep 17 00:00:00 2001
From: Ruslan Baratov <ruslan_bara...@yahoo.com>
Date: Thu, 19 May 2016 14:51:43 +0300
Subject: [PATCH 4/6] ExternalProject refactoring: avoid double verification

Verify step for downloaded files will be performed in separate script
---
 Modules/ExternalProject.cmake | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 0efe0fb..cee402e 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -1928,6 +1928,7 @@ function(_ep_add_download_command name)
           set(steps "download, verify and extract")
         endif ()
         set(comment "Performing download step (${steps}) for '${name}'")
+        file(WRITE "${stamp_dir}/verify-${name}.cmake" "") # already verified by 'download_script'
       else()
         set(file "${url}")
         if (no_extract)
@@ -1936,8 +1937,8 @@ function(_ep_add_download_command name)
           set(steps "verify and extract")
         endif ()
         set(comment "Performing download step (${steps}) for '${name}'")
+        _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
       endif()
-      _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
       list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake
         COMMAND)
       if (NOT no_extract)
-- 
1.9.1

>From cba549a21f08f7c460c4ac73c1649f13dba16659 Mon Sep 17 00:00:00 2001
From: Ruslan Baratov <ruslan_bara...@yahoo.com>
Date: Thu, 19 May 2016 15:00:40 +0300
Subject: [PATCH 5/6] ExternalProject: use separate verify script
 ExternalProject-verify.cmake.in

---
 Modules/ExternalProject-verify.cmake.in | 48 +++++++++++++++++++++++++++++++++
 Modules/ExternalProject.cmake           | 43 +++++++++++++----------------
 2 files changed, 66 insertions(+), 25 deletions(-)
 create mode 100644 Modules/ExternalProject-verify.cmake.in

diff --git a/Modules/ExternalProject-verify.cmake.in b/Modules/ExternalProject-verify.cmake.in
new file mode 100644
index 0000000..1d8db96
--- /dev/null
+++ b/Modules/ExternalProject-verify.cmake.in
@@ -0,0 +1,48 @@
+#=============================================================================
+# Copyright 2008-2013 Kitware, Inc.
+# Copyright 2016 Ruslan Baratov
+#
+# 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.)
+
+cmake_minimum_required(VERSION 3.5)
+
+if("@LOCAL@" STREQUAL "")
+  message(FATAL_ERROR "LOCAL can't be empty")
+endif()
+
+if(NOT EXISTS "@LOCAL@")
+  message(FATAL_ERROR "File not found: @LOCAL@")
+endif()
+
+if("@ALGO@" STREQUAL "")
+  message(WARNING "File will not be verified since no URL_HASH specified")
+  return()
+endif()
+
+if("@EXPECT_VALUE@" STREQUAL "")
+  message(FATAL_ERROR "EXPECT_VALUE can't be empty")
+endif()
+
+message(STATUS "verifying file...
+     file='@LOCAL@'")
+
+file("@ALGO@" "@LOCAL@" actual_value)
+
+if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@")
+  message(FATAL_ERROR "error: @ALGO@ hash of
+  @LOCAL@
+does not match expected value
+  expected: '@EXPECT_VALUE@'
+    actual: '${actual_value}'
+")
+endif()
+
+message(STATUS "verifying file... done")
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index cee402e..a24d355 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -377,6 +377,7 @@ file::
 
 #=============================================================================
 # Copyright 2008-2013 Kitware, Inc.
+# Copyright 2016 Ruslan Baratov
 #
 # Distributed under the OSI-approved BSD License (the "License");
 # see accompanying file Copyright.txt for details.
@@ -418,6 +419,9 @@ endif()
 set(_ep_hash_algos "MD5|SHA1|SHA224|SHA256|SHA384|SHA512")
 set(_ep_hash_regex "^(${_ep_hash_algos})=([0-9A-Fa-f]+)$")
 
+set(_ExternalProject_SELF "${CMAKE_CURRENT_LIST_FILE}")
+get_filename_component(_ExternalProject_SELF_DIR "${_ExternalProject_SELF}" PATH)
+
 function(_ep_parse_arguments f name ns args)
   # Transfer the arguments to this function into target properties for the
   # new custom target we just added so that we can set up all the build steps
@@ -937,33 +941,22 @@ endfunction()
 
 function(_ep_write_verifyfile_script script_filename LOCAL hash)
   if("${hash}" MATCHES "${_ep_hash_regex}")
-    set(algo "${CMAKE_MATCH_1}")
-    string(TOLOWER "${CMAKE_MATCH_2}" expect_value)
-    set(script_content "set(expect_value \"${expect_value}\")
-set(succeeded 0)
-  file(${algo} \"\${file}\" actual_value)
-  if(\"\${actual_value}\" STREQUAL \"\${expect_value}\")
-    set(succeeded 1)
-  endif()
-
-if(\${succeeded})
-  message(STATUS \"verifying file... done\")
-else()
-  message(FATAL_ERROR \"error: ${algo} hash of
-  \${file}
-does not match expected value
-  expected: \${expect_value}
-    actual: \${actual_value}
-\")
-endif()")
+    set(ALGO "${CMAKE_MATCH_1}")
+    string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
   else()
-    set(script_content "message(STATUS \"verifying file... warning: did not verify file - no URL_HASH specified?\")")
+    set(ALGO "")
+    set(EXPECT_VALUE "")
   endif()
-  file(WRITE ${script_filename} "set(file \"${LOCAL}\")
-message(STATUS \"verifying file...
-     file='\${file}'\")
-${script_content}
-")
+
+  # Used variables:
+  # * ALGO
+  # * EXPECT_VALUE
+  # * LOCAL
+  configure_file(
+      "${_ExternalProject_SELF_DIR}/ExternalProject-verify.cmake.in"
+      "${script_filename}"
+      @ONLY
+  )
 endfunction()
 
 
-- 
1.9.1

>From c88916c60f970f4181e279755942813b809abb8e Mon Sep 17 00:00:00 2001
From: Ruslan Baratov <ruslan_bara...@yahoo.com>
Date: Thu, 19 May 2016 16:35:01 +0300
Subject: [PATCH 6/6] ExternalProject: use separate download script
 ExternalProject-download.cmake.in

Verify and retry logic moved to *-download script. Retry logic was not working
before because similar script trigger FATAL_ERROR if 'file(DOWNLOAD ...)'
exits with nonzero 'status_code'. FATAL_ERROR makes the whole chain of
commands stop and '_ep_write_verifyfile_script' retry logic was not used in
fact.

Default retry number set to 5 with pauses 0, 5, 5, 15, 60 seconds. Some space
left for future improvements if needed (90, 300, 1200=20min). Can be controlled
by user.
---
 Modules/ExternalProject-download.cmake.in | 161 ++++++++++++++++++++++++++++++
 Modules/ExternalProject.cmake             |  61 ++++-------
 2 files changed, 180 insertions(+), 42 deletions(-)
 create mode 100644 Modules/ExternalProject-download.cmake.in

diff --git a/Modules/ExternalProject-download.cmake.in b/Modules/ExternalProject-download.cmake.in
new file mode 100644
index 0000000..5b73cd8
--- /dev/null
+++ b/Modules/ExternalProject-download.cmake.in
@@ -0,0 +1,161 @@
+#=============================================================================
+# Copyright 2008-2013 Kitware, Inc.
+# Copyright 2016 Ruslan Baratov
+#
+# 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.)
+
+cmake_minimum_required(VERSION 3.5)
+
+function(check_file_hash has_hash hash_is_good)
+  if("${has_hash}" STREQUAL "")
+    message(FATAL_ERROR "has_hash Can't be empty")
+  endif()
+
+  if("${hash_is_good}" STREQUAL "")
+    message(FATAL_ERROR "hash_is_good Can't be empty")
+  endif()
+
+  if("@ALGO@" STREQUAL "")
+    # No check
+    set("${has_hash}" FALSE PARENT_SCOPE)
+    set("${hash_is_good}" FALSE PARENT_SCOPE)
+    return()
+  endif()
+
+  set("${has_hash}" TRUE PARENT_SCOPE)
+
+  message(STATUS "verifying file...
+       file='@LOCAL@'")
+
+  file("@ALGO@" "@LOCAL@" actual_value)
+
+  if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@")
+    set("${hash_is_good}" FALSE PARENT_SCOPE)
+    message(STATUS "@ALGO@ hash of
+    @LOCAL@
+  does not match expected value
+    expected: '@EXPECT_VALUE@'
+      actual: '${actual_value}'")
+  else()
+    set("${hash_is_good}" TRUE PARENT_SCOPE)
+  endif()
+endfunction()
+
+function(sleep_before_download attempt)
+  if(attempt EQUAL 0)
+    return()
+  endif()
+
+  if(attempt EQUAL 1)
+    message(STATUS "Retrying...")
+    return()
+  endif()
+
+  set(sleep_seconds 0)
+
+  if(attempt EQUAL 2)
+    set(sleep_seconds 5)
+  elseif(attempt EQUAL 3)
+    set(sleep_seconds 5)
+  elseif(attempt EQUAL 4)
+    set(sleep_seconds 15)
+  elseif(attempt EQUAL 5)
+    set(sleep_seconds 60)
+  elseif(attempt EQUAL 6)
+    set(sleep_seconds 90)
+  elseif(attempt EQUAL 7)
+    set(sleep_seconds 300)
+  else()
+    set(sleep_seconds 1200)
+  endif()
+
+  message(STATUS "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ...")
+
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep "${sleep_seconds}")
+endfunction()
+
+if("@LOCAL@" STREQUAL "")
+  message(FATAL_ERROR "LOCAL can't be empty")
+endif()
+
+if("@REMOTE@" STREQUAL "")
+  message(FATAL_ERROR "REMOTE can't be empty")
+endif()
+
+if(EXISTS "@LOCAL@")
+  check_file_hash(has_hash hash_is_good)
+  if(has_hash)
+    if(hash_is_good)
+      message(STATUS "File already exists and hash match (skip download):
+  file='@LOCAL@'
+  @ALGO@='@EXPECT_VALUE@'"
+      )
+      return()
+    else()
+      message(STATUS "File already exists but hash mismatch. Removing...")
+      file(REMOVE "@LOCAL@")
+    endif()
+  else()
+    message(STATUS "File already exists but no hash specified (use URL_HASH):
+  file='@LOCAL@'
+Old file will be removed and new file downloaded from URL."
+    )
+    file(REMOVE "@LOCAL@")
+  endif()
+endif()
+
+set(retry_number 5)
+
+foreach(i RANGE ${retry_number})
+  sleep_before_download(${i})
+
+  message(STATUS "downloading...
+       src='@REMOTE@'
+       dst='@LOCAL@'
+       timeout='@TIMEOUT_MSG@'")
+
+  @TLS_VERIFY_CODE@
+  @TLS_CAINFO_CODE@
+
+  file(
+      DOWNLOAD
+      "@REMOTE@" "@LOCAL@"
+      @SHOW_PROGRESS@
+      @TIMEOUT_ARGS@
+      STATUS status
+      LOG log
+  )
+
+  list(GET status 0 status_code)
+  list(GET status 1 status_string)
+
+  if(status_code EQUAL 0)
+    check_file_hash(has_hash hash_is_good)
+    if(has_hash AND NOT hash_is_good)
+      message(STATUS "Hash mismatch, removing...")
+      file(REMOVE "@LOCAL@")
+    else()
+      message(STATUS "Downloading... done")
+      return()
+    endif()
+  else()
+    message("error: downloading '@REMOTE@' failed
+  status_code: ${status_code}
+  status_string: ${status_string}
+  log:
+  --- LOG BEGIN ---
+  ${log}
+  --- LOG END ---"
+    )
+  endif()
+endforeach()
+
+message(FATAL_ERROR "Downloading failed")
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index a24d355..861566d 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -867,16 +867,11 @@ function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout no_p
   endif()
 
   if("${hash}" MATCHES "${_ep_hash_regex}")
-    string(CONCAT hash_check
-      "if(EXISTS \"${LOCAL}\")\n"
-      "  file(\"${CMAKE_MATCH_1}\" \"${LOCAL}\" hash_value)\n"
-      "  if(\"x\${hash_value}\" STREQUAL \"x${CMAKE_MATCH_2}\")\n"
-      "    return()\n"
-      "  endif()\n"
-      "endif()\n"
-      )
+    set(ALGO "${CMAKE_MATCH_1}")
+    set(EXPECT_VALUE "${CMAKE_MATCH_2}")
   else()
-    set(hash_check "")
+    set(ALGO "")
+    set(EXPECT_VALUE "")
   endif()
 
   set(TLS_VERIFY_CODE "")
@@ -904,41 +899,23 @@ function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout no_p
     set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")")
   endif()
 
-  file(WRITE ${script_filename}
-"${hash_check}message(STATUS \"downloading...
-     src='${REMOTE}'
-     dst='${LOCAL}'
-     timeout='${TIMEOUT_MSG}'\")
-
-${TLS_VERIFY_CODE}
-${TLS_CAINFO_CODE}
-
-file(DOWNLOAD
-  \"${REMOTE}\"
-  \"${LOCAL}\"
-  ${SHOW_PROGRESS}
-  ${TIMEOUT_ARGS}
-  STATUS status
-  LOG log)
-
-list(GET status 0 status_code)
-list(GET status 1 status_string)
-
-if(NOT status_code EQUAL 0)
-  message(FATAL_ERROR \"error: downloading '${REMOTE}' failed
-  status_code: \${status_code}
-  status_string: \${status_string}
-  log: \${log}
-\")
-endif()
-
-message(STATUS \"downloading... done\")
-"
-)
-
+  # Used variables:
+  # * TLS_VERIFY_CODE
+  # * TLS_CAINFO_CODE
+  # * ALGO
+  # * EXPECT_VALUE
+  # * REMOTE
+  # * LOCAL
+  # * SHOW_PROGRESS
+  # * TIMEOUT_ARGS
+  # * TIMEOUT_MSG
+  configure_file(
+      "${_ExternalProject_SELF_DIR}/ExternalProject-download.cmake.in"
+      "${script_filename}"
+      @ONLY
+  )
 endfunction()
 
-
 function(_ep_write_verifyfile_script script_filename LOCAL hash)
   if("${hash}" MATCHES "${_ep_hash_regex}")
     set(ALGO "${CMAKE_MATCH_1}")
-- 
1.9.1

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to