From e85fd219220a4fb21722d654106e18e755f0ce7d Mon Sep 17 00:00:00 2001 From: David Allen Date: Mon, 16 Jun 2025 16:19:43 -0600 Subject: [PATCH] refactor: updated cache editor implementation --- cmd/cache.go | 63 ++++++++++++++++++++++++----- cmd/list.go | 4 +- internal/cache/{edit => }/modify.go | 0 internal/cache/{edit => }/table.go | 4 ++ internal/util/print.go | 20 +++++++++ pkg/list.go | 15 ------- 6 files changed, 78 insertions(+), 28 deletions(-) rename internal/cache/{edit => }/modify.go (100%) rename internal/cache/{edit => }/table.go (95%) diff --git a/cmd/cache.go b/cmd/cache.go index f39bffd..aa35136 100644 --- a/cmd/cache.go +++ b/cmd/cache.go @@ -6,27 +6,25 @@ import ( "os" "strconv" + tea "github.com/charmbracelet/bubbletea" + "github.com/davidallendj/magellan/internal/cache" "github.com/davidallendj/magellan/internal/cache/sqlite" + "github.com/davidallendj/magellan/internal/util" magellan "github.com/davidallendj/magellan/pkg" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) var ( - withHosts []string - withPorts []int + cacheOutputFormat string + interactive bool + withHosts []string + withPorts []int ) var cacheCmd = &cobra.Command{ Use: "cache", Short: "Manage found assets in cache.", - Run: func(cmd *cobra.Command, args []string) { - // show the help for cache and exit - if len(args) <= 0 { - cmd.Help() - os.Exit(0) - } - }, } var cacheRemoveCmd = &cobra.Command{ @@ -88,9 +86,54 @@ var cacheRemoveCmd = &cobra.Command{ }, } +var cacheEditCmd = &cobra.Command{ + Use: "edit", + Short: "Modify cache data either interactively or non-interactively.", + Run: func(cmd *cobra.Command, args []string) { + // start the interactive editor + if interactive { + p := tea.NewProgram(cache.NewModel()) + if _, err := p.Run(); err != nil { + fmt.Printf("failed to start the cache editor: %v", err) + os.Exit(1) + } + } else { + // only edit data with arguments + } + }, +} + +var cacheInfoCmd = &cobra.Command{ + Use: "info", + Short: "Show cache-related information.", + Run: func(cmd *cobra.Command, args []string) { + printCacheInfo(cacheOutputFormat) + }, +} + func init() { + // remove cacheRemoveCmd.Flags().StringSliceVar(&withHosts, "with-hosts", []string{}, "Remove all assets with specified hosts") cacheRemoveCmd.Flags().IntSliceVar(&withPorts, "with-ports", []int{}, "Remove all assets with specified ports") - cacheCmd.AddCommand(cacheRemoveCmd) + + // edit + cacheEditCmd.Flags().BoolVarP(&interactive, "interactive", "i", false, "Edit cache data using interactive editor") + + cacheInfoCmd.Flags().StringVarP(&cacheOutputFormat, "format", "F", FORMAT_LIST, "Set the output format (list|json|yaml)") + + // commands + cacheCmd.AddCommand(cacheRemoveCmd, cacheEditCmd, cacheInfoCmd) rootCmd.AddCommand(cacheCmd) } + +func printCacheInfo(format string) { + assets, err := sqlite.GetScannedAssets(cachePath) + if err != nil { + log.Error().Err(err).Str("path", cachePath).Msg("failed to get assets to print cache info") + } + cacheData := map[string]any{ + "path": cachePath, + "assets": len(assets), + } + util.PrintMapWithFormat(cacheData, format) +} diff --git a/cmd/list.go b/cmd/list.go index e36ae43..3d26c16 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -42,9 +42,7 @@ var ListCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { // check if we just want to show cache-related info and exit if showCacheInfo { - magellan.PrintMapWithFormat(map[string]any{ - "path": cachePath, - }, listOutputFormat) + printCacheInfo(listOutputFormat) os.Exit(0) } diff --git a/internal/cache/edit/modify.go b/internal/cache/modify.go similarity index 100% rename from internal/cache/edit/modify.go rename to internal/cache/modify.go diff --git a/internal/cache/edit/table.go b/internal/cache/table.go similarity index 95% rename from internal/cache/edit/table.go rename to internal/cache/table.go index 7759bd7..777308a 100644 --- a/internal/cache/edit/table.go +++ b/internal/cache/table.go @@ -15,6 +15,10 @@ type Model struct { Table table.Model } +func NewModel() Model { + return Model{} +} + func (m Model) Init() tea.Cmd { return nil } func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { diff --git a/internal/util/print.go b/internal/util/print.go index 0762ed1..a8102f4 100644 --- a/internal/util/print.go +++ b/internal/util/print.go @@ -3,6 +3,7 @@ package util import ( "encoding/json" "fmt" + "strings" "github.com/rs/zerolog/log" "gopkg.in/yaml.v2" @@ -23,3 +24,22 @@ func PrintYAML(data any) { } fmt.Print(string(b)) } + +func PrintMap(data map[string]any) { + for k, v := range data { + fmt.Printf("%s: %v\n", k, v) + } +} + +func PrintMapWithFormat(data map[string]any, format string) { + switch strings.ToLower(format) { + case "json": + PrintJSON(data) + case "yaml": + PrintYAML(data) + case "list": + PrintMap(data) + default: + log.Error().Msg("PrintMapWithFormat: unrecognized format") + } +} diff --git a/pkg/list.go b/pkg/list.go index 3e7ea0b..a72748d 100644 --- a/pkg/list.go +++ b/pkg/list.go @@ -27,21 +27,6 @@ func PrintRemoteAssets(data []RemoteAsset, format string) { } } -func PrintMapWithFormat(data map[string]any, format string) { - switch strings.ToLower(format) { - case "json": - util.PrintJSON(data) - case "yaml": - util.PrintYAML(data) - case "list": - for k, v := range data { - fmt.Printf("%s: %v\n", k, v) - } - default: - log.Error().Msg("PrintMapWithFormat: unrecognized format") - } -} - func ListDrives(cc *crawler.CrawlerConfig) ([]*redfish.Drive, error) { user, err := cc.GetUserPass() if err != nil {