|
10 | 10 | import logging |
11 | 11 | import argparse |
12 | 12 | import shutil |
13 | | -from git import Repo, GitCommandError, Git |
| 13 | +from git import Git |
14 | 14 | import bz2 |
15 | 15 | import contextlib |
16 | 16 | from datetime import datetime |
@@ -217,7 +217,19 @@ def get_remote_refs(git_url: str): |
217 | 217 | tags = [] |
218 | 218 | branches = [] |
219 | 219 | try: |
220 | | - cp = subprocess.run(["git", "ls-remote", "--tags", "--heads", git_url], capture_output=True, text=True, timeout=30) |
| 220 | + env = os.environ.copy() |
| 221 | + env["GIT_TERMINAL_PROMPT"] = "0" |
| 222 | + env["GIT_ASKPASS"] = "echo" |
| 223 | + env["GIT_CREDENTIAL_HELPER"] = "" |
| 224 | + if "GIT_SSH_COMMAND" not in env: |
| 225 | + env["GIT_SSH_COMMAND"] = "ssh -o BatchMode=yes -o StrictHostKeyChecking=no" |
| 226 | + else: |
| 227 | + env["GIT_SSH_COMMAND"] = env["GIT_SSH_COMMAND"] + " -o BatchMode=yes" |
| 228 | + cp = subprocess.run( |
| 229 | + ["git", "-c", "credential.helper=", "-c", "credential.helper=!", |
| 230 | + "ls-remote", "--tags", "--heads", git_url], |
| 231 | + env=env, capture_output=True, text=True, timeout=30, |
| 232 | + stdin=subprocess.DEVNULL) |
221 | 233 | if cp.returncode == 0: |
222 | 234 | for line in cp.stdout.splitlines(): |
223 | 235 | parts = line.split('\t') |
@@ -291,32 +303,84 @@ def download_git_repository(refs_to_checkout, git_url, target_dir, tag, called_c |
291 | 303 |
|
292 | 304 | logger.info(f"Download git url :{git_url}") |
293 | 305 | env = os.environ.copy() |
294 | | - if not called_cli: |
295 | | - env["GIT_TERMINAL_PROMPT"] = "0" |
| 306 | + env["GIT_TERMINAL_PROMPT"] = "0" |
| 307 | + if platform.system() == "Windows": |
| 308 | + env["GIT_ASKPASS"] = "echo" |
| 309 | + else: |
| 310 | + env["GIT_ASKPASS"] = "/bin/echo" |
| 311 | + env["GIT_CREDENTIAL_HELPER"] = "" |
| 312 | + # Disable credential helper via config |
| 313 | + if "GIT_CONFIG_COUNT" not in env: |
| 314 | + env["GIT_CONFIG_COUNT"] = "1" |
| 315 | + env["GIT_CONFIG_KEY_0"] = "credential.helper" |
| 316 | + env["GIT_CONFIG_VALUE_0"] = "" |
| 317 | + if "GIT_SSH_COMMAND" not in env: |
| 318 | + env["GIT_SSH_COMMAND"] = "ssh -o BatchMode=yes -o StrictHostKeyChecking=no" |
| 319 | + else: |
| 320 | + env["GIT_SSH_COMMAND"] = env["GIT_SSH_COMMAND"] + " -o BatchMode=yes" |
| 321 | + |
296 | 322 | if refs_to_checkout: |
297 | 323 | try: |
298 | | - # gitPython uses the branch argument the same whether you check out to a branch or a tag. |
299 | | - Repo.clone_from(git_url, target_dir, branch=refs_to_checkout, env=env) |
300 | | - if any(Path(target_dir).iterdir()): |
301 | | - success = True |
302 | | - oss_version = refs_to_checkout |
303 | | - logger.info(f"Files found in {target_dir} after clone.") |
| 324 | + # For tags, we need full history. For branches, shallow clone is possible but |
| 325 | + # we use full clone to ensure compatibility with all cases |
| 326 | + # Use subprocess to ensure environment variables are properly passed |
| 327 | + cmd = ["git", "-c", "credential.helper=", "-c", "credential.helper=!", "clone", git_url, target_dir] |
| 328 | + result = subprocess.run(cmd, env=env, capture_output=True, text=True, timeout=600, stdin=subprocess.DEVNULL) |
| 329 | + if result.returncode == 0: |
| 330 | + # Checkout the specific branch or tag |
| 331 | + checkout_cmd = ["git", "-C", target_dir, "checkout", refs_to_checkout] |
| 332 | + checkout_result = subprocess.run( |
| 333 | + checkout_cmd, env=env, capture_output=True, text=True, |
| 334 | + timeout=60, stdin=subprocess.DEVNULL) |
| 335 | + if checkout_result.returncode == 0: |
| 336 | + if any(Path(target_dir).iterdir()): |
| 337 | + success = True |
| 338 | + oss_version = refs_to_checkout |
| 339 | + logger.info(f"Files found in {target_dir} after clone and checkout.") |
| 340 | + else: |
| 341 | + logger.info(f"No files found in {target_dir} after clone.") |
| 342 | + success = False |
| 343 | + else: |
| 344 | + logger.info(f"Git checkout error: {checkout_result.stderr}") |
| 345 | + # Clone succeeded but checkout failed (e.g. non-existent ref): |
| 346 | + # repo has default branch; treat as success with empty version |
| 347 | + if any(Path(target_dir).iterdir()): |
| 348 | + success = True |
| 349 | + oss_version = "" |
| 350 | + logger.info("Checkout failed; keeping default branch.") |
304 | 351 | else: |
305 | | - logger.info(f"No files found in {target_dir} after clone.") |
| 352 | + logger.info(f"Git clone error: {result.stderr}") |
306 | 353 | success = False |
307 | | - except GitCommandError as error: |
308 | | - logger.info(f"Git checkout error:{error}") |
| 354 | + except subprocess.TimeoutExpired: |
| 355 | + logger.info("Git clone timeout") |
309 | 356 | success = False |
310 | 357 | except Exception as e: |
311 | | - logger.info(f"Repo.clone_from error:{e}") |
| 358 | + logger.info(f"Git clone error:{e}") |
312 | 359 | success = False |
313 | 360 |
|
314 | 361 | if not success: |
315 | | - Repo.clone_from(git_url, target_dir, env=env) |
316 | | - if any(Path(target_dir).iterdir()): |
317 | | - success = True |
318 | | - else: |
319 | | - logger.info(f"No files found in {target_dir} after clone.") |
| 362 | + try: |
| 363 | + # Use subprocess to ensure environment variables are properly passed |
| 364 | + # No checkout needed, so shallow clone is sufficient |
| 365 | + cmd = [ |
| 366 | + "git", "-c", "credential.helper=", "-c", "credential.helper=!", |
| 367 | + "clone", "--depth", "1", git_url, target_dir |
| 368 | + ] |
| 369 | + result = subprocess.run(cmd, env=env, capture_output=True, text=True, timeout=600, stdin=subprocess.DEVNULL) |
| 370 | + if result.returncode == 0: |
| 371 | + if any(Path(target_dir).iterdir()): |
| 372 | + success = True |
| 373 | + else: |
| 374 | + logger.info(f"No files found in {target_dir} after clone.") |
| 375 | + success = False |
| 376 | + else: |
| 377 | + logger.info(f"Git clone error: {result.stderr}") |
| 378 | + success = False |
| 379 | + except subprocess.TimeoutExpired: |
| 380 | + logger.info("Git clone timeout") |
| 381 | + success = False |
| 382 | + except Exception as e: |
| 383 | + logger.info(f"Git clone error:{e}") |
320 | 384 | success = False |
321 | 385 | return success, oss_version |
322 | 386 |
|
|
0 commit comments