downloadFileViaGitClone downloads a file by shallow cloning the repository This is used as a fallback when git archive doesn't work
(owner, repo, path, ref, host string)
| 684 | // downloadFileViaGitClone downloads a file by shallow cloning the repository |
| 685 | // This is used as a fallback when git archive doesn't work |
| 686 | func downloadFileViaGitClone(owner, repo, path, ref, host string) ([]byte, error) { |
| 687 | remoteLog.Printf("Attempting git clone fallback for %s/%s/%s@%s", owner, repo, path, ref) |
| 688 | |
| 689 | // Create a temporary directory for the shallow clone |
| 690 | tmpDir, err := os.MkdirTemp("", "gh-aw-git-clone-*") |
| 691 | if err != nil { |
| 692 | return nil, fmt.Errorf("failed to create temp directory: %w", err) |
| 693 | } |
| 694 | defer os.RemoveAll(tmpDir) |
| 695 | |
| 696 | var githubHost string |
| 697 | if host != "" { |
| 698 | githubHost = "https://" + host |
| 699 | } else { |
| 700 | githubHost = GetGitHubHostForRepo(owner, repo) |
| 701 | } |
| 702 | repoURL := fmt.Sprintf("%s/%s/%s.git", githubHost, owner, repo) |
| 703 | |
| 704 | // Check if ref is a SHA (40 hex characters) |
| 705 | isSHA := len(ref) == 40 && gitutil.IsHexString(ref) |
| 706 | |
| 707 | var cloneCmd *exec.Cmd |
| 708 | if isSHA { |
| 709 | // For SHA refs, we need to clone without --branch and then checkout the specific commit |
| 710 | // Clone with minimal depth and no branch specified |
| 711 | cloneCmd = exec.Command("git", "clone", "--depth", "1", "--no-single-branch", repoURL, tmpDir) |
| 712 | if output, err := cloneCmd.CombinedOutput(); err != nil { |
| 713 | // Try without --no-single-branch if the first attempt fails |
| 714 | remoteLog.Printf("Clone with --no-single-branch failed, trying full clone: %s", string(output)) |
| 715 | cloneCmd = exec.Command("git", "clone", repoURL, tmpDir) |
| 716 | if output, err := cloneCmd.CombinedOutput(); err != nil { |
| 717 | return nil, fmt.Errorf("failed to clone repository: %w\nOutput: %s", err, string(output)) |
| 718 | } |
| 719 | } |
| 720 | |
| 721 | // Now checkout the specific commit |
| 722 | checkoutCmd := exec.Command("git", "-C", tmpDir, "checkout", ref) |
| 723 | if output, err := checkoutCmd.CombinedOutput(); err != nil { |
| 724 | return nil, fmt.Errorf("failed to checkout commit %s: %w\nOutput: %s", ref, err, string(output)) |
| 725 | } |
| 726 | } else { |
| 727 | // For branch/tag refs, use --branch flag |
| 728 | cloneCmd = exec.Command("git", "clone", "--depth", "1", "--branch", ref, repoURL, tmpDir) |
| 729 | if output, err := cloneCmd.CombinedOutput(); err != nil { |
| 730 | return nil, fmt.Errorf("failed to clone repository: %w\nOutput: %s", err, string(output)) |
| 731 | } |
| 732 | } |
| 733 | |
| 734 | // Read the file from the cloned repository |
| 735 | filePath := filepath.Join(tmpDir, path) |
| 736 | if err := fileutil.ValidatePathWithinBase(tmpDir, filePath); err != nil { |
| 737 | return nil, fmt.Errorf("refusing to read file outside clone directory: %w", err) |
| 738 | } |
| 739 | content, err := os.ReadFile(filePath) |
| 740 | if err != nil { |
| 741 | return nil, fmt.Errorf("failed to read file from cloned repository: %w", err) |
| 742 | } |
| 743 |
no test coverage detected