mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
- **switch tea to the Cobra command tree:** `internal/app` wires the packages from parts 1–4 into explicit noun/verb commands with `--repo`, `--json` / `--jq`, `--sudo` and `--debug`; `main.go` points at it. Build, release and docs tooling (`tools/cli-docs`, Makefile, goreleaser, snap, CI) and README / CONTRIBUTING are updated. - **remove the urfave/cli command tree:** deletes `cmd/`, `modules/`, the old integration tests, contrib completion scripts and the generated `docs/CLI.md`, and drops their dependencies. This commit only deletes. ## Breaking changes This is a breaking release. It requires Gitea 28 or newer; configuration moves to separate `config.yml` and `hosts.yml` files and requires fresh authentication, and command names, aliases, flags and output formats change. `docs/migration-1.0.md` maps every old command, flag and environment variable to its replacement. ## Issues fixes #1118 fixes #1116 fixes #1115 fixes #1094 fixes #1091 fixes #1073 fixes #1052 fixes #1032 fixes #1023 fixes #966 fixes #908 fixes #833 fixes #831 fixes #817 fixes #804 fixes #779 fixes #770 fixes #737 fixes #697 fixes #726 fixes #677 fixes #672 fixes #633 fixes #632 fixes #560 fixes #556 fixes #523 fixes #516 fixes #510 fixes #504 fixes #500 fixes #482 fixes #406 fixes #403 fixes #373 fixes #351 fixes #344 fixes #326 fixes #325 fixes #323 fixes #246 fixes #240 fixes #232 fixes #197 fixes #172 fixes #141 fixes #69 fixes #1110 fixes #569 fixes #480 fixes #666 fixes #670 fixes #457 fixes #643 fixes #498 fixes #490 fixes #1069 fixes #834 fixes #602 fixes #328 fixes #417 fixes #571 fixes #1029 fixes #489 fixes #1050 fixes #162 fixes #430 fixes #1087 fixes #683 Reviewed-on: https://gitea.com/gitea/tea/pulls/1126 Reviewed-by: TheFox0x7 <95654+thefox0x7@noreply.gitea.com>
73 lines
2.5 KiB
Go
73 lines
2.5 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package app
|
|
|
|
import (
|
|
"bufio"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"gitea.dev/tea/internal/clierr"
|
|
"gitea.dev/tea/internal/services"
|
|
)
|
|
|
|
var labelColor = regexp.MustCompile(`^[0-9a-fA-F]{6}$`)
|
|
|
|
// parseLabelFile reads "#color name ;description" rows, skipping blank and comment rows.
|
|
func parseLabelFile(r io.Reader) ([]services.LabelOptions, error) {
|
|
var labels []services.LabelOptions
|
|
scanner := bufio.NewScanner(r)
|
|
for line := 1; scanner.Scan(); line++ {
|
|
label, ok, err := parseLabelRow(scanner.Text(), line)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if ok {
|
|
labels = append(labels, label)
|
|
}
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
if len(labels) == 0 {
|
|
return nil, clierr.Wrap(clierr.Usage, errors.New("label file contains no labels"))
|
|
}
|
|
return labels, nil
|
|
}
|
|
|
|
func parseLabelRow(text string, line int) (services.LabelOptions, bool, error) {
|
|
raw := strings.TrimSpace(text)
|
|
parts := strings.SplitN(raw, ";", 2)
|
|
fields := strings.Fields(parts[0])
|
|
// Rows start with an optional "#" before the color, as Gitea's label templates do.
|
|
if raw == "" || strings.HasPrefix(raw, "#") && !labelColor.MatchString(strings.TrimPrefix(fields[0], "#")) {
|
|
return services.LabelOptions{}, false, nil
|
|
}
|
|
if len(fields) < 2 {
|
|
return services.LabelOptions{}, false, clierr.Wrap(clierr.Usage, fmt.Errorf("invalid label row %d", line))
|
|
}
|
|
color, name, description := strings.TrimPrefix(fields[0], "#"), strings.Join(fields[1:], " "), ""
|
|
if len(parts) == 2 {
|
|
description = strings.TrimSpace(parts[1])
|
|
}
|
|
if !labelColor.MatchString(color) {
|
|
return services.LabelOptions{}, false, clierr.Wrap(clierr.Usage, fmt.Errorf("invalid color on row %d", line))
|
|
}
|
|
return services.LabelOptions{Name: &name, Color: &color, Description: &description}, true, nil
|
|
}
|
|
|
|
// formatLabel renders a label as a label file row, rejecting labels the row cannot reproduce.
|
|
func formatLabel(label services.Label) (string, error) {
|
|
color := strings.TrimPrefix(label.Color, "#")
|
|
row := fmt.Sprintf("#%s %s ;%s", color, label.Name, label.Description)
|
|
parsed, ok, err := parseLabelRow(row, 1)
|
|
if err != nil || !ok || strings.ContainsAny(row, "\r\n") || *parsed.Name != label.Name || *parsed.Color != color || *parsed.Description != label.Description {
|
|
return "", errors.New("label cannot be represented in the import format; use label export --json to preserve its text")
|
|
}
|
|
return row + "\n", nil
|
|
}
|