- Add hf calendar command group to command surface and router - Implement schedule/show/edit/cancel/date-list commands - Implement plan-schedule/plan-list/plan-edit/plan-cancel commands - Add leaf help for all calendar commands - Align CLI with backend calendar routes and response envelopes - Support virtual slot ids for edit/cancel - Validate with go build and go test ./...
1084 lines
27 KiB
Go
1084 lines
27 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 isLeafHelpFlagOnly(args) {
|
|
if text, ok := help.RenderLeafHelp("", name); ok {
|
|
fmt.Print(text)
|
|
return
|
|
}
|
|
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 isLeafHelpFlagOnly(args) || isHelpFlagOnly(args) {
|
|
if text, ok := help.RenderLeafHelp("config", "show"); ok {
|
|
fmt.Print(text)
|
|
return
|
|
}
|
|
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 group.Name == "monitor" && (sub.Name == "server" || sub.Name == "api-key") {
|
|
if len(args) == 1 {
|
|
handleMonitorCommand(sub.Name, nil)
|
|
return
|
|
}
|
|
if isHelpLikePath(args[1:]) || sub.Permitted {
|
|
handleMonitorCommand(sub.Name, args[1:])
|
|
return
|
|
}
|
|
}
|
|
|
|
if len(args) > 1 && isLeafHelpFlagOnly(args[1:]) {
|
|
if !sub.Permitted {
|
|
fmt.Println(help.RenderNotPermitted(group.Name, sub.Name))
|
|
return
|
|
}
|
|
if text, ok := help.RenderLeafHelp(group.Name, sub.Name); ok {
|
|
fmt.Print(text)
|
|
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
|
|
case "role":
|
|
handleRoleCommand(sub.Name, remaining)
|
|
return
|
|
case "permission":
|
|
handlePermissionCommand(sub.Name, remaining)
|
|
return
|
|
case "project":
|
|
handleProjectCommand(sub.Name, remaining)
|
|
return
|
|
case "milestone":
|
|
handleMilestoneCommand(sub.Name, remaining)
|
|
return
|
|
case "task":
|
|
handleTaskCommand(sub.Name, remaining)
|
|
return
|
|
case "meeting":
|
|
handleMeetingCommand(sub.Name, remaining)
|
|
return
|
|
case "support":
|
|
handleSupportCommand(sub.Name, remaining)
|
|
return
|
|
case "proposal", "propose":
|
|
handleProposalCommand(sub.Name, remaining)
|
|
return
|
|
case "calendar":
|
|
handleCalendarCommand(sub.Name, remaining)
|
|
return
|
|
case "comment":
|
|
handleCommentCommand(sub.Name, remaining)
|
|
return
|
|
case "worklog":
|
|
handleWorklogCommand(sub.Name, remaining)
|
|
return
|
|
case "monitor":
|
|
handleMonitorCommand(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 isLeafHelpFlagOnly(args []string) bool {
|
|
return len(args) == 1 && (args[0] == "--help" || args[0] == "-h" || args[0] == "--help-brief")
|
|
}
|
|
|
|
func isHelpLikePath(args []string) bool {
|
|
if len(args) == 0 {
|
|
return true
|
|
}
|
|
if len(args) == 1 {
|
|
return args[0] == "--help" || args[0] == "-h" || args[0] == "--help-brief"
|
|
}
|
|
return isLeafHelpFlagOnly(args[len(args)-1:])
|
|
}
|
|
|
|
// groupAliases maps legacy command names to their current group names.
|
|
var groupAliases = map[string]string{
|
|
"propose": "proposal",
|
|
}
|
|
|
|
func findGroup(name string) (help.Group, bool) {
|
|
// Resolve alias first
|
|
if alias, ok := groupAliases[name]; ok {
|
|
name = alias
|
|
}
|
|
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
|
|
}
|
|
|
|
func handleRoleCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunRoleList(tokenFlag)
|
|
case "get":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf role get <role-name>")
|
|
}
|
|
commands.RunRoleGet(filtered[0], tokenFlag)
|
|
case "create":
|
|
name, desc := "", ""
|
|
global := false
|
|
var remaining []string
|
|
for i := 0; i < len(filtered); i++ {
|
|
switch filtered[i] {
|
|
case "--name":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
name = filtered[i]
|
|
}
|
|
case "--desc":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
desc = filtered[i]
|
|
}
|
|
case "--global":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
global = filtered[i] == "true"
|
|
}
|
|
default:
|
|
remaining = append(remaining, filtered[i])
|
|
}
|
|
}
|
|
_ = remaining
|
|
if name == "" {
|
|
output.Error("usage: hf role create --name <role-name>")
|
|
}
|
|
commands.RunRoleCreate(name, desc, global, tokenFlag)
|
|
case "update":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf role update <role-name> [--desc ...]")
|
|
}
|
|
commands.RunRoleUpdate(filtered[0], filtered[1:], tokenFlag)
|
|
case "delete":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf role delete <role-name>")
|
|
}
|
|
commands.RunRoleDelete(filtered[0], tokenFlag)
|
|
case "set-permissions":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf role set-permissions <role-name> --permission <perm> [...]")
|
|
}
|
|
roleName := filtered[0]
|
|
perms := extractPermissions(filtered[1:])
|
|
commands.RunRoleSetPermissions(roleName, perms, tokenFlag)
|
|
case "add-permissions":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf role add-permissions <role-name> --permission <perm> [...]")
|
|
}
|
|
roleName := filtered[0]
|
|
perms := extractPermissions(filtered[1:])
|
|
commands.RunRoleAddPermissions(roleName, perms, tokenFlag)
|
|
case "remove-permissions":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf role remove-permissions <role-name> --permission <perm> [...]")
|
|
}
|
|
roleName := filtered[0]
|
|
perms := extractPermissions(filtered[1:])
|
|
commands.RunRoleRemovePermissions(roleName, perms, tokenFlag)
|
|
default:
|
|
output.Errorf("hf role %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func extractPermissions(args []string) []string {
|
|
var perms []string
|
|
for i := 0; i < len(args); i++ {
|
|
if args[i] == "--permission" && i+1 < len(args) {
|
|
i++
|
|
perms = append(perms, args[i])
|
|
}
|
|
}
|
|
return perms
|
|
}
|
|
|
|
func handlePermissionCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
for i := 0; i < len(args); i++ {
|
|
if args[i] == "--token" && i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunPermissionList(tokenFlag)
|
|
default:
|
|
output.Errorf("hf permission %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleMilestoneCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunMilestoneList(filtered, tokenFlag)
|
|
case "get":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf milestone get <milestone-code>")
|
|
}
|
|
commands.RunMilestoneGet(filtered[0], tokenFlag)
|
|
case "create":
|
|
commands.RunMilestoneCreate(filtered, tokenFlag)
|
|
case "update":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf milestone update <milestone-code> [--title ...] [--desc ...] [--status ...] [--due ...]")
|
|
}
|
|
commands.RunMilestoneUpdate(filtered[0], filtered[1:], tokenFlag)
|
|
case "delete":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf milestone delete <milestone-code>")
|
|
}
|
|
commands.RunMilestoneDelete(filtered[0], tokenFlag)
|
|
case "progress":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf milestone progress <milestone-code>")
|
|
}
|
|
commands.RunMilestoneProgress(filtered[0], tokenFlag)
|
|
default:
|
|
output.Errorf("hf milestone %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleTaskCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunTaskList(filtered, tokenFlag)
|
|
case "get":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf task get <task-code>")
|
|
}
|
|
commands.RunTaskGet(filtered[0], tokenFlag)
|
|
case "create":
|
|
commands.RunTaskCreate(filtered, tokenFlag)
|
|
case "update":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf task update <task-code> [--title ...] [--desc ...] [--status ...] [--priority ...] [--assignee ...]")
|
|
}
|
|
commands.RunTaskUpdate(filtered[0], filtered[1:], tokenFlag)
|
|
case "transition":
|
|
if len(filtered) < 2 {
|
|
output.Error("usage: hf task transition <task-code> <status>")
|
|
}
|
|
commands.RunTaskTransition(filtered[0], filtered[1], tokenFlag)
|
|
case "take":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf task take <task-code>")
|
|
}
|
|
commands.RunTaskTake(filtered[0], tokenFlag)
|
|
case "delete":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf task delete <task-code>")
|
|
}
|
|
commands.RunTaskDelete(filtered[0], tokenFlag)
|
|
case "search":
|
|
commands.RunTaskSearch(filtered, tokenFlag)
|
|
default:
|
|
output.Errorf("hf task %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleProjectCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunProjectList(filtered, tokenFlag)
|
|
case "get":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf project get <project-code>")
|
|
}
|
|
commands.RunProjectGet(filtered[0], tokenFlag)
|
|
case "create":
|
|
commands.RunProjectCreate(filtered, tokenFlag)
|
|
case "update":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf project update <project-code> [--name ...] [--desc ...] [--repo ...]")
|
|
}
|
|
commands.RunProjectUpdate(filtered[0], filtered[1:], tokenFlag)
|
|
case "delete":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf project delete <project-code>")
|
|
}
|
|
commands.RunProjectDelete(filtered[0], tokenFlag)
|
|
case "members":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf project members <project-code>")
|
|
}
|
|
commands.RunProjectMembers(filtered[0], tokenFlag)
|
|
case "add-member":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf project add-member <project-code> --user <username> --role <role-name>")
|
|
}
|
|
commands.RunProjectAddMember(filtered[0], filtered[1:], tokenFlag)
|
|
case "remove-member":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf project remove-member <project-code> --user <username>")
|
|
}
|
|
commands.RunProjectRemoveMember(filtered[0], filtered[1:], tokenFlag)
|
|
default:
|
|
output.Errorf("hf project %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleMeetingCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunMeetingList(filtered, tokenFlag)
|
|
case "get":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf meeting get <meeting-code>")
|
|
}
|
|
commands.RunMeetingGet(filtered[0], tokenFlag)
|
|
case "create":
|
|
commands.RunMeetingCreate(filtered, tokenFlag)
|
|
case "update":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf meeting update <meeting-code> [--title ...] [--desc ...] [--status ...] [--time ...]")
|
|
}
|
|
commands.RunMeetingUpdate(filtered[0], filtered[1:], tokenFlag)
|
|
case "attend":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf meeting attend <meeting-code>")
|
|
}
|
|
commands.RunMeetingAttend(filtered[0], tokenFlag)
|
|
case "delete":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf meeting delete <meeting-code>")
|
|
}
|
|
commands.RunMeetingDelete(filtered[0], tokenFlag)
|
|
default:
|
|
output.Errorf("hf meeting %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleSupportCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunSupportList(filtered, tokenFlag)
|
|
case "get":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf support get <support-code>")
|
|
}
|
|
commands.RunSupportGet(filtered[0], tokenFlag)
|
|
case "create":
|
|
commands.RunSupportCreate(filtered, tokenFlag)
|
|
case "update":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf support update <support-code> [--title ...] [--desc ...] [--status ...] [--priority ...]")
|
|
}
|
|
commands.RunSupportUpdate(filtered[0], filtered[1:], tokenFlag)
|
|
case "take":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf support take <support-code>")
|
|
}
|
|
commands.RunSupportTake(filtered[0], tokenFlag)
|
|
case "transition":
|
|
if len(filtered) < 2 {
|
|
output.Error("usage: hf support transition <support-code> <status>")
|
|
}
|
|
commands.RunSupportTransition(filtered[0], filtered[1], tokenFlag)
|
|
case "delete":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf support delete <support-code>")
|
|
}
|
|
commands.RunSupportDelete(filtered[0], tokenFlag)
|
|
default:
|
|
output.Errorf("hf support %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleCalendarCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "schedule":
|
|
commands.RunCalendarSchedule(filtered, tokenFlag)
|
|
case "show":
|
|
commands.RunCalendarShow(filtered, tokenFlag)
|
|
case "edit":
|
|
commands.RunCalendarEdit(filtered, tokenFlag)
|
|
case "cancel":
|
|
commands.RunCalendarCancel(filtered, tokenFlag)
|
|
case "date-list":
|
|
commands.RunCalendarDateList(filtered, tokenFlag)
|
|
case "plan-schedule":
|
|
commands.RunCalendarPlanSchedule(filtered, tokenFlag)
|
|
case "plan-list":
|
|
commands.RunCalendarPlanList(filtered, tokenFlag)
|
|
case "plan-edit":
|
|
commands.RunCalendarPlanEdit(filtered, tokenFlag)
|
|
case "plan-cancel":
|
|
commands.RunCalendarPlanCancel(filtered, tokenFlag)
|
|
default:
|
|
output.Errorf("hf calendar %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleProposalCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunProposeList(filtered, tokenFlag)
|
|
case "get":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf proposal get <proposal-code>")
|
|
}
|
|
commands.RunProposeGet(filtered[0], tokenFlag)
|
|
case "create":
|
|
commands.RunProposeCreate(filtered, tokenFlag)
|
|
case "update":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf proposal update <proposal-code> [--title ...] [--desc ...]")
|
|
}
|
|
commands.RunProposeUpdate(filtered[0], filtered[1:], tokenFlag)
|
|
case "accept":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf proposal accept <proposal-code> --milestone <milestone-code>")
|
|
}
|
|
commands.RunProposeAccept(filtered[0], filtered[1:], tokenFlag)
|
|
case "reject":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf proposal reject <proposal-code> [--reason <reason>]")
|
|
}
|
|
commands.RunProposeReject(filtered[0], filtered[1:], tokenFlag)
|
|
case "reopen":
|
|
if len(filtered) < 1 {
|
|
output.Error("usage: hf proposal reopen <proposal-code>")
|
|
}
|
|
commands.RunProposeReopen(filtered[0], tokenFlag)
|
|
case "essential":
|
|
handleProposalEssentialCommand(filtered, tokenFlag)
|
|
default:
|
|
output.Errorf("hf proposal %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleProposalEssentialCommand(args []string, tokenFlag string) {
|
|
essentialCommands := []help.Command{
|
|
{Name: "list", Description: "List essentials for a proposal", Permitted: true},
|
|
{Name: "create", Description: "Create an essential", Permitted: true},
|
|
{Name: "update", Description: "Update an essential", Permitted: true},
|
|
{Name: "delete", Description: "Delete an essential", Permitted: true},
|
|
}
|
|
|
|
if len(args) == 0 || isHelpFlagOnly(args) {
|
|
fmt.Print(help.RenderGroupHelp("proposal essential", essentialCommands))
|
|
return
|
|
}
|
|
|
|
subCmd := args[0]
|
|
remaining := args[1:]
|
|
|
|
if isLeafHelpFlagOnly(remaining) {
|
|
if text, ok := help.RenderLeafHelp("proposal/essential", subCmd); ok {
|
|
fmt.Print(text)
|
|
return
|
|
}
|
|
fmt.Printf("hf proposal essential %s\n", subCmd)
|
|
return
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunEssentialList(remaining, tokenFlag)
|
|
case "create":
|
|
commands.RunEssentialCreate(remaining, tokenFlag)
|
|
case "update":
|
|
if len(remaining) < 1 {
|
|
output.Error("usage: hf proposal essential update <essential-code> [--title ...] [--type ...] [--desc ...]")
|
|
}
|
|
commands.RunEssentialUpdate(remaining[0], remaining[1:], tokenFlag)
|
|
case "delete":
|
|
if len(remaining) < 1 {
|
|
output.Error("usage: hf proposal essential delete <essential-code> --proposal <proposal-code>")
|
|
}
|
|
commands.RunEssentialDeleteFull(remaining[0], remaining[1:], tokenFlag)
|
|
default:
|
|
output.Errorf("hf proposal essential %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleCommentCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "add":
|
|
taskCode, content := "", ""
|
|
for i := 0; i < len(filtered); i++ {
|
|
switch filtered[i] {
|
|
case "--task":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
taskCode = filtered[i]
|
|
}
|
|
case "--content":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
content = filtered[i]
|
|
}
|
|
default:
|
|
output.Errorf("unknown flag: %s", filtered[i])
|
|
}
|
|
}
|
|
commands.RunCommentAdd(taskCode, content, tokenFlag)
|
|
case "list":
|
|
taskCode := ""
|
|
for i := 0; i < len(filtered); i++ {
|
|
switch filtered[i] {
|
|
case "--task":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
taskCode = filtered[i]
|
|
}
|
|
default:
|
|
output.Errorf("unknown flag: %s", filtered[i])
|
|
}
|
|
}
|
|
commands.RunCommentList(taskCode, tokenFlag)
|
|
default:
|
|
output.Errorf("hf comment %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleWorklogCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "add":
|
|
taskCode, desc, date := "", "", ""
|
|
hours := 0.0
|
|
for i := 0; i < len(filtered); i++ {
|
|
switch filtered[i] {
|
|
case "--task":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
taskCode = filtered[i]
|
|
}
|
|
case "--hours":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
if _, err := fmt.Sscanf(filtered[i], "%f", &hours); err != nil {
|
|
output.Error("--hours requires a numeric value")
|
|
}
|
|
}
|
|
case "--desc":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
desc = filtered[i]
|
|
}
|
|
case "--date":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
date = filtered[i]
|
|
}
|
|
default:
|
|
output.Errorf("unknown flag: %s", filtered[i])
|
|
}
|
|
}
|
|
commands.RunWorklogAdd(taskCode, hours, desc, date, tokenFlag)
|
|
case "list":
|
|
taskCode, username := "", ""
|
|
for i := 0; i < len(filtered); i++ {
|
|
switch filtered[i] {
|
|
case "--task":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
taskCode = filtered[i]
|
|
}
|
|
case "--user":
|
|
if i+1 < len(filtered) {
|
|
i++
|
|
username = filtered[i]
|
|
}
|
|
default:
|
|
output.Errorf("unknown flag: %s", filtered[i])
|
|
}
|
|
}
|
|
commands.RunWorklogList(taskCode, username, tokenFlag)
|
|
default:
|
|
output.Errorf("hf worklog %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleMonitorCommand(subCmd string, args []string) {
|
|
tokenFlag := ""
|
|
var filtered []string
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--token":
|
|
if i+1 < len(args) {
|
|
i++
|
|
tokenFlag = args[i]
|
|
}
|
|
default:
|
|
filtered = append(filtered, args[i])
|
|
}
|
|
}
|
|
|
|
switch subCmd {
|
|
case "overview":
|
|
commands.RunMonitorOverview(tokenFlag)
|
|
case "server":
|
|
handleMonitorServerCommand(filtered, tokenFlag)
|
|
case "api-key":
|
|
handleMonitorAPIKeyCommand(filtered, tokenFlag)
|
|
default:
|
|
output.Errorf("hf monitor %s is not implemented yet", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleMonitorServerCommand(args []string, tokenFlag string) {
|
|
serverCommands := []help.Command{
|
|
{Name: "list", Description: "List monitor servers", Permitted: true},
|
|
{Name: "get", Description: "Show a monitor server by identifier", Permitted: true},
|
|
{Name: "create", Description: "Create a monitor server", Permitted: true},
|
|
{Name: "delete", Description: "Delete a monitor server", Permitted: true},
|
|
}
|
|
|
|
if len(args) == 0 || isHelpFlagOnly(args) {
|
|
fmt.Print(help.RenderGroupHelp("monitor server", serverCommands))
|
|
return
|
|
}
|
|
if len(args) == 1 && args[0] == "--help-brief" {
|
|
fmt.Print(help.RenderGroupHelpBrief("monitor server", serverCommands))
|
|
return
|
|
}
|
|
|
|
subCmd := args[0]
|
|
remaining := args[1:]
|
|
if isLeafHelpFlagOnly(remaining) {
|
|
if text, ok := help.RenderLeafHelp("monitor/server", subCmd); ok {
|
|
fmt.Print(text)
|
|
return
|
|
}
|
|
fmt.Printf("hf monitor server %s\n", subCmd)
|
|
return
|
|
}
|
|
|
|
switch subCmd {
|
|
case "list":
|
|
commands.RunMonitorServerList(tokenFlag)
|
|
case "get":
|
|
if len(remaining) < 1 {
|
|
output.Error("usage: hf monitor server get <identifier>")
|
|
}
|
|
commands.RunMonitorServerGet(remaining[0], tokenFlag)
|
|
case "create":
|
|
commands.RunMonitorServerCreate(remaining, tokenFlag)
|
|
case "delete":
|
|
if len(remaining) < 1 {
|
|
output.Error("usage: hf monitor server delete <identifier>")
|
|
}
|
|
commands.RunMonitorServerDelete(remaining[0], tokenFlag)
|
|
default:
|
|
output.Errorf("unknown monitor server subcommand: %s", subCmd)
|
|
}
|
|
}
|
|
|
|
func handleMonitorAPIKeyCommand(args []string, tokenFlag string) {
|
|
apiKeyCommands := []help.Command{
|
|
{Name: "generate", Description: "Generate a monitor API key", Permitted: true},
|
|
{Name: "revoke", Description: "Revoke a monitor API key", Permitted: true},
|
|
}
|
|
|
|
if len(args) == 0 || isHelpFlagOnly(args) {
|
|
fmt.Print(help.RenderGroupHelp("monitor api-key", apiKeyCommands))
|
|
return
|
|
}
|
|
if len(args) == 1 && args[0] == "--help-brief" {
|
|
fmt.Print(help.RenderGroupHelpBrief("monitor api-key", apiKeyCommands))
|
|
return
|
|
}
|
|
|
|
subCmd := args[0]
|
|
remaining := args[1:]
|
|
if isLeafHelpFlagOnly(remaining) {
|
|
if text, ok := help.RenderLeafHelp("monitor/api-key", subCmd); ok {
|
|
fmt.Print(text)
|
|
return
|
|
}
|
|
fmt.Printf("hf monitor api-key %s\n", subCmd)
|
|
return
|
|
}
|
|
|
|
switch subCmd {
|
|
case "generate":
|
|
if len(remaining) < 1 {
|
|
output.Error("usage: hf monitor api-key generate <identifier>")
|
|
}
|
|
commands.RunMonitorAPIKeyGenerate(remaining[0], tokenFlag)
|
|
case "revoke":
|
|
if len(remaining) < 1 {
|
|
output.Error("usage: hf monitor api-key revoke <identifier>")
|
|
}
|
|
commands.RunMonitorAPIKeyRevoke(remaining[0], tokenFlag)
|
|
default:
|
|
output.Errorf("unknown monitor api-key subcommand: %s", subCmd)
|
|
}
|
|
}
|