createPatchFromPR creates a git patch from the PR changes using gh pr diff
(sourceOwner, sourceRepo string, prInfo *PRInfo, verbose bool)
| 204 | |
| 205 | // createPatchFromPR creates a git patch from the PR changes using gh pr diff |
| 206 | func createPatchFromPR(sourceOwner, sourceRepo string, prInfo *PRInfo, verbose bool) (string, error) { |
| 207 | // Create a temporary directory for the patch |
| 208 | tempDir, err := os.MkdirTemp("", "gh-aw-pr-transfer-") |
| 209 | if err != nil { |
| 210 | return "", fmt.Errorf("failed to create temp directory: %w", err) |
| 211 | } |
| 212 | |
| 213 | patchFile := filepath.Join(tempDir, "pr.patch") |
| 214 | |
| 215 | // Use gh pr diff command directly - this is the most reliable method |
| 216 | diffContent, err := workflow.RunGH("Fetching pull request diff...", "pr", "diff", strconv.Itoa(prInfo.Number), "--repo", fmt.Sprintf("%s/%s", sourceOwner, sourceRepo)) |
| 217 | if err != nil { |
| 218 | return "", fmt.Errorf("failed to get PR diff: %w", err) |
| 219 | } |
| 220 | |
| 221 | if len(diffContent) == 0 { |
| 222 | return "", errors.New("PR diff is empty") |
| 223 | } |
| 224 | |
| 225 | // Create proper mailbox format patch that git am expects |
| 226 | var patchBuilder strings.Builder |
| 227 | |
| 228 | // Required mailbox format headers for git am |
| 229 | fmt.Fprintf(&patchBuilder, "From %s Mon Sep 17 00:00:00 2001\n", prInfo.HeadSHA) |
| 230 | fmt.Fprintf(&patchBuilder, "From: %s <%s@users.noreply.github.com>\n", prInfo.AuthorLogin, prInfo.AuthorLogin) |
| 231 | fmt.Fprintf(&patchBuilder, "Date: %s\n", time.Now().Format(time.RFC1123)) |
| 232 | fmt.Fprintf(&patchBuilder, "Subject: [PATCH] %s\n", prInfo.Title) |
| 233 | patchBuilder.WriteString("\n") |
| 234 | |
| 235 | if prInfo.Body != "" { |
| 236 | fmt.Fprintf(&patchBuilder, "%s\n", prInfo.Body) |
| 237 | patchBuilder.WriteString("\n") |
| 238 | } |
| 239 | |
| 240 | fmt.Fprintf(&patchBuilder, "Original-PR: %s#%d\n", prInfo.SourceRepo, prInfo.Number) |
| 241 | fmt.Fprintf(&patchBuilder, "Original-Author: %s\n", prInfo.AuthorLogin) |
| 242 | patchBuilder.WriteString("---\n") |
| 243 | |
| 244 | // Add the actual diff content |
| 245 | patchBuilder.Write(diffContent) |
| 246 | |
| 247 | if err := os.WriteFile(patchFile, []byte(patchBuilder.String()), constants.FilePermPublic); err != nil { |
| 248 | return "", fmt.Errorf("failed to write patch file: %w", err) |
| 249 | } |
| 250 | |
| 251 | if verbose { |
| 252 | fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Successfully created patch using gh pr diff")) |
| 253 | } |
| 254 | |
| 255 | return patchFile, nil |
| 256 | } // applyPatchToRepo applies a patch to the target repository and returns the branch name |
| 257 | func applyPatchToRepo(patchFile string, prInfo *PRInfo, targetOwner, targetRepo string, verbose bool) (string, error) { |
| 258 | // Get current branch to restore later |
| 259 | currentBranch, err := getCurrentBranch() |
no test coverage detected