summaryrefslogtreecommitdiffstats
path: root/Tests
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@crascit.com>2020-10-17 10:16:22 (GMT)
committerBrad King <brad.king@kitware.com>2021-01-28 14:32:35 (GMT)
commitac6a4d488446cb1e906c4b55fd055547dacd55c4 (patch)
treeaaa082df07f18a01a53efbbc0ecb37efba25ada5 /Tests
parent17c4c8b92b63b8ce920dd7db38bab4a772990cce (diff)
downloadCMake-ac6a4d488446cb1e906c4b55fd055547dacd55c4.zip
CMake-ac6a4d488446cb1e906c4b55fd055547dacd55c4.tar.gz
CMake-ac6a4d488446cb1e906c4b55fd055547dacd55c4.tar.bz2
ExternalProject: Improve robustness of update step
Refactor the update logic to make it easier to follow. The following fixes/improvements are some consequences of this change: * Absorb a confusing git checkout failure message when the failure is allowed and we act on that failure appropriately. * Fix an unnecessary fetch in some scenarios when checking out a git hash we already have locally. * Stash and restore any local changes even when not rebasing. * Avoid unsafe rebasing where we are not on a branch that is already tracking the requested branch. * When fetching, use --tags --force to ensure we get all the tags and commits leading up to them regardless of whether the tags are on branches or not. Also update our local tags if they move on the remote. Fixes: #20677
Diffstat (limited to 'Tests')
-rw-r--r--Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake1
-rw-r--r--Tests/RunCMake/ExternalProject/FetchGitTags.cmake67
-rw-r--r--Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt15
-rw-r--r--Tests/RunCMake/ExternalProject/RunCMakeTest.cmake9
4 files changed, 91 insertions, 1 deletions
diff --git a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
index aaa05d7..394df87 100644
--- a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
+++ b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
@@ -185,7 +185,6 @@ if(do_git_tests)
# 'git fetch'
check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
check_a_tag(tag2 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
- check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 1 REBASE)
check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
# This is a remote symbolic ref, so it will always trigger a 'git fetch'
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags.cmake b/Tests/RunCMake/ExternalProject/FetchGitTags.cmake
new file mode 100644
index 0000000..37d1b40
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/FetchGitTags.cmake
@@ -0,0 +1,67 @@
+find_package(Git QUIET REQUIRED)
+
+include(ExternalProject)
+
+set(srcRepo ${CMAKE_CURRENT_BINARY_DIR}/srcRepo)
+set(srcDir ${CMAKE_CURRENT_BINARY_DIR}/src)
+set(binDir ${CMAKE_CURRENT_BINARY_DIR}/build)
+file(MAKE_DIRECTORY ${srcRepo})
+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
+ ${srcDir}/CMakeLists.txt COPYONLY)
+
+function(execGitCommand)
+ execute_process(
+ WORKING_DIRECTORY ${srcRepo}
+ COMMAND ${GIT_EXECUTABLE} ${ARGN}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+endfunction()
+
+function(configureAndBuild tag)
+ execute_process(COMMAND ${CMAKE_COMMAND}
+ -G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}"
+ -A "${CMAKE_GENERATOR_PLATFORM}"
+ -D repoDir:PATH=${srcRepo}
+ -D gitTag:STRING=${tag}
+ -B ${binDir}
+ -S ${srcDir}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+
+ execute_process(COMMAND ${CMAKE_COMMAND} --build ${binDir} --target fetcher
+ WORKING_DIRECTORY ${binDir}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+endfunction()
+
+# Setup a fresh source repo with a predictable default branch across all
+# git versions
+execGitCommand(-c init.defaultBranch=master init)
+execGitCommand(config --add user.email "testauthor@cmake.org")
+execGitCommand(config --add user.name testauthor)
+
+# Create the initial repo structure
+execGitCommand(add firstFile.txt)
+execGitCommand(commit -m "First file")
+
+message(STATUS "First configure-and-build")
+configureAndBuild(master)
+
+# Create a tagged commit that is not on any branch. With git 2.20 or later,
+# this commit won't be fetched without the --tags option.
+file(TOUCH ${srcRepo}/secondFile.txt)
+execGitCommand(add secondFile.txt)
+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")
+configureAndBuild(tag_of_interest)
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt b/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt
new file mode 100644
index 0000000..d9a380c
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.19)
+project(FetchTags LANGUAGES NONE)
+
+include(ExternalProject)
+
+# repoDir and gitTag are expected to be set as cache variables
+
+ExternalProject_Add(fetcher
+ GIT_REPOSITORY ${repoDir}
+ GIT_TAG ${gitTag}
+ GIT_REMOTE_UPDATE_STRATEGY CHECKOUT
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+)
diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
index 22b8d24..976655a 100644
--- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
@@ -181,3 +181,12 @@ endfunction()
if(NOT RunCMake_GENERATOR MATCHES "Visual Studio 9 ")
__ep_test_CONFIGURE_HANDLED_BY_BUILD()
endif()
+
+find_package(Git QUIET)
+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)
+ set(RunCMake_TEST_OUTPUT_MERGE FALSE)
+endif()