From 5e941a545bf5882ddf101cad383dc815fb651f26 Mon Sep 17 00:00:00 2001
From: Craig Scott <craig.scott@crascit.com>
Date: Sun, 9 May 2021 12:33:16 +1000
Subject: [PATCH] ExternalProject: Ensure git fetch if updating to hash we
 don't have yet

In ac6a4d4884 (ExternalProject: Improve robustness of update step,
2020-10-17), the method used to check whether we already have a
commit or not was changed from using git rev-list to git rev-parse.
The new logic assumed rev-parse would output nothing if given a commit
hash it didn't know about, but it simply prints the hash again without
raising an error in this scenario. Amend that logic by adding ^{commit} to
the ref to ensure we do get an error if that ref is not currently known.

Fixes: #22166
---
 Modules/ExternalProject-gitupdate.cmake.in    |  2 +-
 ...{FetchGitTags.cmake => FetchGitRefs.cmake} | 21 +++++++++++++++++--
 .../CMakeLists.txt                            |  0
 .../ExternalProject/RunCMakeTest.cmake        |  2 +-
 4 files changed, 21 insertions(+), 4 deletions(-)
 rename Tests/RunCMake/ExternalProject/{FetchGitTags.cmake => FetchGitRefs.cmake} (73%)
 rename Tests/RunCMake/ExternalProject/{FetchGitTags => FetchGitRefs}/CMakeLists.txt (100%)

diff --git a/Modules/ExternalProject-gitupdate.cmake.in b/Modules/ExternalProject-gitupdate.cmake.in
index 7033918056..461e323540 100644
--- a/Modules/ExternalProject-gitupdate.cmake.in
+++ b/Modules/ExternalProject-gitupdate.cmake.in
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.5)
 
 function(get_hash_for_ref ref out_var err_var)
   execute_process(
-    COMMAND "@git_EXECUTABLE@" rev-parse "${ref}"
+    COMMAND "@git_EXECUTABLE@" rev-parse "${ref}^{commit}"
     WORKING_DIRECTORY "@work_dir@"
     RESULT_VARIABLE error_code
     OUTPUT_VARIABLE ref_hash
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags.cmake b/Tests/RunCMake/ExternalProject/FetchGitRefs.cmake
similarity index 73%
rename from Tests/RunCMake/ExternalProject/FetchGitTags.cmake
rename to Tests/RunCMake/ExternalProject/FetchGitRefs.cmake
index 37d1b40889..a00908b39d 100644
--- a/Tests/RunCMake/ExternalProject/FetchGitTags.cmake
+++ b/Tests/RunCMake/ExternalProject/FetchGitRefs.cmake
@@ -11,7 +11,7 @@ file(MAKE_DIRECTORY ${srcDir})
 file(GLOB entries ${srcRepo}/*)
 file(REMOVE_RECURSE ${entries} ${binDir})
 file(TOUCH ${srcRepo}/firstFile.txt)
-configure_file(${CMAKE_CURRENT_LIST_DIR}/FetchGitTags/CMakeLists.txt
+configure_file(${CMAKE_CURRENT_LIST_DIR}/FetchGitRefs/CMakeLists.txt
     ${srcDir}/CMakeLists.txt COPYONLY)
 
 function(execGitCommand)
@@ -63,5 +63,22 @@ execGitCommand(commit -m "Second file")
 execGitCommand(tag -a -m "Adding tag" tag_of_interest)
 execGitCommand(reset --hard HEAD~1)
 
-message(STATUS "Second configure-and-build")
+message(STATUS "Configure-and-build, update to tag")
 configureAndBuild(tag_of_interest)
+
+# Do the same, but this time for a commit hash
+file(TOUCH ${srcRepo}/thirdFile.txt)
+execGitCommand(add thirdFile.txt)
+execGitCommand(commit -m "Third file")
+execGitCommand(tag -a -m "Adding another tag" check_for_hash)
+execGitCommand(reset --hard HEAD~1)
+execute_process(
+  WORKING_DIRECTORY ${srcRepo}
+  COMMAND ${GIT_EXECUTABLE} rev-parse check_for_hash
+  COMMAND_ERROR_IS_FATAL ANY
+  OUTPUT_VARIABLE commit_hash
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+message(STATUS "Configure-and-build, update to commit hash ${commit_hash}")
+configureAndBuild(${commit_hash})
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt b/Tests/RunCMake/ExternalProject/FetchGitRefs/CMakeLists.txt
similarity index 100%
rename from Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt
rename to Tests/RunCMake/ExternalProject/FetchGitRefs/CMakeLists.txt
diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
index 3205dd54cc..a4244e364d 100644
--- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
@@ -185,6 +185,6 @@ if(GIT_EXECUTABLE)
   # Note that there appear to be differences in where git writes its output to
   # on some platforms. It may go to stdout or stderr, so force it to be merged.
   set(RunCMake_TEST_OUTPUT_MERGE TRUE)
-  run_cmake(FetchGitTags)
+  run_cmake(FetchGitRefs)
   set(RunCMake_TEST_OUTPUT_MERGE FALSE)
 endif()
-- 
GitLab