From d4234623bea7f51d8799c5f9dd2afe1cf8ff9278 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:24:14 +0000 Subject: [PATCH 1/2] Initial plan From d409a71f153410585ad75d82eeab66dd25f1b4c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:54:30 +0000 Subject: [PATCH 2/2] Standardize repository slug functions - implementation complete Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/pr_command.go | 65 +++++++++++++++++++++++----------------- pkg/cli/repo.go | 9 ++++++ pkg/cli/spec.go | 4 +-- pkg/cli/trial_command.go | 8 +---- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/pkg/cli/pr_command.go b/pkg/cli/pr_command.go index 1488ff03aef..415edd9e200 100644 --- a/pkg/cli/pr_command.go +++ b/pkg/cli/pr_command.go @@ -96,28 +96,6 @@ func parsePRURL(prURL string) (owner, repo string, prNumber int, err error) { return parser.ParsePRURL(prURL) } -// getCurrentRepo gets the current repository information using gh CLI -func getCurrentRepo() (owner, repo string, err error) { - cmd := exec.Command("gh", "repo", "view", "--json", "owner,name") - output, err := cmd.Output() - if err != nil { - return "", "", fmt.Errorf("failed to get current repository info: %w", err) - } - - var repoInfo struct { - Owner struct { - Login string `json:"login"` - } `json:"owner"` - Name string `json:"name"` - } - - if err := json.Unmarshal(output, &repoInfo); err != nil { - return "", "", fmt.Errorf("failed to parse repository info: %w", err) - } - - return repoInfo.Owner.Login, repoInfo.Name, nil -} - // checkRepositoryAccess checks if the current user has write access to the target repository func checkRepositoryAccess(owner, repo string) (bool, error) { // Get current user @@ -593,10 +571,14 @@ func transferPR(prURL, targetRepo string, verbose bool) error { targetOwner, targetRepoName = parts[0], parts[1] } else { // Use current repository as target - targetOwner, targetRepoName, err = getCurrentRepo() + slug, err := GetCurrentRepoSlug() if err != nil { return fmt.Errorf("failed to determine target repository: %w", err) } + targetOwner, targetRepoName, err = SplitRepoSlug(slug) + if err != nil { + return fmt.Errorf("failed to parse target repository: %w", err) + } } if verbose { @@ -615,12 +597,39 @@ func transferPR(prURL, targetRepo string, verbose bool) error { if targetRepo != "" { // Check if we're already in the target repository if isGitRepo() { - currentOwner, currentRepoName, err := getCurrentRepo() - if err == nil && currentOwner == targetOwner && currentRepoName == targetRepoName { - // We're already in the target repo - workingDir = "." + slug, err := GetCurrentRepoSlug() + if err == nil { + currentOwner, currentRepoName, err := SplitRepoSlug(slug) + if err == nil && currentOwner == targetOwner && currentRepoName == targetRepoName { + // We're already in the target repo + workingDir = "." + } else { + // We need to clone the target repository + if verbose { + fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Cloning target repository %s/%s...", targetOwner, targetRepoName))) + } + tempDir, err := os.MkdirTemp("", "gh-aw-pr-transfer-repo-") + if err != nil { + return fmt.Errorf("failed to create temp directory for repo: %w", err) + } + + cloneCmd := exec.Command("gh", "repo", "clone", fmt.Sprintf("%s/%s", targetOwner, targetRepoName), tempDir) + if err := cloneCmd.Run(); err != nil { + os.RemoveAll(tempDir) + return fmt.Errorf("failed to clone target repository: %w", err) + } + + workingDir = tempDir + needsCleanup = true + + // Change to the cloned repository directory + if err := os.Chdir(tempDir); err != nil { + os.RemoveAll(tempDir) + return fmt.Errorf("failed to change to cloned repository directory: %w", err) + } + } } else { - // We need to clone the target repository + // Error getting current repo, clone anyway if verbose { fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Cloning target repository %s/%s...", targetOwner, targetRepoName))) } diff --git a/pkg/cli/repo.go b/pkg/cli/repo.go index f9a8b8f9fd0..d60e980f89e 100644 --- a/pkg/cli/repo.go +++ b/pkg/cli/repo.go @@ -104,3 +104,12 @@ func GetCurrentRepoSlug() (string, error) { repoLog.Printf("Using cached repository slug: %s", currentRepoSlugResult) return currentRepoSlugResult, nil } + +// SplitRepoSlug splits "owner/repo" into owner and repo +func SplitRepoSlug(slug string) (owner, repo string, err error) { + parts := strings.Split(slug, "/") + if len(parts) != 2 { + return "", "", fmt.Errorf("invalid repo format: %s", slug) + } + return parts[0], parts[1], nil +} diff --git a/pkg/cli/spec.go b/pkg/cli/spec.go index f9d3840e70c..9a1f609d1a8 100644 --- a/pkg/cli/spec.go +++ b/pkg/cli/spec.go @@ -96,7 +96,7 @@ func parseRepoSpec(repoSpec string) (*RepoSpec, error) { repo = fmt.Sprintf("%s/%s", pathParts[0], pathParts[1]) } else if repo == "." { // Handle current directory as repo (local workflow) - currentRepo, err := getCurrentRepositoryInfo() + currentRepo, err := GetCurrentRepoSlug() if err != nil { return nil, fmt.Errorf("failed to get current repository info: %w", err) } @@ -269,7 +269,7 @@ func parseLocalWorkflowSpec(spec string) (*WorkflowSpec, error) { } // Get current repository info - repoInfo, err := getCurrentRepositoryInfo() + repoInfo, err := GetCurrentRepoSlug() if err != nil { return nil, fmt.Errorf("failed to get current repository info for local workflow: %w", err) } diff --git a/pkg/cli/trial_command.go b/pkg/cli/trial_command.go index f4441a48f99..e7c09bf2056 100644 --- a/pkg/cli/trial_command.go +++ b/pkg/cli/trial_command.go @@ -219,7 +219,7 @@ func RunWorkflowTrials(workflowSpecs []string, logicalRepoSpec string, cloneRepo } else { // Fall back to current repository for logical-repo mode var err error - logicalRepoSlug, err = getCurrentRepositoryInfo() + logicalRepoSlug, err = GetCurrentRepoSlug() if err != nil { return fmt.Errorf("failed to determine simulated host repository: %w", err) } @@ -456,12 +456,6 @@ func RunWorkflowTrials(workflowSpecs []string, logicalRepoSpec string, cloneRepo } -// getCurrentRepositoryInfo determines the current repository from the gh CLI (cached) -// This is a wrapper around GetCurrentRepoSlug for backward compatibility -func getCurrentRepositoryInfo() (string, error) { - return GetCurrentRepoSlug() -} - // getCurrentGitHubUsername gets the current GitHub username from gh CLI func getCurrentGitHubUsername() (string, error) { cmd := exec.Command("gh", "api", "user", "--jq", ".login")