@@ -126,15 +126,18 @@ endfunction()
126126
127127Pull the given repository
128128
129- It will temporarily switch back to the previous branch if the head is detached for updating
129+ If ``TARGET_REVISION`` is given, the pull is skipped if the current revision is the same as the target revision.
130+
131+ It will temporarily switch back to the previous branch if the head is detached for updating.
130132
131133Input variables:
132134
133135- ``REPOSITORY_PATH``: The path to the repository
136+ - ``TARGET_REVISION``: if the current revision of the repository is the same as this given revision, the pull is skipped
134137
135138]]
136139function (git_pull )
137- set (oneValueArgs REPOSITORY_PATH)
140+ set (oneValueArgs REPOSITORY_PATH TARGET_REVISION )
138141 cmake_parse_arguments (_fun "" "${oneValueArgs} " "" ${ARGN} )
139142
140143 if ("${_fun_REPOSITORY_PATH} " STREQUAL "" )
@@ -144,14 +147,30 @@ function(git_pull)
144147 # store the current revision
145148 git_revision (REVISION REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " )
146149
150+ # skip the pull if the revision is the same
151+ if (NOT "${_fun_TARGET_REVISION} " STREQUAL "" AND "${REVISION} " STREQUAL "${_fun_TARGET_REVISION} " )
152+ message (STATUS "Skipping pull of ${_fun_REPOSITORY_PATH} because it's already at ${REVISION} " )
153+ return ()
154+ else ()
155+ # pull and restore it after the pull
156+ set (_fun_TARGET_REVISION "${REVISION} " )
157+ endif ()
158+
147159 git_switch_back (REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " )
148160
149161 message (STATUS "Updating ${_fun_REPOSITORY_PATH} " )
150162 find_program (GIT_EXECUTABLE "git" REQUIRED )
151- execute_process (COMMAND "${GIT_EXECUTABLE} " "pull" WORKING_DIRECTORY "${_fun_REPOSITORY_PATH} " )
163+
164+ # wait for lock before pulling
165+ git_wait (REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " )
166+
167+ execute_process (
168+ COMMAND "${GIT_EXECUTABLE} " "pull" WORKING_DIRECTORY "${_fun_REPOSITORY_PATH} "
169+ COMMAND_ERROR_IS_FATAL LAST
170+ )
152171
153172 # restore the revision
154- git_checkout (REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " REVISION "${REVISION } " )
173+ git_checkout (REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " REVISION "${_fun_TARGET_REVISION } " )
155174endfunction ()
156175
157176#[[ .rst:
@@ -192,6 +211,14 @@ function(git_checkout)
192211 message (FATAL_ERROR "REPOSITORY_PATH and REVISION are required" )
193212 endif ()
194213
214+ git_revision (REVISION REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " )
215+ if ("${REVISION} " STREQUAL "${_fun_REVISION} " )
216+ return ()
217+ endif ()
218+
219+ # wait for lock before checking out
220+ git_wait (REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " )
221+
195222 find_program (GIT_EXECUTABLE "git" REQUIRED )
196223 execute_process (
197224 COMMAND "${GIT_EXECUTABLE} " "-c" "advice.detachedHead=false" "checkout" "${_fun_REVISION} "
@@ -356,7 +383,7 @@ function(git_revision REVISION)
356383 COMMAND "${GIT_EXECUTABLE} " "rev-parse" "HEAD"
357384 OUTPUT_VARIABLE _git_revision
358385 WORKING_DIRECTORY "${_fun_REPOSITORY_PATH} "
359- OUTPUT_STRIP_TRAILING_WHITESPACE
386+ OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL LAST
360387 )
361388 set (${REVISION} ${_git_revision} PARENT_SCOPE )
362389endfunction ()
@@ -391,7 +418,7 @@ function(git_is_detached IS_DETACHED)
391418 COMMAND "${GIT_EXECUTABLE} " "rev-parse" "--abbrev-ref" "--symbolic-full-name" "HEAD"
392419 OUTPUT_VARIABLE _git_status
393420 WORKING_DIRECTORY "${_fun_REPOSITORY_PATH} "
394- OUTPUT_STRIP_TRAILING_WHITESPACE
421+ OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL LAST
395422 )
396423 if ("${_git_status} " STREQUAL "HEAD" )
397424 set (${IS_DETACHED} TRUE PARENT_SCOPE )
@@ -424,9 +451,23 @@ function(git_switch_back)
424451
425452 if (${IS_DETACHED} )
426453 message (STATUS "Switch back ${_fun_REPOSITORY_PATH} " )
454+
455+ # wait for lock before switching back
456+ git_wait (REPOSITORY_PATH "${_fun_REPOSITORY_PATH} " )
457+
427458 execute_process (
428459 COMMAND "${GIT_EXECUTABLE} " "switch" "-" WORKING_DIRECTORY "${_fun_REPOSITORY_PATH} "
460+ RESULT_VARIABLE _switch_back_result
429461 )
462+
463+ # if the switch back failed, try to checkout the previous branch
464+ if (NOT ${_switch_back_result} EQUAL 0)
465+ message (STATUS "Switch back failed. Trying to checkout previous branch" )
466+ execute_process (
467+ COMMAND "${GIT_EXECUTABLE} " "checkout" "-" WORKING_DIRECTORY "${_fun_REPOSITORY_PATH} "
468+ COMMAND_ERROR_IS_FATAL LAST
469+ )
470+ endif ()
430471 endif ()
431472endfunction ()
432473
@@ -457,20 +498,17 @@ function(git_wait)
457498
458499 set (counter 0)
459500
460- message (STATUS "Waiting for git lock file...[${counter} /${_fun_TIMEOUT_COUNTER} ]" )
461-
462501 # wait until .git/index is present (in case a parallel clone is running)
463502 while (NOT EXISTS "${_fun_REPOSITORY_PATH} /.git/index"
464503 OR EXISTS "${_fun_REPOSITORY_PATH} /.git/index.lock"
465504 )
466- execute_process (COMMAND ${CMAKE_COMMAND} -E sleep 0.5 )
505+ message (STATUS "Waiting for git lock file...[${counter} /${_fun_TIMEOUT_COUNTER} ]" )
506+ execute_process (COMMAND ${CMAKE_COMMAND} -E sleep 0.5 COMMAND_ERROR_IS_FATAL LAST )
467507
468508 math (EXPR counter "${counter} + 1" )
469509 if (${counter} GREATER ${_fun_TIMEOUT_COUNTER} )
470510 message (STATUS "Timeout waiting for git lock file. Continuing..." )
471511 return ()
472- else ()
473- message (STATUS "Waiting for git lock file...[${counter} /${_fun_TIMEOUT_COUNTER} ]" )
474512 endif ()
475513 endwhile ()
476514endfunction ()
0 commit comments