| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- 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()
|