| # 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_tsX is 1. | |
| macro(check_a_tag | |
| desired_tag | |
| resulting_sha | |
| fetch_expected_ts1 # TutorialStep1-GIT | |
| fetch_expected_ts2 # TutorialStep2-GIT | |
| 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_ts1} ${fetch_expected_ts2} " | |
| "${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_ts1}) | |
| message( FATAL_ERROR "Fetch did NOT occur when it was expected.") | |
| endif() | |
| if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected_ts1}) | |
| 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_ts2}) | |
| message( FATAL_ERROR "Fetch did NOT occur when it was expected.") | |
| endif() | |
| if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected_ts2}) | |
| 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) | |
| message(STATUS "GIT_VERSION_STRING='${GIT_VERSION_STRING}'") | |
| if("${GIT_VERSION_STRING}" 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 b5f0fc2d442b72dd29e655c329af0062e1f8d129 1 1 REBASE) | |
| check_a_tag(tag1 4209914b424925d6f1b558d79454d60967d4b0f3 1 0 REBASE) | |
| # With the Git UPDATE_COMMAND performance patch, this will not require a | |
| # 'git fetch' | |
| check_a_tag(tag1 4209914b424925d6f1b558d79454d60967d4b0f3 0 0 REBASE) | |
| check_a_tag(tag2 ae72641040f1c9512f152d08afb6909f0498f958 1 0 REBASE) | |
| check_a_tag(4209914b42 4209914b424925d6f1b558d79454d60967d4b0f3 0 0 REBASE) | |
| check_a_tag(origin/master b5f0fc2d442b72dd29e655c329af0062e1f8d129 1 1 REBASE) | |
| # This is a remote symbolic ref, so it will always trigger a 'git fetch' | |
| check_a_tag(origin/master b5f0fc2d442b72dd29e655c329af0062e1f8d129 1 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 b5f0fc2d442b72dd29e655c329af0062e1f8d129 1 1 ${strategy}) | |
| endforeach() | |
| # This file matches a .gitignore rule that the last commit defines. We can't | |
| # directly check that updates don't stash ignored contents because the stash | |
| # and pop are both done within the update step. We don't have an opportunity | |
| # to check things in between, but we can at least check that the update step | |
| # doesn't choke on it. | |
| set(ignoredFile ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT/ignored_item) | |
| file(TOUCH ${ignoredFile}) | |
| check_a_tag(origin/master b5f0fc2d442b72dd29e655c329af0062e1f8d129 1 1 REBASE) | |
| if(NOT EXISTS ${ignoredFile}) | |
| message(FATAL_ERROR "Ignored file is missing") | |
| endif() | |
| endif() |