161 lines
4 KiB
Go
161 lines
4 KiB
Go
|
|
package cmd
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"sort"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"forgejo.zerova.net/public/fgj-sid/internal/config"
|
||
|
|
"github.com/spf13/cobra"
|
||
|
|
)
|
||
|
|
|
||
|
|
var loginsCmd = &cobra.Command{
|
||
|
|
Use: "logins",
|
||
|
|
Short: "Manage configured Forgejo/Gitea logins",
|
||
|
|
Long: `Manage configured Forgejo/Gitea logins.
|
||
|
|
|
||
|
|
This is a complementary command to 'fgj auth' using the noun vocabulary
|
||
|
|
familiar to users of tea. Use 'fgj auth login' to add a new login and
|
||
|
|
'fgj auth logout' to remove one.`,
|
||
|
|
}
|
||
|
|
|
||
|
|
var loginsListCmd = &cobra.Command{
|
||
|
|
Use: "list",
|
||
|
|
Aliases: []string{"ls"},
|
||
|
|
Short: "List all configured logins",
|
||
|
|
Long: "List all configured Forgejo/Gitea logins with their hostname, user, protocol, default flag, and match_dirs.",
|
||
|
|
RunE: runLoginsList,
|
||
|
|
}
|
||
|
|
|
||
|
|
var loginsDefaultCmd = &cobra.Command{
|
||
|
|
Use: "default [hostname]",
|
||
|
|
Short: "Get or set the default login",
|
||
|
|
Long: `Get or set the default login.
|
||
|
|
|
||
|
|
With no argument, prints the currently-configured default hostname
|
||
|
|
(or "no default set" if none is configured).
|
||
|
|
|
||
|
|
With a hostname argument, marks that login as the default and unsets
|
||
|
|
the default flag on all other logins.`,
|
||
|
|
Args: cobra.MaximumNArgs(1),
|
||
|
|
RunE: runLoginsDefault,
|
||
|
|
}
|
||
|
|
|
||
|
|
func init() {
|
||
|
|
rootCmd.AddCommand(loginsCmd)
|
||
|
|
loginsCmd.AddCommand(loginsListCmd)
|
||
|
|
loginsCmd.AddCommand(loginsDefaultCmd)
|
||
|
|
|
||
|
|
addJSONFlags(loginsListCmd, "Output logins as JSON")
|
||
|
|
}
|
||
|
|
|
||
|
|
// loginEntry is the JSON representation of a configured login.
|
||
|
|
type loginEntry struct {
|
||
|
|
Hostname string `json:"hostname"`
|
||
|
|
User string `json:"user"`
|
||
|
|
GitProtocol string `json:"git_protocol"`
|
||
|
|
Default bool `json:"default"`
|
||
|
|
MatchDirs []string `json:"match_dirs"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func runLoginsList(cmd *cobra.Command, args []string) error {
|
||
|
|
cfg, err := config.Load()
|
||
|
|
if err != nil {
|
||
|
|
return fmt.Errorf("failed to load config: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
hostnames := make([]string, 0, len(cfg.Hosts))
|
||
|
|
for hostname := range cfg.Hosts {
|
||
|
|
hostnames = append(hostnames, hostname)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Sort by config-file order; fall back to alphabetical when Order is
|
||
|
|
// equal (e.g., both zero because the config was constructed in-memory
|
||
|
|
// rather than loaded from disk).
|
||
|
|
sort.Slice(hostnames, func(i, j int) bool {
|
||
|
|
a, b := cfg.Hosts[hostnames[i]], cfg.Hosts[hostnames[j]]
|
||
|
|
if a.Order != b.Order {
|
||
|
|
return a.Order < b.Order
|
||
|
|
}
|
||
|
|
return hostnames[i] < hostnames[j]
|
||
|
|
})
|
||
|
|
|
||
|
|
if wantJSON(cmd) {
|
||
|
|
entries := make([]loginEntry, 0, len(hostnames))
|
||
|
|
for _, hostname := range hostnames {
|
||
|
|
h := cfg.Hosts[hostname]
|
||
|
|
dirs := h.MatchDirs
|
||
|
|
if dirs == nil {
|
||
|
|
dirs = []string{}
|
||
|
|
}
|
||
|
|
entries = append(entries, loginEntry{
|
||
|
|
Hostname: hostname,
|
||
|
|
User: h.User,
|
||
|
|
GitProtocol: h.GitProtocol,
|
||
|
|
Default: h.Default,
|
||
|
|
MatchDirs: dirs,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
return outputJSON(cmd, entries)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(hostnames) == 0 {
|
||
|
|
fmt.Fprintln(ios.Out, "No logins configured")
|
||
|
|
fmt.Fprintln(ios.Out, "Run 'fgj auth login' to add a login")
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
tp := ios.NewTablePrinter()
|
||
|
|
tp.AddHeader("HOSTNAME", "USER", "PROTOCOL", "DEFAULT", "MATCH_DIRS")
|
||
|
|
for _, hostname := range hostnames {
|
||
|
|
h := cfg.Hosts[hostname]
|
||
|
|
defaultMark := ""
|
||
|
|
if h.Default {
|
||
|
|
defaultMark = "*"
|
||
|
|
}
|
||
|
|
tp.AddRow(
|
||
|
|
hostname,
|
||
|
|
h.User,
|
||
|
|
h.GitProtocol,
|
||
|
|
defaultMark,
|
||
|
|
strings.Join(h.MatchDirs, ", "),
|
||
|
|
)
|
||
|
|
}
|
||
|
|
return tp.Render()
|
||
|
|
}
|
||
|
|
|
||
|
|
func runLoginsDefault(cmd *cobra.Command, args []string) error {
|
||
|
|
cfg, err := config.Load()
|
||
|
|
if err != nil {
|
||
|
|
return fmt.Errorf("failed to load config: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(args) == 0 {
|
||
|
|
current := cfg.DefaultHost()
|
||
|
|
if current == "" {
|
||
|
|
fmt.Fprintln(ios.Out, "no default set")
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
fmt.Fprintln(ios.Out, current)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
target := args[0]
|
||
|
|
if _, ok := cfg.Hosts[target]; !ok {
|
||
|
|
return fmt.Errorf("no configuration found for host %s", target)
|
||
|
|
}
|
||
|
|
|
||
|
|
for hostname, h := range cfg.Hosts {
|
||
|
|
h.Default = (hostname == target)
|
||
|
|
cfg.Hosts[hostname] = h
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := cfg.Save(); err != nil {
|
||
|
|
return fmt.Errorf("failed to save config: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
cs := ios.ColorScheme()
|
||
|
|
fmt.Fprintf(ios.Out, "%s Default host set to %s\n", cs.SuccessIcon(), target)
|
||
|
|
return nil
|
||
|
|
}
|