diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39dd26c..284568b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,24 +5,16 @@ jobs: ci: runs-on: ubuntu-latest steps: - - name: Set up Go 1.x - uses: actions/setup-go@v2 - with: - go-version: ^1.21 - id: go - name: Checkout - uses: actions/checkout@v2 - - name: Run goimports - run: | - go install golang.org/x/tools/cmd/goimports@latest - output="$($(go env GOPATH)/bin/goimports -l $(find . -type f -name "*.go" -not -path "./vendor/*"))" - test -z $output && exit 0 - $(go env GOPATH)/bin/goimports -d . - exit 1 - - name: Test - env: - GOROOT: "" - run: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.54.2 - ./bin/golangci-lint run - go test -v ./... \ No newline at end of file + uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: "1.21" + - name: Continuous Integration + uses: magefile/mage-action@v2 + with: + version: latest + args: ci + - name: Upload to Codecov + uses: codecov/codecov-action@v3 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9e228e8..e14a2e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ +coverage.txt .DS_Store /goodhosts /goodhosts.exe /.idea /dist +/bin /out /release diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2b91afc..1b22e91 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -11,7 +11,7 @@ builds: - amd64 - arm64 - arm - - 386 + - "386" - ppc64le - s390x - mips64 diff --git a/LICENSE b/LICENSE index e21ed71..94ad888 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2019 - Luther Monson +Copyright (c) 2024 - Luther Monson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile deleted file mode 100644 index b3eab96..0000000 --- a/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# Go and compilation related variables -BUILD_DIR ?= dist -BINARY_NAME := goodhosts -GOLANGCI_LINT_VERSION ?= v1.54.2 - -$(BUILD_DIR): - mkdir -p $(BUILD_DIR) - -clean: - rm -rf $(BUILD_DIR) - -golangci-lint: - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s $(GOLANGCI_LINT_VERSIONM) - -goimports: - go install golang.org/x/tools/cmd/goimports@latest - -goreleaser: - go install github.com/goreleaser/goreleaser@latest - -release: - goreleaser release - -ci: goimports golangci-lint - goimports -d . - golangci-lint run - go test -v ./... - -build: - go build -o $(BINARY_NAME) ./main.go - diff --git a/cmd/add.go b/cmd/add.go index 24819bc..f6d40ae 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -28,7 +28,6 @@ func Add() *cli.Command { } } func add(c *cli.Context) error { - args := c.Args() if args.Len() < 2 { @@ -36,7 +35,7 @@ func add(c *cli.Context) error { return nil } - hostsfile, err := loadHostsfile(c, false) + hf, err := loadHostsfile(c, false) if err != nil { return err } @@ -53,23 +52,23 @@ func add(c *cli.Context) error { hostEntries = append(hostEntries, key) } - err = hostsfile.Add(ip, hostEntries...) + err = hf.Add(ip, hostEntries...) if err != nil { return cli.Exit(err.Error(), 2) } if c.Bool("clean") { - hostsfile.Clean() + hf.Clean() } if c.Bool("dry-run") { logrus.Debugln("performing a dry run, writing output") - outputHostsfile(hostsfile, true) + outputHostsfile(hf, true) return debugFooter(c) } logrus.Debugln("flushing hosts file to disk") - if err := hostsfile.Flush(); err != nil { + if err := hf.Flush(); err != nil { return cli.Exit(err.Error(), 2) } diff --git a/cmd/backup.go b/cmd/backup.go index 7ec1a6c..543da93 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -23,7 +23,7 @@ func Backup() *cli.Command { } func backup(c *cli.Context) error { - hostsfile, err := loadHostsfile(c, false) + hf, err := loadHostsfile(c, false) if err != nil { return err } @@ -31,14 +31,14 @@ func backup(c *cli.Context) error { output := c.String("output") if output == "" { output = filepath.Join( - filepath.Dir(hostsfile.Path), - "."+filepath.Base(hostsfile.Path)) + filepath.Dir(hf.Path), + "."+filepath.Base(hf.Path)) } - _, err = copyFile(hostsfile.Path, output) - if err != nil { + if err := copyFile(hf.Path, output); err != nil { return err } + logrus.Infof("backup complete") return debugFooter(c) } diff --git a/cmd/check.go b/cmd/check.go index 7ed6cf1..ab22a49 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -23,20 +23,20 @@ func check(c *cli.Context) error { return nil } - hostsfile, err := loadHostsfile(c, true) + hf, err := loadHostsfile(c, true) if err != nil { return err } input := c.Args().First() if net.ParseIP(input) != nil { - if hostsfile.HasIp(input) { + if hf.HasIP(input) { logrus.Infof("%s exists in hosts file\n", input) return nil } } - if hostsfile.HasHostname(input) { + if hf.HasHostname(input) { logrus.Infof("%s exists in hosts file\n", input) return nil } diff --git a/cmd/clean.go b/cmd/clean.go index 256dd25..d8b251e 100644 --- a/cmd/clean.go +++ b/cmd/clean.go @@ -66,7 +66,7 @@ func clean(c *cli.Context) error { h.Clean() } else { if c.Bool("remove-duplicate-ips") { - h.RemoveDuplicateIps() + h.CombineDuplicateIPs() } if c.Bool("remove-duplicate-hosts") { h.RemoveDuplicateHosts() @@ -75,7 +75,7 @@ func clean(c *cli.Context) error { h.SortHosts() } if c.Bool("sort-ips") { - h.SortByIp() + h.SortIPs() } // needed for windows for 9/line, -1 default for linux will noop but if passed by cli we will run h.HostsPerLine(hostsfile.HostsPerLine) diff --git a/cmd/edit.go b/cmd/edit.go index 850e6d6..715b330 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -25,12 +25,12 @@ func Edit() *cli.Command { } func edit(c *cli.Context) error { - hostsfile, err := loadHostsfile(c, false) + hf, err := loadHostsfile(c, false) if err != nil { return err } - cmd := exec.Command(c.String("editor"), hostsfile.Path) + cmd := exec.Command(c.String("editor"), hf.Path) cmd.Stdout = os.Stdout cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr diff --git a/cmd/list.go b/cmd/list.go index 5cc11d8..ce45bfa 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -21,11 +21,11 @@ func List() *cli.Command { } func list(c *cli.Context) error { - hostsfile, err := loadHostsfile(c, false) + hf, err := loadHostsfile(c, false) if err != nil { return err } - outputHostsfile(hostsfile, c.Bool("all")) + outputHostsfile(hf, c.Bool("all")) return debugFooter(c) } diff --git a/cmd/main.go b/cmd/main.go index f06a23a..3e1c363 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -11,10 +11,6 @@ import ( "github.com/urfave/cli/v2" ) -func Run(c *cli.Context) error { - return list(c) -} - func Commands() []*cli.Command { return []*cli.Command{ Add(), @@ -35,26 +31,26 @@ func DefaultAction(c *cli.Context) error { func loadHostsfile(c *cli.Context, readOnly bool) (*hostsfile.Hosts, error) { customHostsfile := c.String("file") - var hfile *hostsfile.Hosts + var hf *hostsfile.Hosts var err error if customHostsfile != "" { logrus.Debugf("loading custom hosts file: %s\n", customHostsfile) - hfile, err = hostsfile.NewCustomHosts(customHostsfile) + hf, err = hostsfile.NewCustomHosts(customHostsfile) } else { logrus.Debugf("loading default hosts file: %s\n", hostsfile.HostsFilePath) - hfile, err = hostsfile.NewHosts() + hf, err = hostsfile.NewHosts() } if err != nil { - return hfile, cli.Exit(err, 1) + return hf, cli.Exit(err, 1) } - if !readOnly && !hfile.IsWritable() { - return hfile, cli.Exit("Host file not writable. Try running with elevated privileges.", 1) + if !readOnly && !hf.IsWritable() { + return hf, cli.Exit("Host file not writable. Try running with elevated privileges.", 1) } - return hfile, nil + return hf, nil } func outputHostsfile(hf *hostsfile.Hosts, all bool) { @@ -79,15 +75,15 @@ func debugFooter(c *cli.Context) error { return nil } - hostsfile, err := loadHostsfile(c, true) + hf, err := loadHostsfile(c, true) if err != nil { return err } - logrus.Infof("hosts file path: %s\n", hostsfile.Path) + logrus.Infof("hosts file path: %s\n", hf.Path) var comments, empty, entry, malformed int - for _, line := range hostsfile.Lines { + for _, line := range hf.Lines { if line.IsComment() { comments++ @@ -107,11 +103,11 @@ func debugFooter(c *cli.Context) error { } data := [][]string{ - []string{"lines", fmt.Sprintf("%d", len(hostsfile.Lines))}, - []string{"entries", fmt.Sprintf("%d", entry)}, - []string{"comments", fmt.Sprintf("%d", comments)}, - []string{"empty", fmt.Sprintf("%d", empty)}, - []string{"malformed", fmt.Sprintf("%d", malformed)}, + {"lines", fmt.Sprintf("%d", len(hf.Lines))}, + {"entries", fmt.Sprintf("%d", entry)}, + {"comments", fmt.Sprintf("%d", comments)}, + {"empty", fmt.Sprintf("%d", empty)}, + {"malformed", fmt.Sprintf("%d", malformed)}, } table := tablewriter.NewWriter(os.Stdout) @@ -125,29 +121,40 @@ func debugFooter(c *cli.Context) error { return nil } -func copyFile(src, dst string) (int64, error) { +func copyFile(src, dst string) (err error) { logrus.Debugf("copying file: src %s, dst %s", src, dst) - sourceFileStat, err := os.Stat(src) + + var fi os.FileInfo + fi, err = os.Stat(src) if err != nil { - return 0, err + return err } - if !sourceFileStat.Mode().IsRegular() { - return 0, fmt.Errorf("%s is not a regular file", src) + if !fi.Mode().IsRegular() { + return fmt.Errorf("%s is not a regular file", src) } - source, err := os.Open(src) + var source *os.File + source, err = os.Open(src) if err != nil { - return 0, err + return err } - defer source.Close() - destination, err := os.Create(dst) + defer func() { + err = source.Close() + }() + + var destination *os.File + destination, err = os.Create(dst) if err != nil { - return 0, err + return err } - defer destination.Close() - nBytes, err := io.Copy(destination, source) - return nBytes, err + + defer func() { + err = destination.Close() + }() + + _, err = io.Copy(destination, source) + return } diff --git a/cmd/remove.go b/cmd/remove.go index 5ab5ee5..d63feee 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -32,7 +32,7 @@ func Remove() *cli.Command { func remove(c *cli.Context) error { args := c.Args() - hostsfile, err := loadHostsfile(c, false) + hf, err := loadHostsfile(c, false) if err != nil { return err } @@ -42,7 +42,7 @@ func remove(c *cli.Context) error { } if args.Len() == 1 { //could be ip or hostname - return processSingleArg(hostsfile, args.Slice()[0]) + return processSingleArg(hf, args.Slice()[0]) } uniqueHosts := map[string]bool{} @@ -57,8 +57,8 @@ func remove(c *cli.Context) error { } if net.ParseIP(args.Slice()[0]) != nil { - if hostsfile.HasIp(args.Slice()[0]) { - err = hostsfile.Remove(args.Slice()[0], hostEntries...) + if hf.HasIP(args.Slice()[0]) { + err = hf.Remove(args.Slice()[0], hostEntries...) if err != nil { return cli.Exit(err.Error(), 2) } @@ -66,24 +66,24 @@ func remove(c *cli.Context) error { } else { hostEntries = append(hostEntries, args.Slice()[0]) for _, value := range hostEntries { - if err := hostsfile.RemoveByHostname(value); err != nil { + if err := hf.RemoveByHostname(value); err != nil { return err } } } if c.Bool("clean") { - hostsfile.Clean() + hf.Clean() } if c.Bool("dry-run") { logrus.Debugln("performing a dry run, writing output") - outputHostsfile(hostsfile, true) + outputHostsfile(hf, true) return debugFooter(c) } logrus.Debugln("flushing hosts file to disk") - if err := hostsfile.Flush(); err != nil { + if err := hf.Flush(); err != nil { return cli.Exit(err.Error(), 2) } @@ -91,13 +91,11 @@ func remove(c *cli.Context) error { return debugFooter(c) } -func processSingleArg(hostsfile *hostsfile.Hosts, arg string) error { +func processSingleArg(hf *hostsfile.Hosts, arg string) error { if net.ParseIP(arg) != nil { logrus.Infof("removing ip %s\n", arg) - if err := hostsfile.RemoveByIp(arg); err != nil { - return err - } - if err := hostsfile.Flush(); err != nil { + hf.RemoveByIP(arg) + if err := hf.Flush(); err != nil { return err } @@ -106,10 +104,10 @@ func processSingleArg(hostsfile *hostsfile.Hosts, arg string) error { logrus.Infof("removing hostname %s\n", arg) - if err := hostsfile.RemoveByHostname(arg); err != nil { + if err := hf.RemoveByHostname(arg); err != nil { return err } - if err := hostsfile.Flush(); err != nil { + if err := hf.Flush(); err != nil { return err } diff --git a/cmd/restore.go b/cmd/restore.go index 2ccdaed..dd0e4c7 100644 --- a/cmd/restore.go +++ b/cmd/restore.go @@ -23,21 +23,20 @@ func Restore() *cli.Command { } func restore(c *cli.Context) error { - hostsfile, err := loadHostsfile(c, false) + hf, err := loadHostsfile(c, false) 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) + logrus.Debugf("destination hosts file not found: %s", hf.Path) } input := c.String("input") if input == "" { input = filepath.Join( - filepath.Dir(hostsfile.Path), - "."+filepath.Base(hostsfile.Path)) + filepath.Dir(hf.Path), + "."+filepath.Base(hf.Path)) } - _, err = copyFile(input, hostsfile.Path) - if err != nil { + if err := copyFile(input, hf.Path); err != nil { return err } diff --git a/go.mod b/go.mod index c648bcb..fbade7e 100644 --- a/go.mod +++ b/go.mod @@ -3,19 +3,26 @@ module github.com/goodhosts/cli go 1.21 require ( - github.com/goodhosts/hostsfile v0.1.3 + github.com/goodhosts/hostsfile v0.1.6 + github.com/magefile/mage v1.15.0 github.com/olekukonko/tablewriter v0.0.5 github.com/sirupsen/logrus v1.9.3 + github.com/stretchr/testify v1.8.2 github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 - github.com/urfave/cli/v2 v2.25.7 + github.com/urfave/cli/v2 v2.26.0 + github.com/uwu-tools/magex v0.10.0 ) require ( + github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 44eed0f..48af9e6 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,9 @@ +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U= -github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU= +github.com/corpix/uarand v0.0.0-20170723150923-031be390f409 h1:9A+mfQmwzZ6KwUXPc8nHxFtKgn9VIvO3gXAOspIcE3s= +github.com/corpix/uarand v0.0.0-20170723150923-031be390f409/go.mod h1:JSm890tOkDN+M1jqN8pUGDKnzJrsVbJwSMHBY4zwz7M= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -9,11 +11,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/goodhosts/hostsfile v0.1.3 h1:z5Qt3YZhrS/HT+pwWJMhQ3IrKZ44ZvAKx8UXz5RhydE= -github.com/goodhosts/hostsfile v0.1.3/go.mod h1:HcPMANDthvsRjz5mWQuJrdWUgheVDz5MIm9bkBYHT78= -github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 h1:Mo9W14pwbO9VfRe+ygqZ8dFbPpoIK1HFrG/zjTuQ+nc= -github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo= +github.com/goodhosts/hostsfile v0.1.6 h1:aK6DxpNV6pZ1NbdvNE2vYBMTnvIJF5O2J/8ZOlp2eMY= +github.com/goodhosts/hostsfile v0.1.6/go.mod h1:bkCocEIf3Ca0hcBustUZoWYhOgKUaIK+47m8fBjoBx8= +github.com/icrowley/fake v0.0.0-20221112152111-d7b7e2276db2 h1:qU3v73XG4QAqCPHA4HOpfC1EfUvtLIDvQK4mNQ0LvgI= +github.com/icrowley/fake v0.0.0-20221112152111-d7b7e2276db2/go.mod h1:dQ6TM/OGAe+cMws81eTe4Btv1dKxfPZ2CX+YaAFAPN4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= +github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -27,18 +31,26 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk= github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI= +github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/uwu-tools/magex v0.10.0 h1:eDDHw9izUPXEKXejY26VCtTK4LjuDoGkyWpgGscFO80= +github.com/uwu-tools/magex v0.10.0/go.mod h1:TrSEhrL1xHfJVy6n05AUwFdcQndgwrbgL5ybPNKWmVY= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/mage/install/install.go b/mage/install/install.go new file mode 100644 index 0000000..058007b --- /dev/null +++ b/mage/install/install.go @@ -0,0 +1,44 @@ +package install + +import ( + "fmt" + + "github.com/magefile/mage/mg" + "github.com/uwu-tools/magex/pkg" +) + +const ( + GoreleaserVersion = "v1.22.1" +) + +// Dependencies install all dependencies +func Dependencies() error { + fmt.Println("Installing Dependencies...") + mg.Deps(Golangcilint, Goreleaser) + + return nil +} + +// Golangcilint install golangci-lint +func Golangcilint() error { + fmt.Println("Installing GolangCI Lint...") + opts := pkg.EnsurePackageOptions{ + Name: "github.com/golangci/golangci-lint/cmd/golangci-lint", + DefaultVersion: "v1.54.2", + VersionCommand: "version", + Destination: "bin", + } + return pkg.EnsurePackageWith(opts) +} + +// Goreleaser install goreleaser +func Goreleaser() error { + fmt.Println("Installing goreleaser...") + opts := pkg.EnsurePackageOptions{ + Name: "github.com/goreleaser/goreleaser", + DefaultVersion: "v1.22.1", + VersionCommand: "--version", + Destination: "bin", + } + return pkg.EnsurePackageWith(opts) +} diff --git a/mage/test/test.go b/mage/test/test.go new file mode 100644 index 0000000..6256b5e --- /dev/null +++ b/mage/test/test.go @@ -0,0 +1,45 @@ +package test + +import ( + "fmt" + + "github.com/goodhosts/cli/mage/install" + "github.com/magefile/mage/mg" + + "github.com/magefile/mage/sh" +) + +// Unit run all unit tests +func Unit() error { + fmt.Println("Running Tests...") + return sh.RunV("go", "test") +} + +// Build run a test build to confirm no compilation errors +func Build() error { + fmt.Println("Running Build...") + mg.Deps(install.Goreleaser) + return sh.RunV("goreleaser", "--clean", "--skip=validate", "--skip=publish", "--snapshot") +} + +// Coverage run all unit tests and output coverage +func Coverage() error { + fmt.Println("Running Tests with Coverage...") + return sh.RunV("go", "test", "-v", "-coverprofile=coverage.txt", ".") +} + +// HTML display the html coverage report from the cover tool +func HTML() error { + if err := Coverage(); err != nil { + return err + } + return sh.RunV("go", "tool", "cover", "-html", "coverage.txt") +} + +// Func display the func coverage report from the cover tool +func Func() error { + if err := Coverage(); err != nil { + return err + } + return sh.RunV("go", "tool", "cover", "-func", "coverage.txt") +} diff --git a/magefile.go b/magefile.go new file mode 100644 index 0000000..dec58fa --- /dev/null +++ b/magefile.go @@ -0,0 +1,52 @@ +//go:build mage +// +build mage + +package main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/magefile/mage/mg" + "github.com/magefile/mage/sh" + "github.com/uwu-tools/magex/xplat" + + //mage:import install + "github.com/goodhosts/cli/mage/install" + + //mage:import test + "github.com/goodhosts/cli/mage/test" +) + +func init() { + cwd, _ := os.Getwd() + xplat.EnsureInPath(filepath.Join(cwd, "bin")) +} + +// run everything for ci process (install deps, lint, coverage, build) +func Ci() error { + fmt.Println("Running Continuous Integration...") + mg.Deps(install.Dependencies) + mg.Deps(Lint, test.Coverage) + mg.Deps(test.Build) + return nil +} + +// run the linter +func Lint() error { + mg.Deps(install.Golangcilint) + fmt.Println("Running Linter...") + return sh.RunV("./bin/golangci-lint", "run") +} + +// delete files and paths made by mage +func Clean() error { + for _, path := range []string{"coverage.txt", "dist", "bin"} { + if err := sh.Rm(path); err != nil { + return err + } + } + + return nil +} diff --git a/main.go b/main.go index bd1e569..30d8415 100644 --- a/main.go +++ b/main.go @@ -18,54 +18,11 @@ var ( date = "unknown" ) -func main() { - app := &cli.App{ - Name: "goodhosts", - Usage: "manage your hosts file goodly", - Action: cmd.DefaultAction, - Commands: append(cmd.Commands(), Version()), - Before: func(ctx *cli.Context) error { - if ctx.Bool("debug") { - logrus.SetLevel(logrus.DebugLevel) - } else { - // treat logrus like fmt.Print - logrus.SetFormatter(&easy.Formatter{ - LogFormat: "%msg%", - }) - } - if ctx.Bool("quiet") { - logrus.SetOutput(io.Discard) - } - return nil - }, - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "file", - Aliases: []string{"f"}, - Value: "", - Usage: fmt.Sprintf("override the default hosts: %s", hostsfile.HostsFilePath), - }, - &cli.BoolFlag{ - Name: "debug", - Aliases: []string{"d"}, - Usage: "Turn on verbose debug logging", - }, - &cli.BoolFlag{ - Name: "quiet", - Aliases: []string{"q"}, - Usage: "Turn on off all logging", - }, - }, - } - - err := app.Run(os.Args) - if err != nil { - logrus.Fatal(err) - } -} - -func Version() *cli.Command { - return &cli.Command{ +var app = &cli.App{ + Name: "goodhosts", + Usage: "manage your hosts file goodly", + Action: cmd.DefaultAction, + Commands: append(cmd.Commands(), &cli.Command{ Name: "version", Usage: "", Aliases: []string{"v", "ver"}, @@ -73,5 +30,48 @@ func Version() *cli.Command { logrus.Infof("goodhosts %s@%s built on %s", version, commit, date) return nil }, + }), + Before: func(ctx *cli.Context) error { + if ctx.Bool("debug") { + logrus.SetLevel(logrus.DebugLevel) + logrus.SetFormatter(&logrus.TextFormatter{}) + } else { + // treat logrus like fmt.Print + logrus.SetFormatter(&easy.Formatter{ + LogFormat: "%msg%", + }) + } + if ctx.Bool("quiet") { + logrus.SetOutput(io.Discard) + } + return nil + }, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "file", + Aliases: []string{"f"}, + Value: "", + Usage: fmt.Sprintf("override the default hosts: %s", hostsfile.HostsFilePath), + }, + &cli.BoolFlag{ + Name: "debug", + Aliases: []string{"d"}, + Usage: "Turn on verbose debug logging", + }, + &cli.BoolFlag{ + Name: "quiet", + Aliases: []string{"q"}, + Usage: "Turn on off all logging", + }, + }, +} + +func main() { + if err := run(os.Args); err != nil { + logrus.Fatal(err) } } + +func run(args []string) error { + return app.Run(args) +} diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..5c60b2a --- /dev/null +++ b/main_test.go @@ -0,0 +1,41 @@ +package main + +import ( + "bytes" + "os" + "strings" + "testing" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestVersion(t *testing.T) { + out := &bytes.Buffer{} + logrus.SetOutput(out) + + args := os.Args[0:1] + args = append(args, "version") + assert.Nil(t, run(args)) + assert.Equal(t, "goodhosts dev@none built on unknown", out.String()) +} + +func TestDebug(t *testing.T) { + out := &bytes.Buffer{} + logrus.SetOutput(out) + + args := os.Args[0:1] + args = append(args, "--debug", "version") + assert.Nil(t, run(args)) + assert.True(t, strings.Contains(out.String(), "level=info msg=\"goodhosts dev@none built on unknown\"")) +} + +func TestQuiet(t *testing.T) { + out := &bytes.Buffer{} + logrus.SetOutput(out) + + args := os.Args[0:1] + args = append(args, "--quiet", "version") + assert.Nil(t, run(args)) + assert.Empty(t, out.String()) +}