ExternalProjectUpdateTest.cmake 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. # Set the ExternalProject GIT_TAG to desired_tag, and make sure the
  2. # resulting checked out version is resulting_sha and rebuild.
  3. # This check's the correct behavior of the ExternalProject UPDATE_COMMAND.
  4. # Also verify that a fetch only occurs when fetch_expected is 1.
  5. macro(check_a_tag desired_tag resulting_sha fetch_expected update_strategy)
  6. message( STATUS "Checking ExternalProjectUpdate to tag: ${desired_tag}" )
  7. # Remove the FETCH_HEAD file, so we can check if it gets replaced with a 'git
  8. # fetch'.
  9. set( FETCH_HEAD_file ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT/.git/FETCH_HEAD )
  10. file( REMOVE ${FETCH_HEAD_file} )
  11. # Give ourselves a marker in the output. It is difficult to tell where we
  12. # are up to without this
  13. message(STATUS "===> check_a_tag ${desired_tag} ${resulting_sha} ${fetch_expected} ${update_strategy}")
  14. # Configure
  15. execute_process(COMMAND ${CMAKE_COMMAND}
  16. -G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}"
  17. -A "${CMAKE_GENERATOR_PLATFORM}"
  18. -DTEST_GIT_TAG:STRING=${desired_tag}
  19. -DCMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY:STRING=${update_strategy}
  20. ${ExternalProjectUpdate_SOURCE_DIR}
  21. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}
  22. RESULT_VARIABLE error_code
  23. )
  24. if(error_code)
  25. message(FATAL_ERROR "Could not configure the project.")
  26. endif()
  27. # Build
  28. execute_process(COMMAND ${CMAKE_COMMAND}
  29. --build ${ExternalProjectUpdate_BINARY_DIR}
  30. RESULT_VARIABLE error_code
  31. )
  32. if(error_code)
  33. message(FATAL_ERROR "Could not build the project.")
  34. endif()
  35. # Check the resulting SHA
  36. execute_process(COMMAND ${GIT_EXECUTABLE}
  37. rev-list --max-count=1 HEAD
  38. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
  39. RESULT_VARIABLE error_code
  40. OUTPUT_VARIABLE tag_sha
  41. OUTPUT_STRIP_TRAILING_WHITESPACE
  42. )
  43. if(error_code)
  44. message(FATAL_ERROR "Could not check the sha.")
  45. endif()
  46. if(NOT (${tag_sha} STREQUAL ${resulting_sha}))
  47. message(FATAL_ERROR "UPDATE_COMMAND produced
  48. ${tag_sha}
  49. when
  50. ${resulting_sha}
  51. was expected."
  52. )
  53. endif()
  54. if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected})
  55. message( FATAL_ERROR "Fetch did NOT occur when it was expected.")
  56. endif()
  57. if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected})
  58. message( FATAL_ERROR "Fetch DID occur when it was not expected.")
  59. endif()
  60. message( STATUS "Checking ExternalProjectUpdate to tag: ${desired_tag} (disconnected)" )
  61. # Remove the FETCH_HEAD file, so we can check if it gets replaced with a 'git
  62. # fetch'.
  63. set( FETCH_HEAD_file ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT/.git/FETCH_HEAD )
  64. file( REMOVE ${FETCH_HEAD_file} )
  65. # Check initial SHA
  66. execute_process(COMMAND ${GIT_EXECUTABLE}
  67. rev-list --max-count=1 HEAD
  68. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT
  69. RESULT_VARIABLE error_code
  70. OUTPUT_VARIABLE initial_sha
  71. OUTPUT_STRIP_TRAILING_WHITESPACE
  72. )
  73. # Configure
  74. execute_process(COMMAND ${CMAKE_COMMAND}
  75. -G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}"
  76. -A "${CMAKE_GENERATOR_PLATFORM}"
  77. -DTEST_GIT_TAG:STRING=${desired_tag}
  78. ${ExternalProjectUpdate_SOURCE_DIR}
  79. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}
  80. RESULT_VARIABLE error_code
  81. )
  82. if(error_code)
  83. message(FATAL_ERROR "Could not configure the project.")
  84. endif()
  85. # Build
  86. execute_process(COMMAND ${CMAKE_COMMAND}
  87. --build ${ExternalProjectUpdate_BINARY_DIR}
  88. RESULT_VARIABLE error_code
  89. )
  90. if(error_code)
  91. message(FATAL_ERROR "Could not build the project.")
  92. endif()
  93. if( EXISTS ${FETCH_HEAD_file} )
  94. message( FATAL_ERROR "Fetch occurred when it was not expected.")
  95. endif()
  96. # Check the resulting SHA
  97. execute_process(COMMAND ${GIT_EXECUTABLE}
  98. rev-list --max-count=1 HEAD
  99. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT
  100. RESULT_VARIABLE error_code
  101. OUTPUT_VARIABLE tag_sha
  102. OUTPUT_STRIP_TRAILING_WHITESPACE
  103. )
  104. if(error_code)
  105. message(FATAL_ERROR "Could not check the sha.")
  106. endif()
  107. if(NOT (${tag_sha} STREQUAL ${initial_sha}))
  108. message(FATAL_ERROR "Update occurred when it was not expected.")
  109. endif()
  110. # Update
  111. execute_process(COMMAND ${CMAKE_COMMAND}
  112. --build ${ExternalProjectUpdate_BINARY_DIR}
  113. --target TutorialStep2-GIT-update
  114. RESULT_VARIABLE error_code
  115. )
  116. if(error_code)
  117. message(FATAL_ERROR "Could not build the project.")
  118. endif()
  119. # Check the resulting SHA
  120. execute_process(COMMAND ${GIT_EXECUTABLE}
  121. rev-list --max-count=1 HEAD
  122. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep2-GIT
  123. RESULT_VARIABLE error_code
  124. OUTPUT_VARIABLE tag_sha
  125. OUTPUT_STRIP_TRAILING_WHITESPACE
  126. )
  127. if(error_code)
  128. message(FATAL_ERROR "Could not check the sha.")
  129. endif()
  130. if(NOT (${tag_sha} STREQUAL ${resulting_sha}))
  131. message(FATAL_ERROR "UPDATE_COMMAND produced
  132. ${tag_sha}
  133. when
  134. ${resulting_sha}
  135. was expected."
  136. )
  137. endif()
  138. if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected})
  139. message( FATAL_ERROR "Fetch did NOT occur when it was expected.")
  140. endif()
  141. if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected})
  142. message( FATAL_ERROR "Fetch DID occur when it was not expected.")
  143. endif()
  144. endmacro()
  145. find_package(Git)
  146. set(do_git_tests 0)
  147. if(GIT_EXECUTABLE)
  148. set(do_git_tests 1)
  149. execute_process(
  150. COMMAND "${GIT_EXECUTABLE}" --version
  151. OUTPUT_VARIABLE ov
  152. OUTPUT_STRIP_TRAILING_WHITESPACE
  153. )
  154. string(REGEX REPLACE "^git version (.+)$" "\\1" git_version "${ov}")
  155. message(STATUS "git_version='${git_version}'")
  156. if(git_version VERSION_LESS 1.6.5)
  157. message(STATUS "No ExternalProject git tests with git client less than version 1.6.5")
  158. set(do_git_tests 0)
  159. endif()
  160. endif()
  161. # When re-running tests locally, this ensures we always start afresh
  162. file(REMOVE_RECURSE ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals)
  163. if(do_git_tests)
  164. check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
  165. check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 1 REBASE)
  166. # With the Git UPDATE_COMMAND performance patch, this will not required a
  167. # 'git fetch'
  168. check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
  169. check_a_tag(tag2 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
  170. check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 1 REBASE)
  171. check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
  172. check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
  173. # This is a remote symbolic ref, so it will always trigger a 'git fetch'
  174. check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
  175. foreach(strategy IN ITEMS CHECKOUT REBASE_CHECKOUT)
  176. # Move local master back, then apply a change that will cause a conflict
  177. # during rebase
  178. execute_process(COMMAND ${GIT_EXECUTABLE} checkout master
  179. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
  180. RESULT_VARIABLE error_code
  181. )
  182. if(error_code)
  183. message(FATAL_ERROR "Could not reset local master back to tag1.")
  184. endif()
  185. execute_process(COMMAND ${GIT_EXECUTABLE} reset --hard tag1
  186. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
  187. RESULT_VARIABLE error_code
  188. )
  189. if(error_code)
  190. message(FATAL_ERROR "Could not reset local master back to tag1.")
  191. endif()
  192. set(cmlFile ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT/CMakeLists.txt)
  193. file(READ ${cmlFile} contents)
  194. string(REPLACE "find TutorialConfig.h" "find TutorialConfig.h (conflict here)"
  195. conflictingContent "${contents}"
  196. )
  197. file(WRITE ${cmlFile} "${conflictingContent}")
  198. execute_process(COMMAND ${GIT_EXECUTABLE} commit -a -m "This should cause a conflict"
  199. WORKING_DIRECTORY ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT
  200. RESULT_VARIABLE error_code
  201. )
  202. if(error_code)
  203. message(FATAL_ERROR "Could not commit conflicting change.")
  204. endif()
  205. # This should discard our commit but leave behind an annotated tag
  206. check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 ${strategy})
  207. endforeach()
  208. endif()