ExternalProject: Only run 'git fetch' when required.

In the current default update step for Git under the ExternalProject_Add
command, a 'git fetch' is always performed, followed by a 'git checkout' and
'git submodule update --recursive'.  However, a 'git fetch' can be time
consuming and requires a network connection.

To save time, we look at the current checked out hash, and only perform the
fetch if required.  This is performed in a CMake script so we can handle
the conditional logic in a cross platform manner.
This commit is contained in:
Matt McCormick 2012-06-08 18:29:34 -04:00 committed by David Cole
parent d39bd3e6a8
commit d0758290e7
1 changed files with 65 additions and 5 deletions

View File

@ -402,6 +402,66 @@ endif()
endfunction()
function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_repository work_dir)
file(WRITE ${script_filename}
"if(\"${git_tag}\" STREQUAL \"\")
message(FATAL_ERROR \"Tag for git checkout should not be empty.\")
endif()
execute_process(
COMMAND \"${git_EXECUTABLE}\" rev-list --max-count=1 HEAD
WORKING_DIRECTORY \"${work_dir}\"
RESULT_VARIABLE error_code
OUTPUT_VARIABLE head_sha
)
if(error_code)
message(FATAL_ERROR \"Failed to get the hash for HEAD\")
endif()
# This will fail if the tag does not exist (it probably has not been fetched
# yet).
execute_process(
COMMAND \"${git_EXECUTABLE}\" rev-list --max-count=1 ${git_tag}
WORKING_DIRECTORY \"${work_dir}\"
RESULT_VARIABLE error_code
OUTPUT_VARIABLE tag_sha
)
# Is the hash checkout out that we want?
if(error_code OR NOT (\"\${tag_sha}\" STREQUAL \"\${head_sha}\"))
execute_process(
COMMAND \"${git_EXECUTABLE}\" fetch
WORKING_DIRECTORY \"${work_dir}\"
RESULT_VARIABLE error_code
)
if(error_code)
message(FATAL_ERROR \"Failed to fetch repository '${git_repository}'\")
endif()
execute_process(
COMMAND \"${git_EXECUTABLE}\" checkout ${git_tag}
WORKING_DIRECTORY \"${work_dir}\"
RESULT_VARIABLE error_code
)
if(error_code)
message(FATAL_ERROR \"Failed to checkout tag: '${git_tag}'\")
endif()
execute_process(
COMMAND \"${git_EXECUTABLE}\" submodule update --recursive
WORKING_DIRECTORY \"${work_dir}/${src_name}\"
RESULT_VARIABLE error_code
)
if(error_code)
message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\")
endif()
endif()
"
)
endfunction(_ep_write_gitupdate_script)
function(_ep_write_downloadfile_script script_filename remote local timeout hash tls_verify tls_cainfo)
if(timeout)
set(timeout_args TIMEOUT ${timeout})
@ -1354,7 +1414,7 @@ endfunction()
function(_ep_add_update_command name)
ExternalProject_Get_Property(${name} source_dir)
ExternalProject_Get_Property(${name} source_dir tmp_dir)
get_property(cmd_set TARGET ${name} PROPERTY _EP_UPDATE_COMMAND SET)
get_property(cmd TARGET ${name} PROPERTY _EP_UPDATE_COMMAND)
@ -1406,15 +1466,15 @@ function(_ep_add_update_command name)
message(FATAL_ERROR "error: could not find git for fetch of ${name}")
endif()
set(work_dir ${source_dir})
set(comment "Performing update step (git fetch) for '${name}'")
set(comment "Performing update step for '${name}'")
get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG)
if(NOT git_tag)
set(git_tag "master")
endif()
set(cmd ${GIT_EXECUTABLE} fetch
COMMAND ${GIT_EXECUTABLE} checkout ${git_tag}
COMMAND ${GIT_EXECUTABLE} submodule update --recursive
_ep_write_gitupdate_script(${tmp_dir}/${name}-gitupdate.cmake
${GIT_EXECUTABLE} ${git_tag} ${git_repository} ${work_dir}
)
set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake)
set(always 1)
elseif(hg_repository)
if(NOT HG_EXECUTABLE)