|
|
@@ -0,0 +1,182 @@
|
|
|
+cmake_policy(VERSION 3.25)
|
|
|
+
|
|
|
+# Determine the remote URL of the project containing the working_directory.
|
|
|
+# This will leave output_variable unset if the URL can't be determined.
|
|
|
+function(_ep_get_git_remote_url output_variable working_directory)
|
|
|
+ set("${output_variable}" "" PARENT_SCOPE)
|
|
|
+
|
|
|
+ find_package(Git QUIET REQUIRED)
|
|
|
+
|
|
|
+ execute_process(
|
|
|
+ COMMAND ${GIT_EXECUTABLE} symbolic-ref --short HEAD
|
|
|
+ WORKING_DIRECTORY "${working_directory}"
|
|
|
+ OUTPUT_VARIABLE git_symbolic_ref
|
|
|
+ OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
|
+ ERROR_QUIET
|
|
|
+ )
|
|
|
+
|
|
|
+ if(NOT git_symbolic_ref STREQUAL "")
|
|
|
+ # We are potentially on a branch. See if that branch is associated with
|
|
|
+ # an upstream remote (might be just a local one or not a branch at all).
|
|
|
+ execute_process(
|
|
|
+ COMMAND ${GIT_EXECUTABLE} config branch.${git_symbolic_ref}.remote
|
|
|
+ WORKING_DIRECTORY "${working_directory}"
|
|
|
+ OUTPUT_VARIABLE git_remote_name
|
|
|
+ OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
|
+ ERROR_QUIET
|
|
|
+ )
|
|
|
+ endif()
|
|
|
+
|
|
|
+ if(NOT git_remote_name)
|
|
|
+ # Can't select a remote based on a branch. If there's only one remote,
|
|
|
+ # or we have multiple remotes but one is called "origin", choose that.
|
|
|
+ execute_process(
|
|
|
+ COMMAND ${GIT_EXECUTABLE} remote
|
|
|
+ WORKING_DIRECTORY "${working_directory}"
|
|
|
+ OUTPUT_VARIABLE git_remote_list
|
|
|
+ OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
|
+ ERROR_QUIET
|
|
|
+ )
|
|
|
+ string(REPLACE "\n" ";" git_remote_list "${git_remote_list}")
|
|
|
+ list(LENGTH git_remote_list git_remote_list_length)
|
|
|
+
|
|
|
+ if(git_remote_list_length EQUAL 0)
|
|
|
+ message(FATAL_ERROR "Git remote not found in parent project.")
|
|
|
+ elseif(git_remote_list_length EQUAL 1)
|
|
|
+ list(GET git_remote_list 0 git_remote_name)
|
|
|
+ else()
|
|
|
+ set(base_warning_msg "Multiple git remotes found for parent project")
|
|
|
+ if("origin" IN_LIST git_remote_list)
|
|
|
+ message(WARNING "${base_warning_msg}, defaulting to origin.")
|
|
|
+ set(git_remote_name "origin")
|
|
|
+ else()
|
|
|
+ message(FATAL_ERROR "${base_warning_msg}, none of which are origin.")
|
|
|
+ endif()
|
|
|
+ endif()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ if(GIT_VERSION VERSION_LESS 1.7.5)
|
|
|
+ set(_git_remote_url_cmd_args config remote.${git_remote_name}.url)
|
|
|
+ elseif(GIT_VERSION VERSION_LESS 2.7)
|
|
|
+ set(_git_remote_url_cmd_args ls-remote --get-url ${git_remote_name})
|
|
|
+ else()
|
|
|
+ set(_git_remote_url_cmd_args remote get-url ${git_remote_name})
|
|
|
+ endif()
|
|
|
+
|
|
|
+ execute_process(
|
|
|
+ COMMAND ${GIT_EXECUTABLE} ${_git_remote_url_cmd_args}
|
|
|
+ WORKING_DIRECTORY "${working_directory}"
|
|
|
+ OUTPUT_VARIABLE git_remote_url
|
|
|
+ OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
|
+ COMMAND_ERROR_IS_FATAL LAST
|
|
|
+ ENCODING UTF-8 # Needed to handle non-ascii characters in local paths
|
|
|
+ )
|
|
|
+
|
|
|
+ set("${output_variable}" "${git_remote_url}" PARENT_SCOPE)
|
|
|
+endfunction()
|
|
|
+
|
|
|
+function(_ep_is_relative_git_remote output_variable remote_url)
|
|
|
+ if(remote_url MATCHES "^\\.\\./")
|
|
|
+ set("${output_variable}" TRUE PARENT_SCOPE)
|
|
|
+ else()
|
|
|
+ set("${output_variable}" FALSE PARENT_SCOPE)
|
|
|
+ endif()
|
|
|
+endfunction()
|
|
|
+
|
|
|
+# Return an absolute remote URL given an existing remote URL and relative path.
|
|
|
+# The output_variable will be set to an empty string if an absolute URL
|
|
|
+# could not be computed (no error message is output).
|
|
|
+function(_ep_resolve_relative_git_remote
|
|
|
+ output_variable
|
|
|
+ parent_remote_url
|
|
|
+ relative_remote_url
|
|
|
+)
|
|
|
+ set("${output_variable}" "" PARENT_SCOPE)
|
|
|
+
|
|
|
+ if(parent_remote_url STREQUAL "")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ string(REGEX MATCH
|
|
|
+ "^(([A-Za-z0-9][A-Za-z0-9+.-]*)://)?(([^/@]+)@)?(\\[[A-Za-z0-9:]+\\]|[^/:]+)?([/:]/?)(.+(\\.git)?/?)$"
|
|
|
+ git_remote_url_components
|
|
|
+ "${parent_remote_url}"
|
|
|
+ )
|
|
|
+
|
|
|
+ set(protocol "${CMAKE_MATCH_1}")
|
|
|
+ set(auth "${CMAKE_MATCH_3}")
|
|
|
+ set(host "${CMAKE_MATCH_5}")
|
|
|
+ set(separator "${CMAKE_MATCH_6}")
|
|
|
+ set(path "${CMAKE_MATCH_7}")
|
|
|
+
|
|
|
+ string(REPLACE "/" ";" remote_path_components "${path}")
|
|
|
+ string(REPLACE "/" ";" relative_path_components "${relative_remote_url}")
|
|
|
+
|
|
|
+ foreach(relative_path_component IN LISTS relative_path_components)
|
|
|
+ if(NOT relative_path_component STREQUAL "..")
|
|
|
+ break()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ list(LENGTH remote_path_components remote_path_component_count)
|
|
|
+
|
|
|
+ if(remote_path_component_count LESS 1)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ list(POP_BACK remote_path_components)
|
|
|
+ list(POP_FRONT relative_path_components)
|
|
|
+ endforeach()
|
|
|
+
|
|
|
+ list(APPEND final_path_components ${remote_path_components} ${relative_path_components})
|
|
|
+ list(JOIN final_path_components "/" path)
|
|
|
+
|
|
|
+ set("${output_variable}" "${protocol}${auth}${host}${separator}${path}" PARENT_SCOPE)
|
|
|
+endfunction()
|
|
|
+
|
|
|
+# The output_variable will be set to the original git_repository if it
|
|
|
+# could not be resolved (no error message is output). The original value is
|
|
|
+# also returned if it doesn't need to be resolved.
|
|
|
+function(_ep_resolve_git_remote
|
|
|
+ output_variable
|
|
|
+ git_repository
|
|
|
+ cmp0150
|
|
|
+ cmp0150_old_base_dir
|
|
|
+)
|
|
|
+ if(git_repository STREQUAL "")
|
|
|
+ set("${output_variable}" "" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ _ep_is_relative_git_remote(_git_repository_is_relative "${git_repository}")
|
|
|
+
|
|
|
+ if(NOT _git_repository_is_relative)
|
|
|
+ set("${output_variable}" "${git_repository}" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ if(cmp0150 STREQUAL "NEW")
|
|
|
+ _ep_get_git_remote_url(_parent_git_remote_url "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
|
+ _ep_resolve_relative_git_remote(_resolved_git_remote_url "${_parent_git_remote_url}" "${git_repository}")
|
|
|
+
|
|
|
+ if(_resolved_git_remote_url STREQUAL "")
|
|
|
+ message(FATAL_ERROR
|
|
|
+ "Failed to resolve relative git remote URL:\n"
|
|
|
+ " Relative URL: ${git_repository}\n"
|
|
|
+ " Parent URL: ${_parent_git_remote_url}"
|
|
|
+ )
|
|
|
+ endif()
|
|
|
+ set("${output_variable}" "${_resolved_git_remote_url}" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ elseif(cmp0150 STREQUAL "")
|
|
|
+ cmake_policy(GET_WARNING CMP0150 _cmp0150_warning)
|
|
|
+ message(AUTHOR_WARNING
|
|
|
+ "${_cmp0150_warning}\n"
|
|
|
+ "A relative GIT_REPOSITORY path was detected. "
|
|
|
+ "This will be interpreted as a local path to where the project is being cloned. "
|
|
|
+ "Set GIT_REPOSITORY to an absolute path or set policy CMP0150 to NEW to avoid "
|
|
|
+ "this warning."
|
|
|
+ )
|
|
|
+ endif()
|
|
|
+
|
|
|
+ set("${output_variable}" "${cmp0150_old_base_dir}/${git_repository}" PARENT_SCOPE)
|
|
|
+endfunction()
|