package list import ( "fmt" "github.com/spf13/cobra" "tangled.org/eric.wien/tng-cli/api" gitpkg "tangled.org/eric.wien/tng-cli/git" "tangled.org/eric.wien/tng-cli/pkg/cmdutil" "tangled.org/eric.wien/tng-cli/pkg/iostreams" ) type Options struct { IO *iostreams.IOStreams ApiClient func() (*api.Client, error) BaseRepo func() (*gitpkg.TangledRepo, error) Repo string Web bool } func NewCmdList(f *cmdutil.Factory) *cobra.Command { opts := &Options{ IO: f.IOStreams, ApiClient: f.ApiClient, BaseRepo: f.BaseRepo, } cmd := &cobra.Command{ Use: "list", Short: "List your pull requests", Long: `List pull requests you have created. Optionally filter by repository. Note: This shows only PRs you authored. Use --web to see all pull requests for a repository on tangled.sh.`, Example: ` tng pr list tng pr list --repo alice.bsky.social/my-project tng pr list --web`, Aliases: []string{"ls"}, Args: cmdutil.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return listRun(cmd, opts) }, } cmd.Flags().StringVarP(&opts.Repo, "repo", "R", "", "Filter by repository (owner/name)") cmd.Flags().BoolVarP(&opts.Web, "web", "w", false, "Open pull requests page on tangled.sh") return cmd } func listRun(cmd *cobra.Command, opts *Options) error { cs := iostreams.NewColorScheme(opts.IO.ColorEnabled()) repoRef := opts.Repo if repoRef == "" { if repo, err := opts.BaseRepo(); err == nil { repoRef = repo.FullName() } } if opts.Web { if repoRef == "" { return fmt.Errorf("could not determine repository; use --repo") } url := api.FormatPullURL(repoRef) fmt.Fprintln(opts.IO.Out, url) return nil } client, err := opts.ApiClient() if err != nil { return err } // Resolve the repo filter. An explicit --repo that can't be resolved is an // error; a repo auto-detected from git remotes only warns, since listing // everything is still useful. var repoURI string if repoRef != "" { owner, name, err := cmdutil.ParseOwnerRepo(repoRef) if err == nil { var resolved *api.ResolvedRepo resolved, err = client.ResolveRepo(cmd.Context(), owner, name) if err == nil { repoURI = resolved.URI } } if err != nil { if opts.Repo != "" { return fmt.Errorf("failed to resolve %s: %w", repoRef, err) } fmt.Fprintf(opts.IO.ErrOut, "warning: could not resolve %s (%v); listing all your pull requests\n", repoRef, err) } } pulls, err := client.ListOwnPulls(cmd.Context(), repoURI) if err != nil { return fmt.Errorf("failed to list pull requests: %w", err) } if len(pulls) == 0 { fmt.Fprintln(opts.IO.ErrOut, "No pull requests found.") if repoRef != "" { fmt.Fprintf(opts.IO.ErrOut, "Use --web to see all PRs at %s\n", api.FormatPullURL(repoRef)) } return nil } for _, pr := range pulls { refs := "" if pr.SourceRef != "" && pr.TargetRef != "" { refs = fmt.Sprintf(" %s -> %s", cs.Cyan(pr.SourceRef), cs.Cyan(pr.TargetRef)) } fmt.Fprintf(opts.IO.Out, "%s %s%s %s\n", cs.Gray(pr.Rkey), cs.Bold(pr.Title), refs, cs.Gray(pr.CreatedAt), ) } return nil }