package main import ( "bytes" "context" "errors" "fmt" "io" "log" "net/http" "net/mail" "os" "os/exec" "strings" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "git.sr.ht/~xenrox/hut/srht/listssrht" "git.sr.ht/~xenrox/hut/termfmt") func newListsCommand() *cobra.Command { cmd := &cobra.Command{ Use: "lists", Short: "Use the lists API", } cmd.AddCommand(newListsDeleteCommand()) cmd.AddCommand(newListsListCommand()) cmd.AddCommand(newListsSubscribeCommand()) cmd.AddCommand(newListsUnsubscribeCommand()) cmd.AddCommand(newListsCreateCommand()) cmd.AddCommand(newListsArchiveCommand()) cmd.AddCommand(newListsPatchsetCommand()) cmd.AddCommand(newListsACLCommand()) cmd.AddCommand(newListsUserWebhookCommand()) cmd.AddCommand(newListsWebhookCommand()) cmd.AddCommand(newListsSubscriptions()) cmd.PersistentFlags().StringP("mailing-list", "l", "", "mailing list name") cmd.RegisterFlagCompletionFunc("mailing-list", completeList) return cmd} func newListsDeleteCommand() *cobra.Command { var autoConfirm bool run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) id := getMailingListID(c, ctx, name, owner) if !autoConfirm && !getConfirmation(fmt.Sprintf("Do you really want to delete the list %s", name)) { log.Println("Aborted") return } list, err := listssrht.DeleteMailingList(c.Client, ctx, id) if err != nil { log.Fatal(err) } else if list == nil { log.Fatalf("failed to delete list with ID %d", id) } log.Printf("Deleted mailing list %s\n", list.Name) } cmd := &cobra.Command{ Use: "delete [list]", Short: "Delete a mailing list", Args: cobra.MaximumNArgs(1), ValidArgsFunction: completeList, Run: run, } cmd.Flags().BoolVarP(&autoConfirm, "yes", "y", false, "auto confirm") return cmd} func newListsListCommand() *cobra.Command { cmd := &cobra.Command{ Use: "list [username]", Short: "List mailing lists", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, } cmd.Run = func(cmd *cobra.Command, args []string) { ctx := cmd.Context() c := createClient("lists", cmd) var cursor *listssrht.Cursor var username string if len(args) > 0 { username = strings.TrimLeft(args[0], ownerPrefixes) } err := pagerify(func(p pager) error { var lists *listssrht.MailingListCursor if len(username) > 0 { user, err := listssrht.MailingListsByUser(c.Client, ctx, username, cursor) if err != nil { return err } else if user == nil { return errors.New("no such user") } lists = user.Lists } else { var err error user, err := listssrht.MailingLists(c.Client, ctx, cursor) if err != nil { return err } lists = user.Lists } for _, list := range lists.Results { printList(p, &list) } cursor = lists.Cursor if cursor == nil { return pagerDone } return nil }) if err != nil { log.Fatal(err) } } return cmd} func printList(w io.Writer, list *listssrht.MailingList) { fmt.Fprintf(w, "%s (%s)\n", termfmt.Bold.String(list.Name), list.Visibility.TermString()) if list.Description != nil && *list.Description != "" { fmt.Fprintln(w, "\n"+indent(*list.Description, " ")+"\n") }} func newListsSubscribeCommand() *cobra.Command { run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) id := getMailingListID(c, ctx, name, owner) subscription, err := listssrht.MailingListSubscribe(c.Client, ctx, id) if err != nil { log.Fatal(err) } log.Printf("Subscribed to %s/%s/%s\n", c.BaseURL, subscription.List.Owner.CanonicalName, subscription.List.Name) } cmd := &cobra.Command{ Use: "subscribe [list]", Short: "Subscribe to a mailing list", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } return cmd} func newListsUnsubscribeCommand() *cobra.Command { run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) id := getMailingListID(c, ctx, name, owner) subscription, err := listssrht.MailingListUnsubscribe(c.Client, ctx, id) if err != nil { log.Fatal(err) } else if subscription == nil { log.Fatalf("you were not subscribed to %s/%s/%s", c.BaseURL, owner, name) } log.Printf("Unsubscribed from %s/%s/%s\n", c.BaseURL, subscription.List.Owner.CanonicalName, subscription.List.Name) } cmd := &cobra.Command{ Use: "unsubscribe [list]", Short: "Unubscribe from a mailing list", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } return cmd} const listsCreatePrefill = `<!--Please write the Markdown description of the new mailing list above.-->` func newListsCreateCommand() *cobra.Command { var visibility string var stdin bool run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() c := createClient("lists", cmd) listVisibility, err := listssrht.ParseVisibility(visibility) if err != nil { log.Fatal(err) } var description *string if stdin { b, err := io.ReadAll(os.Stdin) if err != nil { log.Fatalf("failed to read mailing list description: %v", err) } desc := string(b) description = &desc } else { text, err := getInputWithEditor("hut_mailing-list*.md", listsCreatePrefill) if err != nil { log.Fatalf("failed to read mailing list description: %v", err) } text = dropComment(text, listsCreatePrefill) description = &text } list, err := listssrht.CreateMailingList(c.Client, ctx, args[0], description, listVisibility) if err != nil { log.Fatal(err) } else if list == nil { log.Fatal("failed to create mailing list") } log.Printf("Created mailing list %q\n", list.Name) } cmd := &cobra.Command{ Use: "create <name>", Short: "Create a mailing list", Args: cobra.ExactArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } cmd.Flags().BoolVar(&stdin, "stdin", false, "read mailing list from stdin") cmd.Flags().StringVarP(&visibility, "visibility", "v", "public", "mailing list visibility") cmd.RegisterFlagCompletionFunc("visibility", completeVisibility) return cmd} func newListsArchiveCommand() *cobra.Command { var days int run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) c.HTTP.Timeout = fileTransferTimeout var ( user *listssrht.User username string err error ) if owner == "" { user, err = listssrht.Archive(c.Client, ctx, name) } else { username = strings.TrimLeft(owner, ownerPrefixes) user, err = listssrht.ArchiveByUser(c.Client, ctx, username, name) } if err != nil { log.Fatal(err) } else if user == nil { log.Fatalf("no such user %q", username) } else if user.List == nil { if owner == "" { log.Fatalf("no such mailing list %s", name) } log.Fatalf("no such mailing list %s/%s/%s", c.BaseURL, owner, name) } url := string(user.List.Archive) if days != 0 { url = fmt.Sprintf("%s?since=%d", url, days) } req, err := http.NewRequestWithContext(ctx, http.MethodGet, string(url), nil) if err != nil { log.Fatalf("Failed to create request to fetch archive: %v", err) } resp, err := c.HTTP.Do(req) if err != nil { log.Fatalf("Failed to fetch archive: %v", err) } defer resp.Body.Close() if _, err := io.Copy(os.Stdout, resp.Body); err != nil { log.Fatalf("Failed to copy to stdout: %v", err) } } cmd := &cobra.Command{ Use: "archive [list]", Short: "Download a mailing list archive", Args: cobra.MaximumNArgs(1), ValidArgsFunction: completeList, Run: run, } cmd.Flags().IntVarP(&days, "days", "d", 0, "number of last days to download") cmd.RegisterFlagCompletionFunc("days", cobra.NoFileCompletions) return cmd} func newListsPatchsetCommand() *cobra.Command { cmd := &cobra.Command{ Use: "patchset", Short: "Manage patchsets", } cmd.AddCommand(newListsPatchsetListCommand()) cmd.AddCommand(newListsPatchsetUpdateCommand()) cmd.AddCommand(newListsPatchsetApplyCommand()) cmd.AddCommand(newListsPatchsetShowCommand()) return cmd} func newListsPatchsetListCommand() *cobra.Command { var byUser bool run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) var ( cursor *listssrht.Cursor patches *listssrht.PatchsetCursor user *listssrht.User username string err error ) if byUser { if len(args) > 0 { username = strings.TrimLeft(name, ownerPrefixes) } } else { if owner != "" { username = strings.TrimLeft(owner, ownerPrefixes) } } err = pagerify(func(p pager) error { if byUser { if username != "" { user, err = listssrht.PatchesByUser(c.Client, ctx, name, cursor) } else { user, err = listssrht.Patches(c.Client, ctx, cursor) } if err != nil { return err } else if user == nil { return fmt.Errorf("no such user %q", name) } patches = user.Patches } else { if username != "" { user, err = listssrht.ListPatchesByUser(c.Client, ctx, username, name, cursor) } else { user, err = listssrht.ListPatches(c.Client, ctx, name, cursor) } if err != nil { return err } else if user == nil { return fmt.Errorf("no such user %q", username) } else if user.List == nil { return fmt.Errorf("no such list %q", name) } patches = user.List.Patches } for _, patchset := range patches.Results { printPatchset(p, byUser, &patchset) } cursor = patches.Cursor if cursor == nil { return pagerDone } return nil }) if err != nil { log.Fatal(err) } } cmd := &cobra.Command{ Use: "list [list]", Short: "List patchsets", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } cmd.Flags().BoolVarP(&byUser, "user", "u", false, "list patches by user") return cmd} func printPatchset(w io.Writer, byUser bool, patchset *listssrht.Patchset) { s := fmt.Sprintf("%s\t%s\t", termfmt.DarkYellow.Sprintf("#%d", patchset.Id), patchset.Status.TermString()) if patchset.Prefix != nil && *patchset.Prefix != "" { s += fmt.Sprintf("[%s] ", *patchset.Prefix) } s += patchset.Subject if patchset.Version != 1 { s += fmt.Sprintf(" v%d", patchset.Version) } created := termfmt.Dim.String(humanize.Time(patchset.Created.Time)) if byUser { s += fmt.Sprintf("\t%s/%s\t%s", patchset.List.Owner.CanonicalName, patchset.List.Name, created) } else { s += fmt.Sprintf("\t%s\t%s", patchset.Submitter.CanonicalName, created) } fmt.Fprintln(w, s)} func newListsPatchsetUpdateCommand() *cobra.Command { var status string run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() patchStatus, err := listssrht.ParsePatchsetStatus(status) if err != nil { log.Fatal(err) } id, instance, err := parsePatchID(ctx, cmd, args[0]) if err != nil { log.Fatal(err) } c := createClientWithInstance("lists", cmd, instance) patch, err := listssrht.UpdatePatchset(c.Client, ctx, id, patchStatus) if err != nil { log.Fatal(err) } else if patch == nil {Lines 1–500 of 1304. Load more
package main import ( "bytes" "context" "errors" "fmt" "io" "log" "net/http" "net/mail" "os" "os/exec" "strings" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "git.sr.ht/~xenrox/hut/srht/listssrht" "git.sr.ht/~xenrox/hut/termfmt" ) func newListsCommand() *cobra.Command { cmd := &cobra.Command{ Use: "lists", Short: "Use the lists API", } cmd.AddCommand(newListsDeleteCommand()) cmd.AddCommand(newListsListCommand()) cmd.AddCommand(newListsSubscribeCommand()) cmd.AddCommand(newListsUnsubscribeCommand()) cmd.AddCommand(newListsCreateCommand()) cmd.AddCommand(newListsArchiveCommand()) cmd.AddCommand(newListsPatchsetCommand()) cmd.AddCommand(newListsACLCommand()) cmd.AddCommand(newListsUserWebhookCommand()) cmd.AddCommand(newListsWebhookCommand()) cmd.AddCommand(newListsSubscriptions()) cmd.PersistentFlags().StringP("mailing-list", "l", "", "mailing list name") cmd.RegisterFlagCompletionFunc("mailing-list", completeList) return cmd } func newListsDeleteCommand() *cobra.Command { var autoConfirm bool run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) id := getMailingListID(c, ctx, name, owner) if !autoConfirm && !getConfirmation(fmt.Sprintf("Do you really want to delete the list %s", name)) { log.Println("Aborted") return } list, err := listssrht.DeleteMailingList(c.Client, ctx, id) if err != nil { log.Fatal(err) } else if list == nil { log.Fatalf("failed to delete list with ID %d", id) } log.Printf("Deleted mailing list %s\n", list.Name) } cmd := &cobra.Command{ Use: "delete [list]", Short: "Delete a mailing list", Args: cobra.MaximumNArgs(1), ValidArgsFunction: completeList, Run: run, } cmd.Flags().BoolVarP(&autoConfirm, "yes", "y", false, "auto confirm") return cmd } func newListsListCommand() *cobra.Command { cmd := &cobra.Command{ Use: "list [username]", Short: "List mailing lists", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, } cmd.Run = func(cmd *cobra.Command, args []string) { ctx := cmd.Context() c := createClient("lists", cmd) var cursor *listssrht.Cursor var username string if len(args) > 0 { username = strings.TrimLeft(args[0], ownerPrefixes) } err := pagerify(func(p pager) error { var lists *listssrht.MailingListCursor if len(username) > 0 { user, err := listssrht.MailingListsByUser(c.Client, ctx, username, cursor) if err != nil { return err } else if user == nil { return errors.New("no such user") } lists = user.Lists } else { var err error user, err := listssrht.MailingLists(c.Client, ctx, cursor) if err != nil { return err } lists = user.Lists } for _, list := range lists.Results { printList(p, &list) } cursor = lists.Cursor if cursor == nil { return pagerDone } return nil }) if err != nil { log.Fatal(err) } } return cmd } func printList(w io.Writer, list *listssrht.MailingList) { fmt.Fprintf(w, "%s (%s)\n", termfmt.Bold.String(list.Name), list.Visibility.TermString()) if list.Description != nil && *list.Description != "" { fmt.Fprintln(w, "\n"+indent(*list.Description, " ")+"\n") } } func newListsSubscribeCommand() *cobra.Command { run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) id := getMailingListID(c, ctx, name, owner) subscription, err := listssrht.MailingListSubscribe(c.Client, ctx, id) if err != nil { log.Fatal(err) } log.Printf("Subscribed to %s/%s/%s\n", c.BaseURL, subscription.List.Owner.CanonicalName, subscription.List.Name) } cmd := &cobra.Command{ Use: "subscribe [list]", Short: "Subscribe to a mailing list", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } return cmd } func newListsUnsubscribeCommand() *cobra.Command { run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) id := getMailingListID(c, ctx, name, owner) subscription, err := listssrht.MailingListUnsubscribe(c.Client, ctx, id) if err != nil { log.Fatal(err) } else if subscription == nil { log.Fatalf("you were not subscribed to %s/%s/%s", c.BaseURL, owner, name) } log.Printf("Unsubscribed from %s/%s/%s\n", c.BaseURL, subscription.List.Owner.CanonicalName, subscription.List.Name) } cmd := &cobra.Command{ Use: "unsubscribe [list]", Short: "Unubscribe from a mailing list", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } return cmd } const listsCreatePrefill = ` <!-- Please write the Markdown description of the new mailing list above. -->` func newListsCreateCommand() *cobra.Command { var visibility string var stdin bool run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() c := createClient("lists", cmd) listVisibility, err := listssrht.ParseVisibility(visibility) if err != nil { log.Fatal(err) } var description *string if stdin { b, err := io.ReadAll(os.Stdin) if err != nil { log.Fatalf("failed to read mailing list description: %v", err) } desc := string(b) description = &desc } else { text, err := getInputWithEditor("hut_mailing-list*.md", listsCreatePrefill) if err != nil { log.Fatalf("failed to read mailing list description: %v", err) } text = dropComment(text, listsCreatePrefill) description = &text } list, err := listssrht.CreateMailingList(c.Client, ctx, args[0], description, listVisibility) if err != nil { log.Fatal(err) } else if list == nil { log.Fatal("failed to create mailing list") } log.Printf("Created mailing list %q\n", list.Name) } cmd := &cobra.Command{ Use: "create <name>", Short: "Create a mailing list", Args: cobra.ExactArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } cmd.Flags().BoolVar(&stdin, "stdin", false, "read mailing list from stdin") cmd.Flags().StringVarP(&visibility, "visibility", "v", "public", "mailing list visibility") cmd.RegisterFlagCompletionFunc("visibility", completeVisibility) return cmd } func newListsArchiveCommand() *cobra.Command { var days int run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) c.HTTP.Timeout = fileTransferTimeout var ( user *listssrht.User username string err error ) if owner == "" { user, err = listssrht.Archive(c.Client, ctx, name) } else { username = strings.TrimLeft(owner, ownerPrefixes) user, err = listssrht.ArchiveByUser(c.Client, ctx, username, name) } if err != nil { log.Fatal(err) } else if user == nil { log.Fatalf("no such user %q", username) } else if user.List == nil { if owner == "" { log.Fatalf("no such mailing list %s", name) } log.Fatalf("no such mailing list %s/%s/%s", c.BaseURL, owner, name) } url := string(user.List.Archive) if days != 0 { url = fmt.Sprintf("%s?since=%d", url, days) } req, err := http.NewRequestWithContext(ctx, http.MethodGet, string(url), nil) if err != nil { log.Fatalf("Failed to create request to fetch archive: %v", err) } resp, err := c.HTTP.Do(req) if err != nil { log.Fatalf("Failed to fetch archive: %v", err) } defer resp.Body.Close() if _, err := io.Copy(os.Stdout, resp.Body); err != nil { log.Fatalf("Failed to copy to stdout: %v", err) } } cmd := &cobra.Command{ Use: "archive [list]", Short: "Download a mailing list archive", Args: cobra.MaximumNArgs(1), ValidArgsFunction: completeList, Run: run, } cmd.Flags().IntVarP(&days, "days", "d", 0, "number of last days to download") cmd.RegisterFlagCompletionFunc("days", cobra.NoFileCompletions) return cmd } func newListsPatchsetCommand() *cobra.Command { cmd := &cobra.Command{ Use: "patchset", Short: "Manage patchsets", } cmd.AddCommand(newListsPatchsetListCommand()) cmd.AddCommand(newListsPatchsetUpdateCommand()) cmd.AddCommand(newListsPatchsetApplyCommand()) cmd.AddCommand(newListsPatchsetShowCommand()) return cmd } func newListsPatchsetListCommand() *cobra.Command { var byUser bool run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() var name, owner, instance string if len(args) > 0 { name, owner, instance = parseMailingListName(args[0]) } else { var err error name, owner, instance, err = getMailingListName(ctx, cmd) if err != nil { log.Fatal(err) } } c := createClientWithInstance("lists", cmd, instance) var ( cursor *listssrht.Cursor patches *listssrht.PatchsetCursor user *listssrht.User username string err error ) if byUser { if len(args) > 0 { username = strings.TrimLeft(name, ownerPrefixes) } } else { if owner != "" { username = strings.TrimLeft(owner, ownerPrefixes) } } err = pagerify(func(p pager) error { if byUser { if username != "" { user, err = listssrht.PatchesByUser(c.Client, ctx, name, cursor) } else { user, err = listssrht.Patches(c.Client, ctx, cursor) } if err != nil { return err } else if user == nil { return fmt.Errorf("no such user %q", name) } patches = user.Patches } else { if username != "" { user, err = listssrht.ListPatchesByUser(c.Client, ctx, username, name, cursor) } else { user, err = listssrht.ListPatches(c.Client, ctx, name, cursor) } if err != nil { return err } else if user == nil { return fmt.Errorf("no such user %q", username) } else if user.List == nil { return fmt.Errorf("no such list %q", name) } patches = user.List.Patches } for _, patchset := range patches.Results { printPatchset(p, byUser, &patchset) } cursor = patches.Cursor if cursor == nil { return pagerDone } return nil }) if err != nil { log.Fatal(err) } } cmd := &cobra.Command{ Use: "list [list]", Short: "List patchsets", Args: cobra.MaximumNArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } cmd.Flags().BoolVarP(&byUser, "user", "u", false, "list patches by user") return cmd } func printPatchset(w io.Writer, byUser bool, patchset *listssrht.Patchset) { s := fmt.Sprintf("%s\t%s\t", termfmt.DarkYellow.Sprintf("#%d", patchset.Id), patchset.Status.TermString()) if patchset.Prefix != nil && *patchset.Prefix != "" { s += fmt.Sprintf("[%s] ", *patchset.Prefix) } s += patchset.Subject if patchset.Version != 1 { s += fmt.Sprintf(" v%d", patchset.Version) } created := termfmt.Dim.String(humanize.Time(patchset.Created.Time)) if byUser { s += fmt.Sprintf("\t%s/%s\t%s", patchset.List.Owner.CanonicalName, patchset.List.Name, created) } else { s += fmt.Sprintf("\t%s\t%s", patchset.Submitter.CanonicalName, created) } fmt.Fprintln(w, s) } func newListsPatchsetUpdateCommand() *cobra.Command { var status string run := func(cmd *cobra.Command, args []string) { ctx := cmd.Context() patchStatus, err := listssrht.ParsePatchsetStatus(status) if err != nil { log.Fatal(err) } id, instance, err := parsePatchID(ctx, cmd, args[0]) if err != nil { log.Fatal(err) } c := createClientWithInstance("lists", cmd, instance) patch, err := listssrht.UpdatePatchset(c.Client, ctx, id, patchStatus) if err != nil { log.Fatal(err) } else if patch == nil {