You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
6.0 KiB
183 lines
6.0 KiB
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()
|