mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-01 03:11:08 -06:00
Commit 0aea435aa1 (ExternalProject: Provide choice of
git update strategies, 2020-02-12) added the git update
strategies, but the CHECKOUT strategy was not handling
remote refs correctly. The local ref would be checked out
instead and no warning or error would have been emitted.
The test that should have caught this was also malformed
and did not actually move the local master branch as intended.
236 lines
8.3 KiB
CMake
236 lines
8.3 KiB
CMake
# Set the ExternalProject GIT_TAG to desired_tag, and make sure the
|
|
# resulting checked out version is resulting_sha and rebuild.
|
|
# This check's the correct behavior of the ExternalProject UPDATE_COMMAND.
|
|
# Also verify that a fetch only occurs when fetch_expected is 1.
|
|
macro(check_a_tag desired_tag resulting_sha fetch_expected update_strategy)
|
|
message( STATUS "Checking ExternalProjectUpdate to tag: ${desired_tag}" )
|
|
|
|
# Remove the FETCH_HEAD file, so we can check if it gets replaced with a 'git
|
|
# fetch'.
|
|
set( FETCH_HEAD_file ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT/.git/FETCH_HEAD )
|
|
file( REMOVE ${FETCH_HEAD_file} )
|
|
|
|
# Give ourselves a marker in the output. It is difficult to tell where we
|
|
# are up to without this
|
|
message(STATUS "===> check_a_tag ${desired_tag} ${resulting_sha} ${fetch_expected} ${update_strategy}")
|
|
|
|
# Configure
|
|
execute_process(COMMAND ${CMAKE_COMMAND}
|
|
-G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}"
|
|
-A "${CMAKE_GENERATOR_PLATFORM}"
|
|
-DTEST_GIT_TAG:STRING=${desired_tag}
|
|
-DCMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY:STRING=${update_strategy}
|
|
${ExternalProjectUpdate_SOURCE_DIR}
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not configure the project.")
|
|
endif()
|
|
|
|
# Build
|
|
execute_process(COMMAND ${CMAKE_COMMAND}
|
|
--build ${ExternalProjectUpdate_BINARY_DIR}
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not build the project.")
|
|
endif()
|
|
|
|
# Check the resulting SHA
|
|
execute_process(COMMAND ${GIT_EXECUTABLE}
|
|
rev-list --max-count=1 HEAD
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
|
|
RESULT_VARIABLE error_code
|
|
OUTPUT_VARIABLE tag_sha
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not check the sha.")
|
|
endif()
|
|
|
|
if(NOT (${tag_sha} STREQUAL ${resulting_sha}))
|
|
message(FATAL_ERROR "UPDATE_COMMAND produced
|
|
${tag_sha}
|
|
when
|
|
${resulting_sha}
|
|
was expected."
|
|
)
|
|
endif()
|
|
|
|
if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected})
|
|
message( FATAL_ERROR "Fetch did NOT occur when it was expected.")
|
|
endif()
|
|
if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected})
|
|
message( FATAL_ERROR "Fetch DID occur when it was not expected.")
|
|
endif()
|
|
|
|
message( STATUS "Checking ExternalProjectUpdate to tag: ${desired_tag} (disconnected)" )
|
|
|
|
# Remove the FETCH_HEAD file, so we can check if it gets replaced with a 'git
|
|
# fetch'.
|
|
set( FETCH_HEAD_file ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT/.git/FETCH_HEAD )
|
|
file( REMOVE ${FETCH_HEAD_file} )
|
|
|
|
# Check initial SHA
|
|
execute_process(COMMAND ${GIT_EXECUTABLE}
|
|
rev-list --max-count=1 HEAD
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT
|
|
RESULT_VARIABLE error_code
|
|
OUTPUT_VARIABLE initial_sha
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
|
|
# Configure
|
|
execute_process(COMMAND ${CMAKE_COMMAND}
|
|
-G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}"
|
|
-A "${CMAKE_GENERATOR_PLATFORM}"
|
|
-DTEST_GIT_TAG:STRING=${desired_tag}
|
|
${ExternalProjectUpdate_SOURCE_DIR}
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not configure the project.")
|
|
endif()
|
|
|
|
# Build
|
|
execute_process(COMMAND ${CMAKE_COMMAND}
|
|
--build ${ExternalProjectUpdate_BINARY_DIR}
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not build the project.")
|
|
endif()
|
|
|
|
if( EXISTS ${FETCH_HEAD_file} )
|
|
message( FATAL_ERROR "Fetch occurred when it was not expected.")
|
|
endif()
|
|
|
|
# Check the resulting SHA
|
|
execute_process(COMMAND ${GIT_EXECUTABLE}
|
|
rev-list --max-count=1 HEAD
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT
|
|
RESULT_VARIABLE error_code
|
|
OUTPUT_VARIABLE tag_sha
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not check the sha.")
|
|
endif()
|
|
|
|
if(NOT (${tag_sha} STREQUAL ${initial_sha}))
|
|
message(FATAL_ERROR "Update occurred when it was not expected.")
|
|
endif()
|
|
|
|
# Update
|
|
execute_process(COMMAND ${CMAKE_COMMAND}
|
|
--build ${ExternalProjectUpdate_BINARY_DIR}
|
|
--target TutorialStep2-GIT-update
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not build the project.")
|
|
endif()
|
|
|
|
# Check the resulting SHA
|
|
execute_process(COMMAND ${GIT_EXECUTABLE}
|
|
rev-list --max-count=1 HEAD
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT
|
|
RESULT_VARIABLE error_code
|
|
OUTPUT_VARIABLE tag_sha
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not check the sha.")
|
|
endif()
|
|
|
|
if(NOT (${tag_sha} STREQUAL ${resulting_sha}))
|
|
message(FATAL_ERROR "UPDATE_COMMAND produced
|
|
${tag_sha}
|
|
when
|
|
${resulting_sha}
|
|
was expected."
|
|
)
|
|
endif()
|
|
|
|
if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected})
|
|
message( FATAL_ERROR "Fetch did NOT occur when it was expected.")
|
|
endif()
|
|
if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected})
|
|
message( FATAL_ERROR "Fetch DID occur when it was not expected.")
|
|
endif()
|
|
endmacro()
|
|
|
|
find_package(Git)
|
|
set(do_git_tests 0)
|
|
if(GIT_EXECUTABLE)
|
|
set(do_git_tests 1)
|
|
|
|
execute_process(
|
|
COMMAND "${GIT_EXECUTABLE}" --version
|
|
OUTPUT_VARIABLE ov
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
string(REGEX REPLACE "^git version (.+)$" "\\1" git_version "${ov}")
|
|
message(STATUS "git_version='${git_version}'")
|
|
|
|
if(git_version VERSION_LESS 1.6.5)
|
|
message(STATUS "No ExternalProject git tests with git client less than version 1.6.5")
|
|
set(do_git_tests 0)
|
|
endif()
|
|
endif()
|
|
|
|
# When re-running tests locally, this ensures we always start afresh
|
|
file(REMOVE_RECURSE ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals)
|
|
|
|
if(do_git_tests)
|
|
check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
|
|
check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 1 REBASE)
|
|
# With the Git UPDATE_COMMAND performance patch, this will not required a
|
|
# '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 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
|
|
# This is a remote symbolic ref, so it will always trigger a 'git fetch'
|
|
check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
|
|
|
|
foreach(strategy IN ITEMS CHECKOUT REBASE_CHECKOUT)
|
|
# Move local master back, then apply a change that will cause a conflict
|
|
# during rebase
|
|
execute_process(COMMAND ${GIT_EXECUTABLE} checkout master
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not reset local master back to tag1.")
|
|
endif()
|
|
execute_process(COMMAND ${GIT_EXECUTABLE} reset --hard tag1
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not reset local master back to tag1.")
|
|
endif()
|
|
|
|
set(cmlFile ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT/CMakeLists.txt)
|
|
file(READ ${cmlFile} contents)
|
|
string(REPLACE "find TutorialConfig.h" "find TutorialConfig.h (conflict here)"
|
|
conflictingContent "${contents}"
|
|
)
|
|
file(WRITE ${cmlFile} "${conflictingContent}")
|
|
execute_process(COMMAND ${GIT_EXECUTABLE} commit -a -m "This should cause a conflict"
|
|
WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
|
|
RESULT_VARIABLE error_code
|
|
)
|
|
if(error_code)
|
|
message(FATAL_ERROR "Could not commit conflicting change.")
|
|
endif()
|
|
# This should discard our commit but leave behind an annotated tag
|
|
check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 ${strategy})
|
|
endforeach()
|
|
|
|
endif()
|