From b0281f9248c6063386f7cfddb5982050a3930ba4 Mon Sep 17 00:00:00 2001 From: Jan Kubalek Date: Sun, 6 Jul 2025 22:35:26 +0200 Subject: [PATCH 1/3] Add NORMILIZE_GIT_URI functionality --- FindCMUTIL.cmake | 1 + README.md | 12 +- system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake | 179 ++++++++++++++++++ test/CMakeLists.txt | 1 + test/NORMALIZE_GIT_URI/CMakeLists.txt | 121 ++++++++++++ test/NORMALIZE_GIT_URI/fail/CMakeLists.txt | 12 ++ .../fail/invalid_http_uri/CMakeLists.txt | 16 ++ .../fail/invalid_ssh_uri/CMakeLists.txt | 16 ++ .../fail/invalid_target_type/CMakeLists.txt | 16 ++ 9 files changed, 369 insertions(+), 5 deletions(-) create mode 100644 system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake create mode 100644 test/NORMALIZE_GIT_URI/CMakeLists.txt create mode 100644 test/NORMALIZE_GIT_URI/fail/CMakeLists.txt create mode 100644 test/NORMALIZE_GIT_URI/fail/invalid_http_uri/CMakeLists.txt create mode 100644 test/NORMALIZE_GIT_URI/fail/invalid_ssh_uri/CMakeLists.txt create mode 100644 test/NORMALIZE_GIT_URI/fail/invalid_target_type/CMakeLists.txt diff --git a/FindCMUTIL.cmake b/FindCMUTIL.cmake index 8ef1653..f8ead78 100644 --- a/FindCMUTIL.cmake +++ b/FindCMUTIL.cmake @@ -18,4 +18,5 @@ INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_TRAIT.cmake) INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_PROPERTY_FILE.cmake) INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_VERSION.cmake) INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_PLATFORM_STRING.cmake) +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake) diff --git a/README.md b/README.md index 5ee9c71..d041aaf 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Provide mixed functionality for other CMake-lib components List of functionality +- [CMUTIL_NORMALIZE_GIT_URI.cmake] - normalize Git URIs between SSH and HTTP formats - [CMUTIL_PROPERTY_FILE.cmake] - read properties in form "=" from a file - [CMUTIL_TRAIT.cmake] - ensure that the given traits are met - [CMUTIL_VERSION.cmake] - version manipulation @@ -21,8 +22,9 @@ Project is licensed under [MIT](LICENSE) -[CMUTIL_PROPERTY_FILE.cmake]: ./system_modules/CMUTIL_PROPERTY_FILE.cmake -[CMUTIL_VERSION.cmake]: ./system_modules/CMUTIL_VERSION.cmake -[CMUTIL_TRAIT.cmake]: ./system_modules/CMUTIL_TRAIT.cmake -[CMLIB]: https://github.com/cmakelib/cmakelib -[buildbadge_github]: https://github.com/cmakelib/cmakelib-component-util/workflows/Tests/badge.svg +[CMUTIL_NORMALIZE_GIT_URI.cmake]: ./system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake +[CMUTIL_PROPERTY_FILE.cmake]: ./system_modules/CMUTIL_PROPERTY_FILE.cmake +[CMUTIL_VERSION.cmake]: ./system_modules/CMUTIL_VERSION.cmake +[CMUTIL_TRAIT.cmake]: ./system_modules/CMUTIL_TRAIT.cmake +[CMLIB]: https://github.com/cmakelib/cmakelib +[buildbadge_github]: https://github.com/cmakelib/cmakelib-component-util/workflows/Tests/badge.svg diff --git a/system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake b/system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake new file mode 100644 index 0000000..ffda2cb --- /dev/null +++ b/system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake @@ -0,0 +1,179 @@ +## Main +# +# Normalize Git URI to HTTP or SSH format compatible with +# all major Git hosting services like Github, Gitlab, Bitbucket, etc. +# +# [Definition] +# Git URIs can be in two main formats: +# SSH format: git@hostname:path/to/repo.git +# HTTP format: https://hostname/path/to/repo.git +# +# This module provides functionality to convert between these formats +# while preserving all path information and handling edge cases like +# port numbers and repositories without .git extension. +# + +IF(DEFINED CMUTIL_NORMALIZE_GIT_URI_MODULE) + RETURN() +ENDIF() +SET(CMUTIL_NORMALIZE_GIT_URI_MODULE 1) + +FIND_PACKAGE(CMLIB) + + + +## +# Normalize Git URI to specified target format (SSH or HTTP). +# +# Converts Git URIs between SSH and HTTP formats: +# SSH format: git@hostname:path/to/repo.git +# HTTP format: https://hostname/path/to/repo.git +# +# If the input URI is already in the target format, it is returned unchanged. +# Supports complex paths, custom domains, port numbers, and repositories +# without .git extension. +# +# ( +# URI +# TARGET_TYPE +# OUTPUT_VAR +# ) +FUNCTION(CMUTIL_NORMALIZE_GIT_URI) + CMLIB_PARSE_ARGUMENTS( + ONE_VALUE + URI + TARGET_TYPE + OUTPUT_VAR + REQUIRED + URI + TARGET_TYPE + OUTPUT_VAR + P_ARGN ${ARGN} + ) + + SET(output_value) + IF(__TARGET_TYPE STREQUAL "SSH") + _CMUTIL_NORMALIZE_GIT_URI_SSH( + URI "${__URI}" + OUTPUT_VAR _var + ) + SET(output_value "${_var}") + ELSEIF(__TARGET_TYPE STREQUAL "HTTP") + _CMUTIL_NORMALIZE_GIT_URI_HTTP( + URI "${__URI}" + OUTPUT_VAR _var + ) + SET(output_value "${_var}") + ELSE() + MESSAGE(FATAL_ERROR "Invalid TARGET_TYPE '${__TARGET_TYPE}'") + ENDIF() + + SET(${__OUTPUT_VAR} "${output_value}" PARENT_SCOPE) +ENDFUNCTION() + + + +## Helper +# +# Converts HTTP(S) Git URIs to SSH format. +# If URI is already in SSH format, returns it unchanged. +# +# Transformation examples: +# https://github.com/user/repo.git --> git@github.com:user/repo.git +# https://gitlab.com/user/repo.git --> git@gitlab.com:user/repo.git +# git@gitlab.com:user/repo.git --> git@gitlab.com:user/repo.git (unchanged) +# +# ( +# URI +# OUTPUT_VAR +# ) +# +FUNCTION(_CMUTIL_NORMALIZE_GIT_URI_SSH) + CMLIB_PARSE_ARGUMENTS( + ONE_VALUE + URI + OUTPUT_VAR + REQUIRED + URI + OUTPUT_VAR + P_ARGN ${ARGN} + ) + + SET(uri "${__URI}") + + STRING(REGEX MATCH "^git@.*" git_ssh_uri "${uri}") + IF(git_ssh_uri) + SET(${__OUTPUT_VAR} "${uri}" PARENT_SCOPE) + RETURN() + ENDIF() + + STRING(REGEX MATCH "^https?://" git_http_uri "${uri}") + IF(NOT git_http_uri) + MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid HTTP(S) or git@ Git URI") + ENDIF() + + STRING(REGEX MATCH "^https?://([^/]+)/(.+)$" http_match "${uri}") + IF(NOT http_match) + MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid HTTP(S) or git@ Git URI") + ENDIF() + + STRING(REGEX REPLACE "^https?://([^/]+)/(.+)$" "\\1" hostname "${uri}") + STRING(REGEX REPLACE "^https?://([^/]+)/(.+)$" "\\2" path "${uri}") + + SET(ssh_uri "git@${hostname}:${path}") + SET(${__OUTPUT_VAR} "${ssh_uri}" PARENT_SCOPE) +ENDFUNCTION() + + + +## Helper +# +# Converts SSH Git URIs to HTTPS format. +# If URI is already in HTTP(S) format, returns it unchanged. +# +# Transformation examples: +# git@github.com:user/repo.git --> https://github.com/user/repo.git +# git@gitlab.com:user/repo.git --> https://gitlab.com/user/repo.git +# https://github.com/user/repo.git --> https://github.com/user/repo.git (unchanged) +# +# ( +# URI +# OUTPUT_VAR +# ) +# +FUNCTION(_CMUTIL_NORMALIZE_GIT_URI_HTTP) + CMLIB_PARSE_ARGUMENTS( + ONE_VALUE + URI + OUTPUT_VAR + REQUIRED + URI + OUTPUT_VAR + P_ARGN ${ARGN} + ) + + SET(uri "${__URI}") + + STRING(REGEX MATCH "^https?://" git_http_uri "${uri}") + IF(git_http_uri) + SET(${__OUTPUT_VAR} "${uri}" PARENT_SCOPE) + RETURN() + ENDIF() + + STRING(REGEX MATCH "^git@.*" git_ssh_uri "${uri}") + IF(NOT git_ssh_uri) + MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid git@ or HTTP(S) Git URI") + ENDIF() + + STRING(REGEX MATCH "^git@([^:]+):(.+)$" ssh_match "${uri}") + IF(NOT ssh_match) + MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid git@ or HTTP(S) Git URI") + ENDIF() + + STRING(REGEX REPLACE "^git@([^:]+):(.+)$" "\\1" hostname "${uri}") + STRING(REGEX REPLACE "^git@([^:]+):(.+)$" "\\2" path "${uri}") + + SET(https_uri "https://${hostname}/${path}") + SET(${__OUTPUT_VAR} "${https_uri}" PARENT_SCOPE) +ENDFUNCTION() + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bd211bb..7328f3c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,3 +9,4 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/TEST.cmake") TEST_RUN("PROPERTY_FILE/") TEST_RUN("TRAIT/") TEST_RUN("VERSION/") +TEST_RUN("NORMALIZE_GIT_URI/") diff --git a/test/NORMALIZE_GIT_URI/CMakeLists.txt b/test/NORMALIZE_GIT_URI/CMakeLists.txt new file mode 100644 index 0000000..07c94e4 --- /dev/null +++ b/test/NORMALIZE_GIT_URI/CMakeLists.txt @@ -0,0 +1,121 @@ +IF(NOT DEFINED CMAKE_SCRIPT_MODE_FILE) + CMAKE_MINIMUM_REQUIRED(VERSION 3.18) + PROJECT(CMUTIL_NORMALIZE_GIT_URI_TEST) +ENDIF() + +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../") + +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/../TEST.cmake") + +FIND_PACKAGE(CMUTIL) + + + +FUNCTION(TEST_SSH_TARGET_TYPE) + CMUTIL_NORMALIZE_GIT_URI( + URI "https://github.com/username/repository.git" + TARGET_TYPE "SSH" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "git@github.com:username/repository.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "https://gitlab.com/user/repo.git" + TARGET_TYPE "SSH" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "git@gitlab.com:user/repo.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "http://example.com/path/to/repo.git" + TARGET_TYPE "SSH" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "git@example.com:path/to/repo.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "git@github.com:user/repo.git" + TARGET_TYPE "SSH" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "git@github.com:user/repo.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "https://gitlab.example.com/group/subgroup/project.git" + TARGET_TYPE "SSH" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "git@gitlab.example.com:group/subgroup/project.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "https://github.com/user/repo" + TARGET_TYPE "SSH" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "git@github.com:user/repo") + + CMUTIL_NORMALIZE_GIT_URI( + URI "https://git.example.com:8080/user/repo.git" + TARGET_TYPE "SSH" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "git@git.example.com:8080:user/repo.git") +ENDFUNCTION() + + + +FUNCTION(TEST_HTTP_TARGET_TYPE) + CMUTIL_NORMALIZE_GIT_URI( + URI "git@github.com:username/repository.git" + TARGET_TYPE "HTTP" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "https://github.com/username/repository.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "git@gitlab.com:user/repo.git" + TARGET_TYPE "HTTP" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "https://gitlab.com/user/repo.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "git@example.com:path/to/repo.git" + TARGET_TYPE "HTTP" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "https://example.com/path/to/repo.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "https://github.com/user/repo.git" + TARGET_TYPE "HTTP" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "https://github.com/user/repo.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "http://example.com/user/repo.git" + TARGET_TYPE "HTTP" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "http://example.com/user/repo.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "git@gitlab.example.com:group/subgroup/project.git" + TARGET_TYPE "HTTP" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "https://gitlab.example.com/group/subgroup/project.git") + + CMUTIL_NORMALIZE_GIT_URI( + URI "git@github.com:user/repo" + TARGET_TYPE "HTTP" + OUTPUT_VAR result + ) + TEST_VAR_EQUALS_LITERAL(result "https://github.com/user/repo") +ENDFUNCTION() + +TEST_SSH_TARGET_TYPE() +TEST_HTTP_TARGET_TYPE() + +TEST_RUN("fail/") diff --git a/test/NORMALIZE_GIT_URI/fail/CMakeLists.txt b/test/NORMALIZE_GIT_URI/fail/CMakeLists.txt new file mode 100644 index 0000000..7c513cd --- /dev/null +++ b/test/NORMALIZE_GIT_URI/fail/CMakeLists.txt @@ -0,0 +1,12 @@ +IF(NOT DEFINED CMAKE_SCRIPT_MODE_FILE) + CMAKE_MINIMUM_REQUIRED(VERSION 3.18) + PROJECT(CMUTIL_NORMALIZE_GIT_URI_FAIL_TEST) +ENDIF() + +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../") + +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/../../TEST.cmake") + +TEST_INVALID_CMAKE_RUN("invalid_target_type/" "Invalid TARGET_TYPE") +TEST_INVALID_CMAKE_RUN("invalid_http_uri/" "is not a valid HTTP\\(S\\) or git@ Git URI") +TEST_INVALID_CMAKE_RUN("invalid_ssh_uri/" "is not a valid git@ or HTTP\\(S\\) Git URI") diff --git a/test/NORMALIZE_GIT_URI/fail/invalid_http_uri/CMakeLists.txt b/test/NORMALIZE_GIT_URI/fail/invalid_http_uri/CMakeLists.txt new file mode 100644 index 0000000..c7022d0 --- /dev/null +++ b/test/NORMALIZE_GIT_URI/fail/invalid_http_uri/CMakeLists.txt @@ -0,0 +1,16 @@ +IF(NOT DEFINED CMAKE_SCRIPT_MODE_FILE) + CMAKE_MINIMUM_REQUIRED(VERSION 3.18) + PROJECT(CMUTIL_NORMALIZE_GIT_URI_INVALID_HTTP_URI_TEST) +ENDIF() + +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../../") + +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/../../../TEST.cmake") + +FIND_PACKAGE(CMUTIL) + +CMUTIL_NORMALIZE_GIT_URI( + URI "ftp://example.com/repo.git" + TARGET_TYPE "SSH" + OUTPUT_VAR result +) diff --git a/test/NORMALIZE_GIT_URI/fail/invalid_ssh_uri/CMakeLists.txt b/test/NORMALIZE_GIT_URI/fail/invalid_ssh_uri/CMakeLists.txt new file mode 100644 index 0000000..5043aa5 --- /dev/null +++ b/test/NORMALIZE_GIT_URI/fail/invalid_ssh_uri/CMakeLists.txt @@ -0,0 +1,16 @@ +IF(NOT DEFINED CMAKE_SCRIPT_MODE_FILE) + CMAKE_MINIMUM_REQUIRED(VERSION 3.18) + PROJECT(CMUTIL_NORMALIZE_GIT_URI_INVALID_SSH_URI_TEST) +ENDIF() + +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../../") + +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/../../../TEST.cmake") + +FIND_PACKAGE(CMUTIL) + +CMUTIL_NORMALIZE_GIT_URI( + URI "git@example.com" + TARGET_TYPE "HTTP" + OUTPUT_VAR result +) diff --git a/test/NORMALIZE_GIT_URI/fail/invalid_target_type/CMakeLists.txt b/test/NORMALIZE_GIT_URI/fail/invalid_target_type/CMakeLists.txt new file mode 100644 index 0000000..9f0ecb9 --- /dev/null +++ b/test/NORMALIZE_GIT_URI/fail/invalid_target_type/CMakeLists.txt @@ -0,0 +1,16 @@ +IF(NOT DEFINED CMAKE_SCRIPT_MODE_FILE) + CMAKE_MINIMUM_REQUIRED(VERSION 3.18) + PROJECT(CMUTIL_NORMALIZE_GIT_URI_INVALID_TARGET_TYPE_TEST) +ENDIF() + +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../../") + +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/../../../TEST.cmake") + +FIND_PACKAGE(CMUTIL) + +CMUTIL_NORMALIZE_GIT_URI( + URI "https://github.com/user/repo.git" + TARGET_TYPE "INVALID" + OUTPUT_VAR result +) From b26184599c6a9567b49495041e0d5c9bf93aa64e Mon Sep 17 00:00:00 2001 From: Jan Kubalek Date: Tue, 15 Jul 2025 20:42:58 +0200 Subject: [PATCH 2/3] CI/CD - update set of used Images --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a7f8175..c1fddf7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,10 +16,12 @@ jobs: image: [ "test_debian:bullseye", "test_debian:bookworm", + "test_debian:trixie", "test_ubuntu:2004", "test_ubuntu:2204", "test_ubuntu:2404", - "test_fedora:41" + "test_fedora:41", + "test_fedora:42" ] cmdopt: [ "-P ./CMakeLists.txt", "." ] runs-on: ubuntu-latest From 389f02031f2e12277aae895f1222f7894485c0b4 Mon Sep 17 00:00:00 2001 From: Jan Kubalek Date: Tue, 15 Jul 2025 23:26:15 +0200 Subject: [PATCH 3/3] CI/CD - update checkout to v4 --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c1fddf7..5b73b16 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,7 @@ jobs: container: image: ghcr.io/cmakelib/${{ matrix.image }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Init CMakelib run: | git clone "https://github.com/cmakelib/cmakelib.git" @@ -42,7 +42,7 @@ jobs: cmdopt: [ "-P ./CMakeLists.txt", "." ] runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Init CMakelib run: | git clone "https://github.com/cmakelib/cmakelib.git" @@ -58,7 +58,7 @@ jobs: cmdopt: [ "-P ./CMakeLists.txt", "." ] runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Init CMakelib run: | git clone "https://github.com/cmakelib/cmakelib.git"