package cmd import ( "fmt" "code.gitea.io/sdk/gitea" "forgejo.zerova.net/public/fgj-sid/internal/api" "forgejo.zerova.net/public/fgj-sid/internal/config" "github.com/spf13/cobra" ) var milestoneIssuesCmd = &cobra.Command{ Use: "issues", Aliases: []string{"i"}, Short: "Manage issues associated with a milestone", Long: "Associate or disassociate issues with a milestone.", } var milestoneIssuesAddCmd = &cobra.Command{ Use: "add ...", Short: "Add issues to a milestone", Long: "Associate one or more issues with a milestone.", Example: ` # Add issues #5 and #7 to milestone "v1.0" fgj milestone issues add "v1.0" 5 7 # Add issue #12 to milestone with ID 3 in a specific repo fgj milestone issues add 3 12 -R owner/repo`, Args: cobra.MinimumNArgs(2), RunE: runMilestoneIssuesAdd, } var milestoneIssuesRemoveCmd = &cobra.Command{ Use: "remove ...", Short: "Remove issues from a milestone", Long: "Disassociate one or more issues from a milestone.", Example: ` # Remove issues #5 and #7 from milestone "v1.0" fgj milestone issues remove "v1.0" 5 7 # Remove issue #12 from milestone with ID 3 in a specific repo fgj milestone issues remove 3 12 -R owner/repo`, Args: cobra.MinimumNArgs(2), RunE: runMilestoneIssuesRemove, } func init() { milestoneCmd.AddCommand(milestoneIssuesCmd) milestoneIssuesCmd.AddCommand(milestoneIssuesAddCmd) milestoneIssuesCmd.AddCommand(milestoneIssuesRemoveCmd) addRepoFlags(milestoneIssuesAddCmd) addRepoFlags(milestoneIssuesRemoveCmd) } func runMilestoneIssuesAdd(cmd *cobra.Command, args []string) error { repo, _ := cmd.Flags().GetString("repo") owner, name, err := parseRepo(repo) if err != nil { return err } cfg, err := config.Load() if err != nil { return err } client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd()) if err != nil { return err } ios.StartSpinner("Fetching milestone...") ms, err := resolveMilestone(client, owner, name, args[0]) ios.StopSpinner() if err != nil { return err } milestoneID := ms.ID cs := ios.ColorScheme() hadError := false for _, arg := range args[1:] { issueNum, parseErr := parseIssueArg(arg) if parseErr != nil { fmt.Fprintf(ios.ErrOut, "invalid issue number %q: %v\n", arg, parseErr) hadError = true continue } _, _, editErr := client.EditIssue(owner, name, issueNum, gitea.EditIssueOption{ Milestone: &milestoneID, }) if editErr != nil { fmt.Fprintf(ios.ErrOut, "failed to add issue #%d to milestone %q: %v\n", issueNum, ms.Title, editErr) hadError = true continue } fmt.Fprintf(ios.Out, "%s Added issue #%d to milestone %q\n", cs.SuccessIcon(), issueNum, ms.Title) } if hadError { return fmt.Errorf("one or more issues could not be added to milestone %q", ms.Title) } return nil } func runMilestoneIssuesRemove(cmd *cobra.Command, args []string) error { repo, _ := cmd.Flags().GetString("repo") owner, name, err := parseRepo(repo) if err != nil { return err } cfg, err := config.Load() if err != nil { return err } client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd()) if err != nil { return err } ios.StartSpinner("Fetching milestone...") ms, err := resolveMilestone(client, owner, name, args[0]) ios.StopSpinner() if err != nil { return err } cs := ios.ColorScheme() hadError := false var zero int64 = 0 for _, arg := range args[1:] { issueNum, parseErr := parseIssueArg(arg) if parseErr != nil { fmt.Fprintf(ios.ErrOut, "invalid issue number %q: %v\n", arg, parseErr) hadError = true continue } // Setting Milestone to a pointer-to-zero clears the milestone association // in Gitea's API (PATCH /repos/{owner}/{repo}/issues/{num} with {"milestone": 0}). _, _, editErr := client.EditIssue(owner, name, issueNum, gitea.EditIssueOption{ Milestone: &zero, }) if editErr != nil { fmt.Fprintf(ios.ErrOut, "failed to remove issue #%d from milestone %q: %v\n", issueNum, ms.Title, editErr) hadError = true continue } fmt.Fprintf(ios.Out, "%s Removed issue #%d from milestone %q\n", cs.SuccessIcon(), issueNum, ms.Title) } if hadError { return fmt.Errorf("one or more issues could not be removed from milestone %q", ms.Title) } return nil }