Files
HarborForge.Cli/cmd/hf/main.go
2026-03-21 14:37:42 +00:00

259 lines
6.1 KiB
Go

package main
import (
"fmt"
"os"
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/commands"
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/help"
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/mode"
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/output"
)
func main() {
args := os.Args[1:]
// Parse global flags first
args = parseGlobalFlags(args)
if len(args) == 0 {
fmt.Print(help.RenderTopHelp(commands.Version, help.CommandSurface()))
return
}
switch args[0] {
case "--help", "-h":
fmt.Print(help.RenderTopHelp(commands.Version, help.CommandSurface()))
case "--help-brief":
fmt.Print(help.RenderTopHelpBrief(commands.Version, help.CommandSurface()))
case "version":
handleLeafOrRun("version", args[1:], commands.RunVersion)
case "health":
handleLeafOrRun("health", args[1:], commands.RunHealth)
case "config":
handleConfig(args[1:])
default:
if group, ok := findGroup(args[0]); ok {
handleGroup(group, args[1:])
return
}
fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
fmt.Fprintf(os.Stderr, "Run 'hf --help' for usage.\n")
os.Exit(1)
}
}
// parseGlobalFlags extracts --json from anywhere in the args and returns remaining args.
func parseGlobalFlags(args []string) []string {
var remaining []string
for _, a := range args {
switch a {
case "--json":
output.JSONMode = true
default:
remaining = append(remaining, a)
}
}
return remaining
}
func handleLeafOrRun(name string, args []string, run func()) {
if isHelpFlagOnly(args) {
fmt.Printf("hf %s\n", name)
return
}
if len(args) > 0 {
output.Errorf("unknown arguments for %s: %v", name, args)
}
run()
}
func handleConfig(args []string) {
if isHelpFlagOnly(args) {
runConfigHelp()
return
}
if len(args) == 0 {
commands.RunConfigShow()
return
}
for i := 0; i < len(args); i++ {
switch args[i] {
case "--url":
if i+1 >= len(args) {
output.Error("usage: hf config --url <hf-url>")
}
commands.RunConfigURL(args[i+1])
return
case "--acc-mgr-token":
if i+1 >= len(args) {
output.Error("usage: hf config --acc-mgr-token <token>")
}
commands.RunConfigAccMgrToken(args[i+1])
return
default:
output.Errorf("unknown config flag: %s", args[i])
}
}
}
func runConfigHelp() {
fmt.Println("hf config - View and manage CLI configuration")
fmt.Println()
fmt.Println("Usage:")
fmt.Println(" hf config Show current config")
fmt.Println(" hf config --url <hf-url> Set HarborForge API URL")
if !mode.IsPaddedCell() {
fmt.Println(" hf config --acc-mgr-token <token> Set account-manager token")
}
}
func handleGroup(group help.Group, args []string) {
if len(args) == 0 || isHelpFlagOnly(args) {
fmt.Print(help.RenderGroupHelp(group.Name, group.SubCommands))
return
}
if len(args) == 1 && args[0] == "--help-brief" {
fmt.Print(help.RenderGroupHelpBrief(group.Name, group.SubCommands))
return
}
sub, ok := findSubCommand(group, args[0])
if !ok {
output.Errorf("unknown %s subcommand: %s", group.Name, args[0])
}
if len(args) > 1 && isHelpFlagOnly(args[1:]) {
if !sub.Permitted {
fmt.Println(help.RenderNotPermitted(group.Name, sub.Name))
return
}
fmt.Printf("hf %s %s\n", group.Name, sub.Name)
return
}
if !sub.Permitted {
fmt.Println(help.RenderNotPermitted(group.Name, sub.Name))
return
}
// Dispatch implemented commands
remaining := args[1:]
switch group.Name {
case "user":
handleUserCommand(sub.Name, remaining)
return
}
output.Errorf("hf %s %s is recognized but not implemented yet", group.Name, sub.Name)
}
func handleUserCommand(subCmd string, args []string) {
// Extract --token and --acc-mgr-token flags from args
tokenFlag := ""
accMgrTokenFlag := ""
var filtered []string
for i := 0; i < len(args); i++ {
switch args[i] {
case "--token":
if i+1 < len(args) {
i++
tokenFlag = args[i]
}
case "--acc-mgr-token":
if i+1 < len(args) {
i++
accMgrTokenFlag = args[i]
}
default:
filtered = append(filtered, args[i])
}
}
switch subCmd {
case "list":
commands.RunUserList(tokenFlag)
case "get":
if len(filtered) < 1 {
output.Error("usage: hf user get <username>")
}
commands.RunUserGet(filtered[0], tokenFlag)
case "create":
username, password, email, fullName := "", "", "", ""
for i := 0; i < len(filtered); i++ {
switch filtered[i] {
case "--user":
if i+1 < len(filtered) {
i++
username = filtered[i]
}
case "--pass":
if i+1 < len(filtered) {
i++
password = filtered[i]
}
case "--email":
if i+1 < len(filtered) {
i++
email = filtered[i]
}
case "--full-name":
if i+1 < len(filtered) {
i++
fullName = filtered[i]
}
default:
output.Errorf("unknown flag: %s", filtered[i])
}
}
if username == "" {
output.Error("usage: hf user create --user <username>")
}
commands.RunUserCreate(username, password, email, fullName, accMgrTokenFlag)
case "update":
if len(filtered) < 1 {
output.Error("usage: hf user update <username> [--email ...] [--full-name ...] [--pass ...] [--active ...]")
}
commands.RunUserUpdate(filtered[0], filtered[1:], tokenFlag)
case "activate":
if len(filtered) < 1 {
output.Error("usage: hf user activate <username>")
}
commands.RunUserActivate(filtered[0], tokenFlag)
case "deactivate":
if len(filtered) < 1 {
output.Error("usage: hf user deactivate <username>")
}
commands.RunUserDeactivate(filtered[0], tokenFlag)
case "delete":
if len(filtered) < 1 {
output.Error("usage: hf user delete <username>")
}
commands.RunUserDelete(filtered[0], tokenFlag)
default:
output.Errorf("hf user %s is not implemented yet", subCmd)
}
}
func isHelpFlagOnly(args []string) bool {
return len(args) == 1 && (args[0] == "--help" || args[0] == "-h")
}
func findGroup(name string) (help.Group, bool) {
for _, group := range help.CommandSurface() {
if group.Name == name {
return group, true
}
}
return help.Group{}, false
}
func findSubCommand(group help.Group, name string) (help.Command, bool) {
for _, cmd := range group.SubCommands {
if cmd.Name == name {
return cmd, true
}
}
return help.Command{}, false
}