New commands: - fgj label list/create/edit/delete - fgj milestone list/view/create/edit/delete - fgj wiki list/view/create/edit/delete Enhanced: - fgj issue edit --add-dependency/--remove-dependency
278 lines
6.8 KiB
Go
278 lines
6.8 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"text/tabwriter"
|
|
|
|
"code.gitea.io/sdk/gitea"
|
|
"forgejo.zerova.net/sid/fgj-sid/internal/api"
|
|
"forgejo.zerova.net/sid/fgj-sid/internal/config"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var labelCmd = &cobra.Command{
|
|
Use: "label",
|
|
Short: "Manage labels",
|
|
Long: "List, create, edit, and delete repository labels.",
|
|
}
|
|
|
|
var labelListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List labels for a repository",
|
|
Long: "List all labels defined in a repository.",
|
|
Example: ` # List labels for the current repository
|
|
fgj label list
|
|
|
|
# List labels for a specific repository
|
|
fgj label list -R owner/repo
|
|
|
|
# Output as JSON
|
|
fgj label list --json`,
|
|
RunE: runLabelList,
|
|
}
|
|
|
|
var labelCreateCmd = &cobra.Command{
|
|
Use: "create <name>",
|
|
Short: "Create a label",
|
|
Long: "Create a new label in a repository.",
|
|
Example: ` # Create a label with a color
|
|
fgj label create bug -c ff0000
|
|
|
|
# Create a label with color and description
|
|
fgj label create feature -c 00ff00 -d "New feature request"
|
|
|
|
# Create a label in a specific repository
|
|
fgj label create urgent -c ff0000 -R owner/repo`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: runLabelCreate,
|
|
}
|
|
|
|
var labelEditCmd = &cobra.Command{
|
|
Use: "edit <name>",
|
|
Short: "Edit a label",
|
|
Long: "Edit an existing label in a repository.",
|
|
Example: ` # Rename a label
|
|
fgj label edit bug --name bugfix
|
|
|
|
# Change the color of a label
|
|
fgj label edit bug -c 00ff00
|
|
|
|
# Update description
|
|
fgj label edit bug -d "Something is broken"`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: runLabelEdit,
|
|
}
|
|
|
|
var labelDeleteCmd = &cobra.Command{
|
|
Use: "delete <name>",
|
|
Short: "Delete a label",
|
|
Long: "Delete a label from a repository.",
|
|
Example: ` # Delete a label
|
|
fgj label delete bug
|
|
|
|
# Delete a label from a specific repository
|
|
fgj label delete bug -R owner/repo`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: runLabelDelete,
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(labelCmd)
|
|
labelCmd.AddCommand(labelListCmd)
|
|
labelCmd.AddCommand(labelCreateCmd)
|
|
labelCmd.AddCommand(labelEditCmd)
|
|
labelCmd.AddCommand(labelDeleteCmd)
|
|
|
|
labelListCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
|
labelListCmd.Flags().Bool("json", false, "Output as JSON")
|
|
|
|
labelCreateCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
|
labelCreateCmd.Flags().StringP("color", "c", "", "Label color (hex, e.g. 00ff00)")
|
|
labelCreateCmd.Flags().StringP("description", "d", "", "Label description")
|
|
labelCreateCmd.Flags().Bool("json", false, "Output as JSON")
|
|
|
|
labelEditCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
|
labelEditCmd.Flags().String("name", "", "New name for the label")
|
|
labelEditCmd.Flags().StringP("color", "c", "", "New color (hex, e.g. 00ff00)")
|
|
labelEditCmd.Flags().StringP("description", "d", "", "New description")
|
|
labelEditCmd.Flags().Bool("json", false, "Output as JSON")
|
|
|
|
labelDeleteCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
|
}
|
|
|
|
func newLabelClient(cmd *cobra.Command) (*api.Client, string, string, error) {
|
|
repo, _ := cmd.Flags().GetString("repo")
|
|
owner, name, err := parseRepo(repo)
|
|
if err != nil {
|
|
return nil, "", "", err
|
|
}
|
|
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
return nil, "", "", err
|
|
}
|
|
|
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
|
if err != nil {
|
|
return nil, "", "", err
|
|
}
|
|
|
|
return client, owner, name, nil
|
|
}
|
|
|
|
// findLabelByName lists all repo labels and returns the one matching the given name.
|
|
func findLabelByName(client *api.Client, owner, repo, labelName string) (*gitea.Label, error) {
|
|
labels, _, err := client.ListRepoLabels(owner, repo, gitea.ListLabelsOptions{})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list labels: %w", err)
|
|
}
|
|
|
|
for _, l := range labels {
|
|
if strings.EqualFold(l.Name, labelName) {
|
|
return l, nil
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("label not found: %s", labelName)
|
|
}
|
|
|
|
func runLabelList(cmd *cobra.Command, args []string) error {
|
|
client, owner, name, err := newLabelClient(cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
labels, _, err := client.ListRepoLabels(owner, name, gitea.ListLabelsOptions{})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list labels: %w", err)
|
|
}
|
|
|
|
jsonFlag, _ := cmd.Flags().GetBool("json")
|
|
if jsonFlag {
|
|
return writeJSON(labels)
|
|
}
|
|
|
|
if len(labels) == 0 {
|
|
fmt.Println("No labels found")
|
|
return nil
|
|
}
|
|
|
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
_, _ = fmt.Fprintf(w, "NAME\tCOLOR\tDESCRIPTION\n")
|
|
for _, l := range labels {
|
|
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", l.Name, l.Color, l.Description)
|
|
}
|
|
_ = w.Flush()
|
|
|
|
return nil
|
|
}
|
|
|
|
func runLabelCreate(cmd *cobra.Command, args []string) error {
|
|
labelName := args[0]
|
|
color, _ := cmd.Flags().GetString("color")
|
|
description, _ := cmd.Flags().GetString("description")
|
|
|
|
client, owner, name, err := newLabelClient(cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
label, _, err := client.CreateLabel(owner, name, gitea.CreateLabelOption{
|
|
Name: labelName,
|
|
Color: color,
|
|
Description: description,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create label: %w", err)
|
|
}
|
|
|
|
jsonFlag, _ := cmd.Flags().GetBool("json")
|
|
if jsonFlag {
|
|
return writeJSON(label)
|
|
}
|
|
|
|
fmt.Printf("Label created: %s\n", label.Name)
|
|
return nil
|
|
}
|
|
|
|
func runLabelEdit(cmd *cobra.Command, args []string) error {
|
|
labelName := args[0]
|
|
|
|
client, owner, name, err := newLabelClient(cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
existing, err := findLabelByName(client, owner, name, labelName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
opt := gitea.EditLabelOption{}
|
|
changed := false
|
|
|
|
if cmd.Flags().Changed("name") {
|
|
n, _ := cmd.Flags().GetString("name")
|
|
opt.Name = &n
|
|
changed = true
|
|
}
|
|
if cmd.Flags().Changed("color") {
|
|
c, _ := cmd.Flags().GetString("color")
|
|
opt.Color = &c
|
|
changed = true
|
|
}
|
|
if cmd.Flags().Changed("description") {
|
|
d, _ := cmd.Flags().GetString("description")
|
|
opt.Description = &d
|
|
changed = true
|
|
}
|
|
|
|
if !changed {
|
|
return fmt.Errorf("no changes specified; use flags like --name, --color, or --description")
|
|
}
|
|
|
|
label, _, err := client.EditLabel(owner, name, existing.ID, opt)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to edit label: %w", err)
|
|
}
|
|
|
|
jsonFlag, _ := cmd.Flags().GetBool("json")
|
|
if jsonFlag {
|
|
return writeJSON(label)
|
|
}
|
|
|
|
fmt.Printf("Label updated: %s\n", label.Name)
|
|
return nil
|
|
}
|
|
|
|
func runLabelDelete(cmd *cobra.Command, args []string) error {
|
|
labelName := args[0]
|
|
|
|
client, owner, name, err := newLabelClient(cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
existing, err := findLabelByName(client, owner, name, labelName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("Are you sure you want to delete label %q? (y/N): ", labelName)
|
|
var confirm string
|
|
_, _ = fmt.Scanln(&confirm)
|
|
if strings.ToLower(confirm) != "y" {
|
|
fmt.Println("Aborted")
|
|
return nil
|
|
}
|
|
|
|
_, err = client.DeleteLabel(owner, name, existing.ID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete label: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Label deleted: %s\n", labelName)
|
|
return nil
|
|
}
|