Skip to content

Commit 77e2ba9

Browse files
authored
Merge pull request #3 from cmakelib/jan_kubalek/normalize_gituri
Add NORMILIZE_GIT_URI functionality, update CI/CD and TYPOs in README
2 parents fcd1387 + 389f020 commit 77e2ba9

File tree

10 files changed

+375
-9
lines changed

10 files changed

+375
-9
lines changed

.github/workflows/tests.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ jobs:
1616
image: [
1717
"test_debian:bullseye",
1818
"test_debian:bookworm",
19+
"test_debian:trixie",
1920
"test_ubuntu:2004",
2021
"test_ubuntu:2204",
2122
"test_ubuntu:2404",
22-
"test_fedora:41"
23+
"test_fedora:41",
24+
"test_fedora:42"
2325
]
2426
cmdopt: [ "-P ./CMakeLists.txt", "." ]
2527
runs-on: ubuntu-latest
2628
container:
2729
image: ghcr.io/cmakelib/${{ matrix.image }}
2830
steps:
29-
- uses: actions/checkout@v2
31+
- uses: actions/checkout@v4
3032
- name: Init CMakelib
3133
run: |
3234
git clone "https://github.com/cmakelib/cmakelib.git"
@@ -40,7 +42,7 @@ jobs:
4042
cmdopt: [ "-P ./CMakeLists.txt", "." ]
4143
runs-on: windows-latest
4244
steps:
43-
- uses: actions/checkout@v2
45+
- uses: actions/checkout@v4
4446
- name: Init CMakelib
4547
run: |
4648
git clone "https://github.com/cmakelib/cmakelib.git"
@@ -56,7 +58,7 @@ jobs:
5658
cmdopt: [ "-P ./CMakeLists.txt", "." ]
5759
runs-on: macos-latest
5860
steps:
59-
- uses: actions/checkout@v2
61+
- uses: actions/checkout@v4
6062
- name: Init CMakelib
6163
run: |
6264
git clone "https://github.com/cmakelib/cmakelib.git"

FindCMUTIL.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_TRAIT.cmake)
1818
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_PROPERTY_FILE.cmake)
1919
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_VERSION.cmake)
2020
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_PLATFORM_STRING.cmake)
21+
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake)
2122

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Provide mixed functionality for other CMake-lib components
77

88
List of functionality
99

10+
- [CMUTIL_NORMALIZE_GIT_URI.cmake] - normalize Git URIs between SSH and HTTP formats
1011
- [CMUTIL_PROPERTY_FILE.cmake] - read properties in form "<key>=<value>" from a file
1112
- [CMUTIL_TRAIT.cmake] - ensure that the given traits are met
1213
- [CMUTIL_VERSION.cmake] - version manipulation
@@ -21,8 +22,9 @@ Project is licensed under [MIT](LICENSE)
2122

2223

2324

24-
[CMUTIL_PROPERTY_FILE.cmake]: ./system_modules/CMUTIL_PROPERTY_FILE.cmake
25-
[CMUTIL_VERSION.cmake]: ./system_modules/CMUTIL_VERSION.cmake
26-
[CMUTIL_TRAIT.cmake]: ./system_modules/CMUTIL_TRAIT.cmake
27-
[CMLIB]: https://github.com/cmakelib/cmakelib
28-
[buildbadge_github]: https://github.com/cmakelib/cmakelib-component-util/workflows/Tests/badge.svg
25+
[CMUTIL_NORMALIZE_GIT_URI.cmake]: ./system_modules/CMUTIL_NORMALIZE_GIT_URI.cmake
26+
[CMUTIL_PROPERTY_FILE.cmake]: ./system_modules/CMUTIL_PROPERTY_FILE.cmake
27+
[CMUTIL_VERSION.cmake]: ./system_modules/CMUTIL_VERSION.cmake
28+
[CMUTIL_TRAIT.cmake]: ./system_modules/CMUTIL_TRAIT.cmake
29+
[CMLIB]: https://github.com/cmakelib/cmakelib
30+
[buildbadge_github]: https://github.com/cmakelib/cmakelib-component-util/workflows/Tests/badge.svg
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
## Main
2+
#
3+
# Normalize Git URI to HTTP or SSH format compatible with
4+
# all major Git hosting services like Github, Gitlab, Bitbucket, etc.
5+
#
6+
# [Definition]
7+
# Git URIs can be in two main formats:
8+
# SSH format: git@hostname:path/to/repo.git
9+
# HTTP format: https://hostname/path/to/repo.git
10+
#
11+
# This module provides functionality to convert between these formats
12+
# while preserving all path information and handling edge cases like
13+
# port numbers and repositories without .git extension.
14+
#
15+
16+
IF(DEFINED CMUTIL_NORMALIZE_GIT_URI_MODULE)
17+
RETURN()
18+
ENDIF()
19+
SET(CMUTIL_NORMALIZE_GIT_URI_MODULE 1)
20+
21+
FIND_PACKAGE(CMLIB)
22+
23+
24+
25+
##
26+
# Normalize Git URI to specified target format (SSH or HTTP).
27+
#
28+
# Converts Git URIs between SSH and HTTP formats:
29+
# SSH format: git@hostname:path/to/repo.git
30+
# HTTP format: https://hostname/path/to/repo.git
31+
#
32+
# If the input URI is already in the target format, it is returned unchanged.
33+
# Supports complex paths, custom domains, port numbers, and repositories
34+
# without .git extension.
35+
#
36+
# <function>(
37+
# URI <git_uri>
38+
# TARGET_TYPE <SSH|HTTP>
39+
# OUTPUT_VAR <output_variable>
40+
# )
41+
FUNCTION(CMUTIL_NORMALIZE_GIT_URI)
42+
CMLIB_PARSE_ARGUMENTS(
43+
ONE_VALUE
44+
URI
45+
TARGET_TYPE
46+
OUTPUT_VAR
47+
REQUIRED
48+
URI
49+
TARGET_TYPE
50+
OUTPUT_VAR
51+
P_ARGN ${ARGN}
52+
)
53+
54+
SET(output_value)
55+
IF(__TARGET_TYPE STREQUAL "SSH")
56+
_CMUTIL_NORMALIZE_GIT_URI_SSH(
57+
URI "${__URI}"
58+
OUTPUT_VAR _var
59+
)
60+
SET(output_value "${_var}")
61+
ELSEIF(__TARGET_TYPE STREQUAL "HTTP")
62+
_CMUTIL_NORMALIZE_GIT_URI_HTTP(
63+
URI "${__URI}"
64+
OUTPUT_VAR _var
65+
)
66+
SET(output_value "${_var}")
67+
ELSE()
68+
MESSAGE(FATAL_ERROR "Invalid TARGET_TYPE '${__TARGET_TYPE}'")
69+
ENDIF()
70+
71+
SET(${__OUTPUT_VAR} "${output_value}" PARENT_SCOPE)
72+
ENDFUNCTION()
73+
74+
75+
76+
## Helper
77+
#
78+
# Converts HTTP(S) Git URIs to SSH format.
79+
# If URI is already in SSH format, returns it unchanged.
80+
#
81+
# Transformation examples:
82+
# https://github.com/user/repo.git --> git@github.com:user/repo.git
83+
# https://gitlab.com/user/repo.git --> git@gitlab.com:user/repo.git
84+
# git@gitlab.com:user/repo.git --> git@gitlab.com:user/repo.git (unchanged)
85+
#
86+
# <function>(
87+
# URI <uri>
88+
# OUTPUT_VAR <output_variable>
89+
# )
90+
#
91+
FUNCTION(_CMUTIL_NORMALIZE_GIT_URI_SSH)
92+
CMLIB_PARSE_ARGUMENTS(
93+
ONE_VALUE
94+
URI
95+
OUTPUT_VAR
96+
REQUIRED
97+
URI
98+
OUTPUT_VAR
99+
P_ARGN ${ARGN}
100+
)
101+
102+
SET(uri "${__URI}")
103+
104+
STRING(REGEX MATCH "^git@.*" git_ssh_uri "${uri}")
105+
IF(git_ssh_uri)
106+
SET(${__OUTPUT_VAR} "${uri}" PARENT_SCOPE)
107+
RETURN()
108+
ENDIF()
109+
110+
STRING(REGEX MATCH "^https?://" git_http_uri "${uri}")
111+
IF(NOT git_http_uri)
112+
MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid HTTP(S) or git@ Git URI")
113+
ENDIF()
114+
115+
STRING(REGEX MATCH "^https?://([^/]+)/(.+)$" http_match "${uri}")
116+
IF(NOT http_match)
117+
MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid HTTP(S) or git@ Git URI")
118+
ENDIF()
119+
120+
STRING(REGEX REPLACE "^https?://([^/]+)/(.+)$" "\\1" hostname "${uri}")
121+
STRING(REGEX REPLACE "^https?://([^/]+)/(.+)$" "\\2" path "${uri}")
122+
123+
SET(ssh_uri "git@${hostname}:${path}")
124+
SET(${__OUTPUT_VAR} "${ssh_uri}" PARENT_SCOPE)
125+
ENDFUNCTION()
126+
127+
128+
129+
## Helper
130+
#
131+
# Converts SSH Git URIs to HTTPS format.
132+
# If URI is already in HTTP(S) format, returns it unchanged.
133+
#
134+
# Transformation examples:
135+
# git@github.com:user/repo.git --> https://github.com/user/repo.git
136+
# git@gitlab.com:user/repo.git --> https://gitlab.com/user/repo.git
137+
# https://github.com/user/repo.git --> https://github.com/user/repo.git (unchanged)
138+
#
139+
# <function>(
140+
# URI <uri>
141+
# OUTPUT_VAR <output_variable>
142+
# )
143+
#
144+
FUNCTION(_CMUTIL_NORMALIZE_GIT_URI_HTTP)
145+
CMLIB_PARSE_ARGUMENTS(
146+
ONE_VALUE
147+
URI
148+
OUTPUT_VAR
149+
REQUIRED
150+
URI
151+
OUTPUT_VAR
152+
P_ARGN ${ARGN}
153+
)
154+
155+
SET(uri "${__URI}")
156+
157+
STRING(REGEX MATCH "^https?://" git_http_uri "${uri}")
158+
IF(git_http_uri)
159+
SET(${__OUTPUT_VAR} "${uri}" PARENT_SCOPE)
160+
RETURN()
161+
ENDIF()
162+
163+
STRING(REGEX MATCH "^git@.*" git_ssh_uri "${uri}")
164+
IF(NOT git_ssh_uri)
165+
MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid git@ or HTTP(S) Git URI")
166+
ENDIF()
167+
168+
STRING(REGEX MATCH "^git@([^:]+):(.+)$" ssh_match "${uri}")
169+
IF(NOT ssh_match)
170+
MESSAGE(FATAL_ERROR "URI '${uri}' is not a valid git@ or HTTP(S) Git URI")
171+
ENDIF()
172+
173+
STRING(REGEX REPLACE "^git@([^:]+):(.+)$" "\\1" hostname "${uri}")
174+
STRING(REGEX REPLACE "^git@([^:]+):(.+)$" "\\2" path "${uri}")
175+
176+
SET(https_uri "https://${hostname}/${path}")
177+
SET(${__OUTPUT_VAR} "${https_uri}" PARENT_SCOPE)
178+
ENDFUNCTION()
179+

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/TEST.cmake")
99
TEST_RUN("PROPERTY_FILE/")
1010
TEST_RUN("TRAIT/")
1111
TEST_RUN("VERSION/")
12+
TEST_RUN("NORMALIZE_GIT_URI/")
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
IF(NOT DEFINED CMAKE_SCRIPT_MODE_FILE)
2+
CMAKE_MINIMUM_REQUIRED(VERSION 3.18)
3+
PROJECT(CMUTIL_NORMALIZE_GIT_URI_TEST)
4+
ENDIF()
5+
6+
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
7+
8+
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/../TEST.cmake")
9+
10+
FIND_PACKAGE(CMUTIL)
11+
12+
13+
14+
FUNCTION(TEST_SSH_TARGET_TYPE)
15+
CMUTIL_NORMALIZE_GIT_URI(
16+
URI "https://github.com/username/repository.git"
17+
TARGET_TYPE "SSH"
18+
OUTPUT_VAR result
19+
)
20+
TEST_VAR_EQUALS_LITERAL(result "git@github.com:username/repository.git")
21+
22+
CMUTIL_NORMALIZE_GIT_URI(
23+
URI "https://gitlab.com/user/repo.git"
24+
TARGET_TYPE "SSH"
25+
OUTPUT_VAR result
26+
)
27+
TEST_VAR_EQUALS_LITERAL(result "git@gitlab.com:user/repo.git")
28+
29+
CMUTIL_NORMALIZE_GIT_URI(
30+
URI "http://example.com/path/to/repo.git"
31+
TARGET_TYPE "SSH"
32+
OUTPUT_VAR result
33+
)
34+
TEST_VAR_EQUALS_LITERAL(result "git@example.com:path/to/repo.git")
35+
36+
CMUTIL_NORMALIZE_GIT_URI(
37+
URI "git@github.com:user/repo.git"
38+
TARGET_TYPE "SSH"
39+
OUTPUT_VAR result
40+
)
41+
TEST_VAR_EQUALS_LITERAL(result "git@github.com:user/repo.git")
42+
43+
CMUTIL_NORMALIZE_GIT_URI(
44+
URI "https://gitlab.example.com/group/subgroup/project.git"
45+
TARGET_TYPE "SSH"
46+
OUTPUT_VAR result
47+
)
48+
TEST_VAR_EQUALS_LITERAL(result "git@gitlab.example.com:group/subgroup/project.git")
49+
50+
CMUTIL_NORMALIZE_GIT_URI(
51+
URI "https://github.com/user/repo"
52+
TARGET_TYPE "SSH"
53+
OUTPUT_VAR result
54+
)
55+
TEST_VAR_EQUALS_LITERAL(result "git@github.com:user/repo")
56+
57+
CMUTIL_NORMALIZE_GIT_URI(
58+
URI "https://git.example.com:8080/user/repo.git"
59+
TARGET_TYPE "SSH"
60+
OUTPUT_VAR result
61+
)
62+
TEST_VAR_EQUALS_LITERAL(result "git@git.example.com:8080:user/repo.git")
63+
ENDFUNCTION()
64+
65+
66+
67+
FUNCTION(TEST_HTTP_TARGET_TYPE)
68+
CMUTIL_NORMALIZE_GIT_URI(
69+
URI "git@github.com:username/repository.git"
70+
TARGET_TYPE "HTTP"
71+
OUTPUT_VAR result
72+
)
73+
TEST_VAR_EQUALS_LITERAL(result "https://github.com/username/repository.git")
74+
75+
CMUTIL_NORMALIZE_GIT_URI(
76+
URI "git@gitlab.com:user/repo.git"
77+
TARGET_TYPE "HTTP"
78+
OUTPUT_VAR result
79+
)
80+
TEST_VAR_EQUALS_LITERAL(result "https://gitlab.com/user/repo.git")
81+
82+
CMUTIL_NORMALIZE_GIT_URI(
83+
URI "git@example.com:path/to/repo.git"
84+
TARGET_TYPE "HTTP"
85+
OUTPUT_VAR result
86+
)
87+
TEST_VAR_EQUALS_LITERAL(result "https://example.com/path/to/repo.git")
88+
89+
CMUTIL_NORMALIZE_GIT_URI(
90+
URI "https://github.com/user/repo.git"
91+
TARGET_TYPE "HTTP"
92+
OUTPUT_VAR result
93+
)
94+
TEST_VAR_EQUALS_LITERAL(result "https://github.com/user/repo.git")
95+
96+
CMUTIL_NORMALIZE_GIT_URI(
97+
URI "http://example.com/user/repo.git"
98+
TARGET_TYPE "HTTP"
99+
OUTPUT_VAR result
100+
)
101+
TEST_VAR_EQUALS_LITERAL(result "http://example.com/user/repo.git")
102+
103+
CMUTIL_NORMALIZE_GIT_URI(
104+
URI "git@gitlab.example.com:group/subgroup/project.git"
105+
TARGET_TYPE "HTTP"
106+
OUTPUT_VAR result
107+
)
108+
TEST_VAR_EQUALS_LITERAL(result "https://gitlab.example.com/group/subgroup/project.git")
109+
110+
CMUTIL_NORMALIZE_GIT_URI(
111+
URI "git@github.com:user/repo"
112+
TARGET_TYPE "HTTP"
113+
OUTPUT_VAR result
114+
)
115+
TEST_VAR_EQUALS_LITERAL(result "https://github.com/user/repo")
116+
ENDFUNCTION()
117+
118+
TEST_SSH_TARGET_TYPE()
119+
TEST_HTTP_TARGET_TYPE()
120+
121+
TEST_RUN("fail/")
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
IF(NOT DEFINED CMAKE_SCRIPT_MODE_FILE)
2+
CMAKE_MINIMUM_REQUIRED(VERSION 3.18)
3+
PROJECT(CMUTIL_NORMALIZE_GIT_URI_FAIL_TEST)
4+
ENDIF()
5+
6+
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../")
7+
8+
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/../../TEST.cmake")
9+
10+
TEST_INVALID_CMAKE_RUN("invalid_target_type/" "Invalid TARGET_TYPE")
11+
TEST_INVALID_CMAKE_RUN("invalid_http_uri/" "is not a valid HTTP\\(S\\) or git@ Git URI")
12+
TEST_INVALID_CMAKE_RUN("invalid_ssh_uri/" "is not a valid git@ or HTTP\\(S\\) Git URI")

0 commit comments

Comments
 (0)