Skip to content

Commit

Permalink
Various CheckSubmodules fixes (#3996)
Browse files Browse the repository at this point in the history
Various CheckSubmodules fixes
Closes #3992, #3993, #3994
  • Loading branch information
tresf authored Nov 21, 2017
1 parent 5e2c105 commit d634ed3
Showing 1 changed file with 59 additions and 13 deletions.
72 changes: 59 additions & 13 deletions cmake/modules/CheckSubmodules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.

# Files which confirm a successful clone
SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh")
SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh;.gitignore")

# Try and use the specified shallow clone on submodules, if supported
SET(DEPTH_VALUE 100)
Expand All @@ -29,11 +29,23 @@ SET(MAX_ATTEMPTS 2)
MESSAGE("\nValidating submodules...")
FILE(READ "${CMAKE_SOURCE_DIR}/.gitmodules" SUBMODULE_DATA)

# Force English locale
SET(LC_ALL_BACKUP "$ENV{LC_ALL}")
SET(LANG_BACKUP "$ENV{LANG}")
SET(ENV{LC_ALL} "C")
SET(ENV{LANG} "en_US")

# Assume alpha-numeric paths
STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST ${SUBMODULE_DATA})
STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_LIST ${SUBMODULE_DATA})

FOREACH(_part ${SUBMODULE_LIST})
STRING(REPLACE "path = " "" SUBMODULE_PATH ${_part})

LIST(FIND SUBMODULE_LIST ${_part} SUBMODULE_INDEX)
LIST(GET SUBMODULE_URL_LIST ${SUBMODULE_INDEX} _url)
STRING(REPLACE "url = " "" SUBMODULE_URL ${_url})

# Remove submodules from validation as specified in -DSKIP_SUBMODULES=foo;bar
SET(SKIP false)
IF(SKIP_SUBMODULES)
Expand All @@ -44,27 +56,41 @@ FOREACH(_part ${SUBMODULE_LIST})
ENDIF()
ENDFOREACH()
ENDIF()
LIST(REMOVE_ITEM SUBMODULE_LIST ${_part})
IF(NOT SKIP)
LIST(APPEND SUBMODULE_LIST ${SUBMODULE_PATH})
LIST(INSERT SUBMODULE_LIST ${SUBMODULE_INDEX} ${SUBMODULE_PATH})
LIST(INSERT SUBMODULE_URL_LIST ${SUBMODULE_INDEX} ${SUBMODULE_URL})
ENDIF()
LIST(REMOVE_ITEM SUBMODULE_LIST ${_part})
LIST(REMOVE_ITEM SUBMODULE_URL_LIST ${_url})
ENDFOREACH()

LIST(SORT SUBMODULE_LIST)

# Once called, status is stored in GIT_RESULT respectively.
# Note: Git likes to write to stderr. Don't assume stderr is error; Check GIT_RESULT instead.
MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT)
MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE)
FIND_PACKAGE(Git REQUIRED)
IF(${FORCE_DEINIT})
# Handle missing commits
SET(FORCE_REMOTE_FLAG "${FORCE_REMOTE}")
IF(FORCE_REMOTE_FLAG)
MESSAGE("-- Adding remote submodulefix to ${SUBMODULE_PATH}")
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} remote rm submodulefix
COMMAND ${GIT_EXECUTABLE} remote add submodulefix ${FORCE_REMOTE}
COMMAND ${GIT_EXECUTABLE} fetch submodulefix
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}
OUTPUT_QUIET ERROR_QUIET
)
# Recurse
GIT_SUBMODULE(${SUBMODULE_PATH} false false)
ELSEIF(${FORCE_DEINIT})
MESSAGE("-- Resetting ${SUBMODULE_PATH}")
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} submodule deinit -f ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET
)
# Recurse
GIT_SUBMODULE(${SUBMODULE_PATH} false)
GIT_SUBMODULE(${SUBMODULE_PATH} false false)
ELSE()
# Try to use the depth switch
SET(DEPTH_CMD "")
Expand All @@ -87,7 +113,8 @@ MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT)
ENDIF()
ENDMACRO()

SET(RETRY_PHRASES "Failed to recurse;unadvertised object;cannot create directory")
SET(MISSING_COMMIT_PHRASES "no such remote ref;reference is not a tree")
SET(RETRY_PHRASES "Failed to recurse;unadvertised object;cannot create directory;already exists;${MISSING_COMMIT_PHRASES}")

# Attempt to do lazy clone
FOREACH(_submodule ${SUBMODULE_LIST})
Expand All @@ -101,22 +128,36 @@ FOREACH(_submodule ${SUBMODULE_LIST})
IF(EXISTS "${CMAKE_SOURCE_DIR}/${_submodule}/${_crumb}")
SET(CRUMB_FOUND true)
MESSAGE("-- Found ${_submodule}/${_crumb}")
BREAK()
ENDIF()
ENDFOREACH()
IF(NOT CRUMB_FOUND)
GIT_SUBMODULE(${_submodule} false)
GIT_SUBMODULE(${_submodule} false false)

SET(COUNTED 0)
SET(COUNTING "")
# Handle edge-cases where submodule didn't clone properly or re-uses a non-empty directory
WHILE(NOT GIT_RESULT EQUAL 0 AND COUNTED LESS MAX_ATTEMPTS)
LIST(APPEND COUNTING "x")
LIST(LENGTH COUNTING COUNTED)

FOREACH(_phrase ${RETRY_PHRASES})
SET(MISSING_COMMIT false)
FOREACH(_phrase ${MISSING_COMMIT_PHRASES})
IF("${GIT_MESSAGE}" MATCHES "${_phrase}")
MESSAGE("-- Retrying ${_submodule} using 'deinit' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...")
SET(MISSING_COMMIT true)
BREAK()
ENDIF()
ENDFOREACH()
FOREACH(_phrase ${RETRY_PHRASES})
IF(${MISSING_COMMIT})
LIST(FIND SUBMODULE_LIST ${_submodule} SUBMODULE_INDEX)
LIST(GET SUBMODULE_URL_LIST ${SUBMODULE_INDEX} SUBMODULE_URL)
MESSAGE("-- Retrying ${_submodule} using 'remote add submodulefix' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...")

GIT_SUBMODULE(${_submodule} false "${SUBMODULE_URL}")
BREAK()
ELSEIF("${GIT_MESSAGE}" MATCHES "${_phrase}")
MESSAGE("-- Retrying ${_submodule} using 'deinit' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...")

# Shallow submodules were introduced in 1.8.4
# Shallow commits can fail to clone from non-default branches, only try once
IF(GIT_VERSION_STRING VERSION_GREATER "1.8.3" AND COUNTED LESS 2)
Expand All @@ -125,7 +166,8 @@ FOREACH(_submodule ${SUBMODULE_LIST})
UNSET(DEPTH_VALUE)
ENDIF()

GIT_SUBMODULE(${_submodule} true)
GIT_SUBMODULE(${_submodule} true false)
BREAK()
ENDIF()
ENDFOREACH()
ENDWHILE()
Expand All @@ -136,3 +178,7 @@ FOREACH(_submodule ${SUBMODULE_LIST})
ENDIF()
ENDFOREACH()
MESSAGE("-- Done validating submodules.\n")

# Reset locale
SET(ENV{LC_ALL} "${LC_ALL_BACKUP}")
SET(ENV{LANG} "${LANG_BACKUP}")

0 comments on commit d634ed3

Please sign in to comment.