setup basic CLI and config commands

This commit is contained in:
VetheonGames 2024-03-27 02:11:46 -06:00
parent 37e96b5005
commit 303670e43a
4 changed files with 207 additions and 1 deletions

View File

@ -0,0 +1,82 @@
package cmd
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
)
const configDir = "/etc/PixelRidge/BackupGo"
const configFile = "config.json"
// Config represents the application's configuration
type Config struct {
S3ConnectionInfo string `json:"s3_connection_info"`
// Add other configuration options here, all as strings or booleans
}
// LoadConfig loads the configuration from the JSON file
func LoadConfig() (*Config, error) {
configPath := filepath.Join(configDir, configFile)
file, err := os.Open(configPath)
if err != nil {
return nil, err
}
defer file.Close()
config := &Config{}
decoder := json.NewDecoder(file)
if err := decoder.Decode(config); err != nil {
return nil, err
}
return config, nil
}
// SaveConfig saves the modified configuration back to the JSON file
func SaveConfig(config *Config) error {
configPath := filepath.Join(configDir, configFile)
file, err := os.Create(configPath)
if err != nil {
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
if err := encoder.Encode(config); err != nil {
return err
}
return nil
}
// EditConfigOption allows editing a specific configuration option from the CLI
func EditConfigOption(optionName, newValue string) error {
config, err := LoadConfig()
if err != nil {
return err
}
// Reflect or a simple switch can be used to match the optionName to Config fields
switch optionName {
case "s3_connection_info":
config.S3ConnectionInfo = newValue
// Add cases for other options here
default:
return fmt.Errorf("unknown configuration option: %s", optionName)
}
return SaveConfig(config)
}
// OpenConfigInNano opens the configuration file in the nano editor
func OpenConfigInNano() error {
configPath := filepath.Join(configDir, configFile)
cmd := exec.Command("nano", configPath)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}

View File

@ -0,0 +1,109 @@
package cmd
import (
"flag"
"fmt"
)
// Command represents a CLI command.
type Command struct {
Name string
Description string
FlagSet *flag.FlagSet
SubCommands map[string]*Command
Execute func(cmd *Command, args []string)
}
// RootCmd is now defined at the package level, making it accessible from other packages.
var RootCmd = NewCommand("backup", "Main entry point for backup utility", nil)
// NewCommand creates a new command instance.
func NewCommand(name, description string, execute func(cmd *Command, args []string)) *Command {
return &Command{
Name: name,
Description: description,
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
SubCommands: make(map[string]*Command),
Execute: execute,
}
}
// AddSubCommand adds a subcommand to a command.
func (c *Command) AddSubCommand(subCmd *Command) {
c.SubCommands[subCmd.Name] = subCmd
}
// FindSubCommand looks for a subcommand by name.
func (c *Command) FindSubCommand(name string) (*Command, bool) {
subCmd, found := c.SubCommands[name]
return subCmd, found
}
// ExecuteCommand executes the command with the provided arguments.
func ExecuteCommand(rootCmd *Command, args []string) error {
if len(args) < 1 {
fmt.Println("No command provided")
return nil
}
cmdName := args[0]
subArgs := args[1:]
cmd, found := rootCmd.FindSubCommand(cmdName)
if !found {
fmt.Printf("Unknown command: %s\n", cmdName)
return nil
}
// Look for sub-subcommands if applicable.
if len(subArgs) > 0 {
subCmdName := subArgs[0]
subCmd, found := cmd.FindSubCommand(subCmdName)
if found {
// Parse flags for sub-subcommands.
subCmd.FlagSet.Parse(subArgs[1:])
subCmd.Execute(subCmd, subCmd.FlagSet.Args())
return nil
}
}
// Parse flags for direct subcommands.
cmd.FlagSet.Parse(subArgs)
cmd.Execute(cmd, cmd.FlagSet.Args())
return nil
}
func init() {
configCmd := NewCommand("config", "Configuration management", nil)
editCmd := NewCommand("edit", "Edit a configuration option", func(cmd *Command, args []string) {
configOption := cmd.FlagSet.Lookup("config-option").Value.String()
if configOption == "" {
fmt.Println("No config option specified")
return
}
newValue := cmd.FlagSet.Arg(0) // Assumes the new value is the first argument after flags
if newValue == "" {
fmt.Println("No new value specified for the config option")
return
}
if err := EditConfigOption(configOption, newValue); err != nil {
fmt.Println("Error editing config option:", err)
return
}
fmt.Println("Config option updated successfully")
})
editCmd.FlagSet.String("config-option", "", "The configuration option to edit")
openCmd := NewCommand("open", "Open the configuration in nano", func(cmd *Command, args []string) {
if err := OpenConfigInNano(); err != nil {
fmt.Println("Error opening config in nano:", err)
return
}
fmt.Println("Configuration opened in nano")
})
configCmd.AddSubCommand(editCmd)
configCmd.AddSubCommand(openCmd)
RootCmd.AddSubCommand(configCmd)
}

2
go.mod
View File

@ -1,3 +1,3 @@
module BackGo module pixelridgesoftworks.com/BackGo
go 1.22.0 go 1.22.0

15
main.go
View File

@ -0,0 +1,15 @@
package main
import (
"fmt"
"os"
"pixelridgesoftworks.com/BackGo/cmd"
)
func main() {
// Correctly pass RootCmd as it's already a *Command
if err := cmd.ExecuteCommand(cmd.RootCmd, os.Args[1:]); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}