Second pass of tea-parity work:
- fgj webhook {list,create,update,delete}: full CRUD over repo webhooks.
Create supports all standard hook types (gitea, slack, discord, etc.),
event selection, content type, secret, branch filter, auth header.
Update is partial — flags you omit leave existing config unchanged.
- fgj repo delete: type-to-confirm deletion; --yes skips for scripts;
refuses without a TTY unless --yes is passed.
- fgj repo search: SDK SearchRepos with query, topic/description,
private/archived, --type (source/fork/mirror), owner, sort/order.
- fgj admin user list: admin-gated user enumeration.
- fgj pr clean: delete the local branch from 'pr checkout'. Refuses
if the PR is still open (use --force) or if the branch is currently
checked out.
- fgj pr review-comments: list inline review comments across every
review on a PR (ListPullReviews + ListPullReviewComments per review).
- fgj pr resolve / unresolve: mark review comments as (un)resolved.
Uses raw POST since SDK v0.22.1 predates these endpoints; requires
Forgejo 8.x+ / Gitea 1.22+ server-side.
All share the standard parseRepo + config.Load + NewClientFromConfig
pattern; list commands support --json / --jq.
98 lines
2.8 KiB
Go
98 lines
2.8 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"forgejo.zerova.net/public/fgj-sid/internal/api"
|
|
"forgejo.zerova.net/public/fgj-sid/internal/config"
|
|
"forgejo.zerova.net/public/fgj-sid/internal/git"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var prCleanCmd = &cobra.Command{
|
|
Use: "clean <number>",
|
|
Short: "Delete the local branch created by 'pr checkout'",
|
|
Long: `Remove the local branch that was checked out for a pull request.
|
|
|
|
For safety, the PR must be closed (merged or declined). If the branch is
|
|
currently checked out, switch away first — this command refuses to delete
|
|
your active branch.
|
|
|
|
Pass --force to delete the local branch even if the PR is still open.`,
|
|
Example: ` # Clean up after a merged PR
|
|
fgj pr clean 42
|
|
|
|
# Force-delete local branch for an open PR
|
|
fgj pr clean 42 --force`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: runPRClean,
|
|
}
|
|
|
|
func init() {
|
|
prCmd.AddCommand(prCleanCmd)
|
|
addRepoFlags(prCleanCmd)
|
|
prCleanCmd.Flags().Bool("force", false, "Delete the local branch even if the PR is still open")
|
|
}
|
|
|
|
func runPRClean(cmd *cobra.Command, args []string) error {
|
|
prNumber, err := parseIssueArg(args[0])
|
|
if err != nil {
|
|
return fmt.Errorf("invalid pull request number: %w", err)
|
|
}
|
|
|
|
repoFlag, _ := cmd.Flags().GetString("repo")
|
|
owner, name, err := parseRepo(repoFlag)
|
|
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
|
|
}
|
|
|
|
force, _ := cmd.Flags().GetBool("force")
|
|
|
|
pr, _, err := client.GetPullRequest(owner, name, prNumber)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get pull request: %w", err)
|
|
}
|
|
|
|
if !force && string(pr.State) == "open" {
|
|
return fmt.Errorf("PR #%d is still open; refuse to delete local branch without --force", prNumber)
|
|
}
|
|
|
|
headBranch := pr.Head.Ref
|
|
if headBranch == "" {
|
|
return fmt.Errorf("PR #%d has no head branch to clean (it may have been deleted already)", prNumber)
|
|
}
|
|
|
|
// Refuse to delete the current branch.
|
|
current, err := git.GetCurrentBranch()
|
|
if err == nil && current == headBranch {
|
|
return fmt.Errorf("branch %q is currently checked out; switch to another branch first (e.g. 'git switch main')", headBranch)
|
|
}
|
|
|
|
// Check local branch exists.
|
|
if out, _ := exec.Command("git", "rev-parse", "--verify", "--quiet", "refs/heads/"+headBranch).Output(); len(strings.TrimSpace(string(out))) == 0 {
|
|
fmt.Fprintf(ios.ErrOut, "Local branch %q not found; nothing to clean.\n", headBranch)
|
|
return nil
|
|
}
|
|
|
|
delCmd := exec.Command("git", "branch", "-D", headBranch)
|
|
delCmd.Stdout = ios.Out
|
|
delCmd.Stderr = ios.ErrOut
|
|
if err := delCmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to delete local branch %q: %w", headBranch, err)
|
|
}
|
|
|
|
cs := ios.ColorScheme()
|
|
fmt.Fprintf(ios.Out, "%s Deleted local branch %q\n", cs.SuccessIcon(), headBranch)
|
|
return nil
|
|
}
|