From 2dd8c427b3501ea759845b79f9f523d87f7674e8 Mon Sep 17 00:00:00 2001 From: Luther Date: Mon, 20 Jan 2020 01:57:10 -0700 Subject: [PATCH] added backup, restore and edit --- cmd/add.go | 9 +++++---- cmd/backup.go | 21 +++++++++++++++++++-- cmd/check.go | 7 ++++--- cmd/edit.go | 38 ++++++++++++++++++++++++++++++++++++++ cmd/list.go | 8 +++++--- cmd/main.go | 36 ++++++++++++++++++++++++++++++++++-- cmd/remove.go | 12 ++++++------ cmd/restore.go | 24 +++++++++++++++++++++--- 8 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 cmd/edit.go diff --git a/cmd/add.go b/cmd/add.go index e07684d..df6dfc2 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -1,9 +1,9 @@ package cmd import ( - "fmt" "strings" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -21,7 +21,7 @@ func add(c *cli.Context) error { args := c.Args() if args.Len() < 2 { - fmt.Println("Adding an entry requires an ip and a hostname.") + logrus.Infof("adding a hostsfile entry requires an ip and a hostname.") return nil } @@ -47,11 +47,12 @@ func add(c *cli.Context) error { return cli.NewExitError(err.Error(), 2) } + logrus.Debugln("flushing hosts file to disk") err = hostsfile.Flush() if err != nil { return cli.NewExitError(err.Error(), 2) } - fmt.Printf("Added: %s %s\n", ip, strings.Join(hostEntries, " ")) - return nil + logrus.Infof("hosts entry added: %s %s\n", ip, strings.Join(hostEntries, " ")) + return debugFooter(c) } diff --git a/cmd/backup.go b/cmd/backup.go index 3ce0c1e..59e61c1 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -1,8 +1,9 @@ package cmd import ( - "fmt" + "path/filepath" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -22,6 +23,22 @@ func Backup() *cli.Command { } func backup(c *cli.Context) error { - fmt.Println("todo") + hostsfile, err := loadHostsfile(c) + if err != nil { + return err + } + + output := c.String("output") + if output == "" { + output = filepath.Join( + filepath.Dir(hostsfile.Path), + "."+filepath.Base(hostsfile.Path)) + } + + _, err = copyFile(hostsfile.Path, output) + if err != nil { + return err + } + logrus.Infof("backup complete") return debugFooter(c) } diff --git a/cmd/check.go b/cmd/check.go index 79a62ab..d9c4e8d 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -4,6 +4,7 @@ import ( "fmt" "net" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -18,7 +19,7 @@ func Check() *cli.Command { } func check(c *cli.Context) error { if c.Args().Len() < 1 { - fmt.Println("No input, pass an ip address or hostname to check.") + logrus.Infof("No input, pass an ip address or hostname to check.") return nil } @@ -30,13 +31,13 @@ func check(c *cli.Context) error { if net.ParseIP(input) != nil { if hostsfile.HasIp(input) { - fmt.Printf("%s exists in hosts life\n", input) + logrus.Infof("%s exists in hosts file\n", input) return nil } } if hostsfile.HasHostname(input) { - fmt.Printf("%s exists in hosts life\n", input) + logrus.Infof("%s exists in hosts file\n", input) return nil } diff --git a/cmd/edit.go b/cmd/edit.go new file mode 100644 index 0000000..72d3af1 --- /dev/null +++ b/cmd/edit.go @@ -0,0 +1,38 @@ +package cmd + +import ( + "os" + "os/exec" + + "github.com/urfave/cli/v2" +) + +func Edit() *cli.Command { + return &cli.Command{ + Name: "edit", + Aliases: []string{"e"}, + Usage: "Open hosts file in an editor, default vim", + Action: edit, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "editor", + Aliases: []string{"e"}, + Usage: "Which file editor to use, defaults vim", + Value: "vim", + }, + }, + } +} + +func edit(c *cli.Context) error { + hostsfile, err := loadHostsfile(c) + if err != nil { + return err + } + + cmd := exec.Command(c.String("editor"), hostsfile.Path) + cmd.Stdout = os.Stdout + cmd.Stdin = os.Stdin + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/cmd/list.go b/cmd/list.go index 5ee0f0f..4c5efd7 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -14,8 +15,9 @@ func List() *cli.Command { Action: list, Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "all", - Usage: "Show all entries in the hosts file including commented lines.", + Name: "all", + Aliases: []string{"a"}, + Usage: "Show all entries in the hosts file including commented lines.", }, }, } @@ -39,7 +41,7 @@ func list(c *cli.Context) error { lineOutput = fmt.Sprintf("%s # <<< Malformed!", lineOutput) } - fmt.Println(lineOutput) + logrus.Infof(lineOutput) } return debugFooter(c) diff --git a/cmd/main.go b/cmd/main.go index 6506a36..f877f72 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,10 +2,12 @@ package cmd import ( "fmt" + "io" "os" "github.com/goodhosts/hostsfile" "github.com/olekukonko/tablewriter" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -22,6 +24,7 @@ func Commands() []*cli.Command { Debug(), Backup(), Restore(), + Edit(), } } @@ -30,13 +33,15 @@ func DefaultAction(c *cli.Context) error { } func loadHostsfile(c *cli.Context) (hostsfile.Hosts, error) { - customHostsfile := c.String("custom") + customHostsfile := c.String("file") var hfile hostsfile.Hosts var err error if customHostsfile != "" { + logrus.Debugf("loading custom hosts file: %s\n", customHostsfile) hfile, err = hostsfile.NewCustomHosts(customHostsfile) } else { + logrus.Debugf("loading default hosts file: %s\n", hostsfile.HostsFilePath) hfile, err = hostsfile.NewHosts() } @@ -61,7 +66,7 @@ func debugFooter(c *cli.Context) error { return err } - fmt.Printf("%s\n", hostsfile.Path) + logrus.Infof("hosts file path: %s\n", hostsfile.Path) var comments, empty, entry, malformed int for _, line := range hostsfile.Lines { @@ -101,3 +106,30 @@ func debugFooter(c *cli.Context) error { return nil } + +func copyFile(src, dst string) (int64, error) { + logrus.Debugf("copying file: src %s, dst %s", + src, dst) + sourceFileStat, err := os.Stat(src) + if err != nil { + return 0, err + } + + if !sourceFileStat.Mode().IsRegular() { + return 0, fmt.Errorf("%s is not a regular file", src) + } + + source, err := os.Open(src) + if err != nil { + return 0, err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return 0, err + } + defer destination.Close() + nBytes, err := io.Copy(destination, source) + return nBytes, err +} diff --git a/cmd/remove.go b/cmd/remove.go index a33d9d1..19c829e 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -1,11 +1,11 @@ package cmd import ( - "fmt" "net" "strings" "github.com/goodhosts/hostsfile" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -26,7 +26,7 @@ func remove(c *cli.Context) error { } if args.Len() == 0 { - return cli.NewExitError("No input.", 1) + return cli.NewExitError("no input", 1) } if args.Len() == 1 { //could be ip or hostname @@ -63,13 +63,13 @@ func remove(c *cli.Context) error { return cli.NewExitError(err.Error(), 2) } - fmt.Printf("Removed: %s\n", strings.Join(hostEntries, " ")) - return nil + logrus.Infof("entry removed: %s\n", strings.Join(hostEntries, " ")) + return debugFooter(c) } func processSingleArg(hostsfile hostsfile.Hosts, arg string) error { if net.ParseIP(arg) != nil { - fmt.Printf("Removing ip %s\n", arg) + logrus.Infof("removing ip %s\n", arg) if err := hostsfile.RemoveByIp(arg); err != nil { return err } @@ -80,7 +80,7 @@ func processSingleArg(hostsfile hostsfile.Hosts, arg string) error { return nil } - fmt.Printf("Removing hostname %s\n", arg) + logrus.Infof("removing hostname %s\n", arg) if err := hostsfile.RemoveByHostname(arg); err != nil { return err diff --git a/cmd/restore.go b/cmd/restore.go index fd10a6c..a8d6080 100644 --- a/cmd/restore.go +++ b/cmd/restore.go @@ -1,8 +1,9 @@ package cmd import ( - "fmt" + "path/filepath" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -14,7 +15,7 @@ func Restore() *cli.Command { Flags: []cli.Flag{ &cli.StringFlag{ Name: "input", - Aliases: []string{"o"}, + Aliases: []string{"i"}, Usage: "File location to restore a backup from, default /.hosts", }, }, @@ -22,6 +23,23 @@ func Restore() *cli.Command { } func restore(c *cli.Context) error { - fmt.Println("todo") + hostsfile, err := loadHostsfile(c) + if err != nil { + // debug only, no problem if file doesn't exist we just need path + logrus.Debugf("destination hosts file not found: %s", hostsfile.Path) + } + + input := c.String("input") + if input == "" { + input = filepath.Join( + filepath.Dir(hostsfile.Path), + "."+filepath.Base(hostsfile.Path)) + } + + _, err = copyFile(input, hostsfile.Path) + if err != nil { + return err + } + return debugFooter(c) }