diff --git a/cmd/issue.go b/cmd/issue.go index d582d01..f008f83 100644 --- a/cmd/issue.go +++ b/cmd/issue.go @@ -84,6 +84,7 @@ func init() { issueCreateCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format") issueCreateCmd.Flags().StringP("title", "t", "", "Title for the issue") issueCreateCmd.Flags().StringP("body", "b", "", "Body for the issue") + issueCreateCmd.Flags().StringSliceP("label", "l", nil, "Labels to add (can be specified multiple times)") issueCommentCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format") issueCommentCmd.Flags().StringP("body", "b", "", "Comment body") @@ -95,6 +96,8 @@ func init() { issueEditCmd.Flags().StringP("title", "t", "", "New title for the issue") issueEditCmd.Flags().StringP("body", "b", "", "New body for the issue") issueEditCmd.Flags().StringP("state", "s", "", "New state for the issue (open or closed)") + issueEditCmd.Flags().StringSlice("add-label", nil, "Labels to add (can be specified multiple times)") + issueEditCmd.Flags().StringSlice("remove-label", nil, "Labels to remove (can be specified multiple times)") } func runIssueList(cmd *cobra.Command, args []string) error { @@ -233,6 +236,7 @@ func runIssueCreate(cmd *cobra.Command, args []string) error { repo, _ := cmd.Flags().GetString("repo") title, _ := cmd.Flags().GetString("title") body, _ := cmd.Flags().GetString("body") + labelNames, _ := cmd.Flags().GetStringSlice("label") owner, name, err := parseRepo(repo) if err != nil { @@ -253,9 +257,18 @@ func runIssueCreate(cmd *cobra.Command, args []string) error { return err } + var labelIDs []int64 + if len(labelNames) > 0 { + labelIDs, err = resolveLabelIDs(client, owner, name, labelNames) + if err != nil { + return err + } + } + issue, _, err := client.CreateIssue(owner, name, gitea.CreateIssueOption{ - Title: title, - Body: body, + Title: title, + Body: body, + Labels: labelIDs, }) if err != nil { return fmt.Errorf("failed to create issue: %w", err) @@ -357,6 +370,8 @@ func runIssueEdit(cmd *cobra.Command, args []string) error { title, _ := cmd.Flags().GetString("title") body, _ := cmd.Flags().GetString("body") stateStr, _ := cmd.Flags().GetString("state") + addLabelNames, _ := cmd.Flags().GetStringSlice("add-label") + removeLabelNames, _ := cmd.Flags().GetStringSlice("remove-label") issueNumber, err := strconv.ParseInt(args[0], 10, 64) if err != nil { @@ -368,8 +383,8 @@ func runIssueEdit(cmd *cobra.Command, args []string) error { return err } - if title == "" && body == "" && stateStr == "" { - return fmt.Errorf("at least one of --title, --body, or --state must be provided") + if title == "" && body == "" && stateStr == "" && len(addLabelNames) == 0 && len(removeLabelNames) == 0 { + return fmt.Errorf("at least one of --title, --body, --state, --add-label, or --remove-label must be provided") } cfg, err := config.Load() @@ -405,12 +420,73 @@ func runIssueEdit(cmd *cobra.Command, args []string) error { } } - _, _, err = client.EditIssue(owner, name, issueNumber, editOpt) - if err != nil { - return fmt.Errorf("failed to edit issue: %w", err) + if title != "" || body != "" || stateStr != "" { + _, _, err = client.EditIssue(owner, name, issueNumber, editOpt) + if err != nil { + return fmt.Errorf("failed to edit issue: %w", err) + } + } + + if len(addLabelNames) > 0 { + labelIDs, err := resolveLabelIDs(client, owner, name, addLabelNames) + if err != nil { + return err + } + _, _, err = client.AddIssueLabels(owner, name, issueNumber, gitea.IssueLabelsOption{ + Labels: labelIDs, + }) + if err != nil { + return fmt.Errorf("failed to add labels: %w", err) + } + } + + if len(removeLabelNames) > 0 { + labelIDs, err := resolveLabelIDs(client, owner, name, removeLabelNames) + if err != nil { + return err + } + for _, labelID := range labelIDs { + _, err = client.DeleteIssueLabel(owner, name, issueNumber, labelID) + if err != nil { + return fmt.Errorf("failed to remove label %d: %w", labelID, err) + } + } } fmt.Printf("Issue #%d updated\n", issueNumber) return nil } + +func resolveLabelIDs(client *api.Client, owner, name string, labelNames []string) ([]int64, error) { + if len(labelNames) == 0 { + return nil, nil + } + + labels, _, err := client.ListRepoLabels(owner, name, gitea.ListLabelsOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to list labels: %w", err) + } + + labelNameToID := make(map[string]int64) + for _, label := range labels { + labelNameToID[label.Name] = label.ID + } + + var labelIDs []int64 + var missingLabels []string + for _, labelName := range labelNames { + labelID, exists := labelNameToID[labelName] + if !exists { + missingLabels = append(missingLabels, labelName) + continue + } + labelIDs = append(labelIDs, labelID) + } + + if len(missingLabels) > 0 { + return nil, fmt.Errorf("labels not found: %s", strings.Join(missingLabels, ", ")) + } + + return labelIDs, nil +}