|
11 | 11 |
|
12 | 12 | from gitingest.utils.exceptions import InvalidGitHubTokenError |
13 | 13 | from gitingest.utils.git_utils import ( |
| 14 | + _is_github_host, |
14 | 15 | create_git_auth_header, |
15 | 16 | create_git_command, |
16 | 17 | validate_github_token, |
@@ -140,3 +141,124 @@ def test_create_git_command_helper_calls(mocker, url, token, should_call): |
140 | 141 | header_mock.assert_not_called() |
141 | 142 | # HEADER should not be included in command list |
142 | 143 | assert "HEADER" not in cmd |
| 144 | + |
| 145 | + |
| 146 | +@pytest.mark.parametrize( |
| 147 | + "url, expected", |
| 148 | + [ |
| 149 | + # GitHub.com URLs |
| 150 | + ("https://github.com/owner/repo.git", True), |
| 151 | + ("http://github.com/owner/repo.git", True), |
| 152 | + ("https://github.com/owner/repo", True), |
| 153 | + # GitHub Enterprise URLs |
| 154 | + ("https://github.company.com/owner/repo.git", True), |
| 155 | + ("https://github.enterprise.org/owner/repo.git", True), |
| 156 | + ("http://github.internal/owner/repo.git", True), |
| 157 | + ("https://github.example.co.uk/owner/repo.git", True), |
| 158 | + # Non-GitHub URLs |
| 159 | + ("https://gitlab.com/owner/repo.git", False), |
| 160 | + ("https://bitbucket.org/owner/repo.git", False), |
| 161 | + ("https://git.example.com/owner/repo.git", False), |
| 162 | + ("https://mygithub.com/owner/repo.git", False), # doesn't start with "github." |
| 163 | + ("https://subgithub.com/owner/repo.git", False), |
| 164 | + ("https://example.com/github/repo.git", False), |
| 165 | + # Edge cases |
| 166 | + ("", False), |
| 167 | + ("not-a-url", False), |
| 168 | + ("ftp://github.com/owner/repo.git", True), # Different protocol but still github.com |
| 169 | + ], |
| 170 | +) |
| 171 | +def test_is_github_host(url, expected): |
| 172 | + """_is_github_host should correctly identify GitHub and GitHub Enterprise URLs.""" |
| 173 | + assert _is_github_host(url) == expected |
| 174 | + |
| 175 | + |
| 176 | +@pytest.mark.parametrize( |
| 177 | + "token, url, expected_hostname", |
| 178 | + [ |
| 179 | + # GitHub.com URLs (default) |
| 180 | + ("ghp_" + "a" * 36, "https://github.com", "github.com"), |
| 181 | + ("ghp_" + "a" * 36, "https://github.com/owner/repo.git", "github.com"), |
| 182 | + # GitHub Enterprise URLs |
| 183 | + ("ghp_" + "b" * 36, "https://github.company.com", "github.company.com"), |
| 184 | + ("ghp_" + "c" * 36, "https://github.enterprise.org/owner/repo.git", "github.enterprise.org"), |
| 185 | + ("ghp_" + "d" * 36, "http://github.internal", "github.internal"), |
| 186 | + ], |
| 187 | +) |
| 188 | +def test_create_git_auth_header_with_ghe_url(token, url, expected_hostname): |
| 189 | + """create_git_auth_header should handle GitHub Enterprise URLs correctly.""" |
| 190 | + header = create_git_auth_header(token, url) |
| 191 | + expected_basic = base64.b64encode(f"x-oauth-basic:{token}".encode()).decode() |
| 192 | + expected = f"http.https://{expected_hostname}/.extraheader=Authorization: Basic {expected_basic}" |
| 193 | + assert header == expected |
| 194 | + |
| 195 | + |
| 196 | +@pytest.mark.parametrize( |
| 197 | + "base_cmd, local_path, url, token, expected_auth_hostname", |
| 198 | + [ |
| 199 | + # GitHub.com URLs - should use default hostname |
| 200 | + ( |
| 201 | + ["git", "clone"], |
| 202 | + "/some/path", |
| 203 | + "https://github.com/owner/repo.git", |
| 204 | + "ghp_" + "a" * 36, |
| 205 | + "github.com", |
| 206 | + ), |
| 207 | + # GitHub Enterprise URLs - should use custom hostname |
| 208 | + ( |
| 209 | + ["git", "clone"], |
| 210 | + "/some/path", |
| 211 | + "https://github.company.com/owner/repo.git", |
| 212 | + "ghp_" + "b" * 36, |
| 213 | + "github.company.com", |
| 214 | + ), |
| 215 | + ( |
| 216 | + ["git", "clone"], |
| 217 | + "/some/path", |
| 218 | + "https://github.enterprise.org/owner/repo.git", |
| 219 | + "ghp_" + "c" * 36, |
| 220 | + "github.enterprise.org", |
| 221 | + ), |
| 222 | + ( |
| 223 | + ["git", "clone"], |
| 224 | + "/some/path", |
| 225 | + "http://github.internal/owner/repo.git", |
| 226 | + "ghp_" + "d" * 36, |
| 227 | + "github.internal", |
| 228 | + ), |
| 229 | + ], |
| 230 | +) |
| 231 | +def test_create_git_command_with_ghe_urls(base_cmd, local_path, url, token, expected_auth_hostname): |
| 232 | + """create_git_command should handle GitHub Enterprise URLs correctly.""" |
| 233 | + cmd = create_git_command(base_cmd, local_path, url, token) |
| 234 | + |
| 235 | + # Should have base command and -C option |
| 236 | + expected_prefix = base_cmd + ["-C", local_path] |
| 237 | + assert cmd[: len(expected_prefix)] == expected_prefix |
| 238 | + |
| 239 | + # Should have -c and auth header |
| 240 | + assert "-c" in cmd |
| 241 | + auth_header_index = cmd.index("-c") + 1 |
| 242 | + auth_header = cmd[auth_header_index] |
| 243 | + |
| 244 | + # Verify the auth header contains the expected hostname |
| 245 | + assert f"http.https://{expected_auth_hostname}/" in auth_header |
| 246 | + assert "Authorization: Basic" in auth_header |
| 247 | + |
| 248 | + |
| 249 | +@pytest.mark.parametrize( |
| 250 | + "base_cmd, local_path, url, token", |
| 251 | + [ |
| 252 | + # Should NOT add auth headers for non-GitHub URLs |
| 253 | + (["git", "clone"], "/some/path", "https://gitlab.com/owner/repo.git", "ghp_" + "a" * 36), |
| 254 | + (["git", "clone"], "/some/path", "https://bitbucket.org/owner/repo.git", "ghp_" + "b" * 36), |
| 255 | + (["git", "clone"], "/some/path", "https://git.example.com/owner/repo.git", "ghp_" + "c" * 36), |
| 256 | + ], |
| 257 | +) |
| 258 | +def test_create_git_command_ignores_non_github_urls(base_cmd, local_path, url, token): |
| 259 | + """create_git_command should not add auth headers for non-GitHub URLs.""" |
| 260 | + cmd = create_git_command(base_cmd, local_path, url, token) |
| 261 | + |
| 262 | + # Should only have base command and -C option, no auth headers |
| 263 | + expected = base_cmd + ["-C", local_path] |
| 264 | + assert cmd == expected |
0 commit comments