github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/issue/transfer/transfer.go (about) 1 package transfer 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "github.com/ungtb10d/cli/v2/api" 8 "github.com/ungtb10d/cli/v2/internal/config" 9 "github.com/ungtb10d/cli/v2/internal/ghrepo" 10 "github.com/ungtb10d/cli/v2/pkg/cmd/issue/shared" 11 "github.com/ungtb10d/cli/v2/pkg/cmdutil" 12 "github.com/ungtb10d/cli/v2/pkg/iostreams" 13 "github.com/shurcooL/githubv4" 14 "github.com/spf13/cobra" 15 ) 16 17 type TransferOptions struct { 18 HttpClient func() (*http.Client, error) 19 Config func() (config.Config, error) 20 IO *iostreams.IOStreams 21 BaseRepo func() (ghrepo.Interface, error) 22 23 IssueSelector string 24 DestRepoSelector string 25 } 26 27 func NewCmdTransfer(f *cmdutil.Factory, runF func(*TransferOptions) error) *cobra.Command { 28 opts := TransferOptions{ 29 IO: f.IOStreams, 30 HttpClient: f.HttpClient, 31 Config: f.Config, 32 } 33 34 cmd := &cobra.Command{ 35 Use: "transfer {<number> | <url>} <destination-repo>", 36 Short: "Transfer issue to another repository", 37 Args: cmdutil.ExactArgs(2, "issue and destination repository are required"), 38 RunE: func(cmd *cobra.Command, args []string) error { 39 opts.BaseRepo = f.BaseRepo 40 opts.IssueSelector = args[0] 41 opts.DestRepoSelector = args[1] 42 43 if runF != nil { 44 return runF(&opts) 45 } 46 47 return transferRun(&opts) 48 }, 49 } 50 51 return cmd 52 } 53 54 func transferRun(opts *TransferOptions) error { 55 httpClient, err := opts.HttpClient() 56 if err != nil { 57 return err 58 } 59 60 issue, baseRepo, err := shared.IssueFromArgWithFields(httpClient, opts.BaseRepo, opts.IssueSelector, []string{"id", "number"}) 61 if err != nil { 62 return err 63 } 64 if issue.IsPullRequest() { 65 return fmt.Errorf("issue #%d is a pull request and cannot be transferred", issue.Number) 66 } 67 68 destRepo, err := ghrepo.FromFullNameWithHost(opts.DestRepoSelector, baseRepo.RepoHost()) 69 if err != nil { 70 return err 71 } 72 73 url, err := issueTransfer(httpClient, issue.ID, destRepo) 74 if err != nil { 75 return err 76 } 77 78 _, err = fmt.Fprintln(opts.IO.Out, url) 79 return err 80 } 81 82 func issueTransfer(httpClient *http.Client, issueID string, destRepo ghrepo.Interface) (string, error) { 83 var destinationRepoID string 84 if r, ok := destRepo.(*api.Repository); ok { 85 destinationRepoID = r.ID 86 } else { 87 apiClient := api.NewClientFromHTTP(httpClient) 88 r, err := api.GitHubRepo(apiClient, destRepo) 89 if err != nil { 90 return "", err 91 } 92 destinationRepoID = r.ID 93 } 94 95 var mutation struct { 96 TransferIssue struct { 97 Issue struct { 98 URL string 99 } 100 } `graphql:"transferIssue(input: $input)"` 101 } 102 103 variables := map[string]interface{}{ 104 "input": githubv4.TransferIssueInput{ 105 IssueID: issueID, 106 RepositoryID: destinationRepoID, 107 }, 108 } 109 110 gql := api.NewClientFromHTTP(httpClient) 111 err := gql.Mutate(destRepo.RepoHost(), "IssueTransfer", &mutation, variables) 112 return mutation.TransferIssue.Issue.URL, err 113 }