Skip to content

Commit

Permalink
Merge pull request #26 from goodhosts/win-hosts
Browse files Browse the repository at this point in the history
fix windows hosts per line problem
  • Loading branch information
luthermonson authored Dec 1, 2021
2 parents 4c3da6d + bbaa605 commit 142c66e
Show file tree
Hide file tree
Showing 69 changed files with 23,038 additions and 82 deletions.
9 changes: 1 addition & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,7 @@ jobs:
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 .)"
test -z $output && exit 0
$(go env GOPATH)/bin/goimports -d .
exit 1
- name: Test
- name: Validate and Test
env:
GOROOT: ""
run: |
Expand Down
9 changes: 0 additions & 9 deletions const.go

This file was deleted.

7 changes: 0 additions & 7 deletions const_windows.go

This file was deleted.

12 changes: 11 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,14 @@ module github.com/goodhosts/hostsfile

go 1.17

require github.com/dimchansky/utfbom v1.1.1
require (
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/dimchansky/utfbom v1.1.1
github.com/stretchr/testify v1.7.0
)

require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
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/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
33 changes: 25 additions & 8 deletions hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"path/filepath"
"sort"

"github.com/asaskevich/govalidator"
"github.com/dimchansky/utfbom"
)

Expand All @@ -17,7 +18,7 @@ type Hosts struct {
Lines []HostsLine
}

// Return a new instance of ``Hosts`` using the default hosts file path.
// NewHosts return a new instance of ``Hosts`` using the default hosts file path.
func NewHosts() (Hosts, error) {
osHostsFilePath := os.ExpandEnv(filepath.FromSlash(HostsFilePath))

Expand All @@ -28,7 +29,7 @@ func NewHosts() (Hosts, error) {
return NewCustomHosts(osHostsFilePath)
}

// Return a new instance of ``Hosts`` using a custom hosts file path.
// NewCustomHosts return a new instance of ``Hosts`` using a custom hosts file path.
func NewCustomHosts(osHostsFilePath string) (Hosts, error) {
hosts := Hosts{
Path: osHostsFilePath,
Expand All @@ -41,7 +42,7 @@ func NewCustomHosts(osHostsFilePath string) (Hosts, error) {
return hosts, nil
}

// Return ```true``` if hosts file is writable.
// IsWritable return ```true``` if hosts file is writable.
func (h *Hosts) IsWritable() bool {
file, err := os.OpenFile(h.Path, os.O_WRONLY, 0660)
if err != nil {
Expand Down Expand Up @@ -75,6 +76,7 @@ func (h *Hosts) Load() error {

// Flush any changes made to hosts file.
func (h Hosts) Flush() error {
h.preFlushClean()
file, err := os.Create(h.Path)
if err != nil {
return err
Expand Down Expand Up @@ -116,6 +118,9 @@ func (h *Hosts) Add(ip string, hosts ...string) error {
// add new hosts to the correct position for the ip
hostsCopy := h.Lines[position].Hosts
for _, addHost := range hosts {
if !govalidator.IsDNSName(addHost) {
return fmt.Errorf("hostname is not a valid dns name: %s", addHost)
}
if itemInSlice(addHost, hostsCopy) {
continue // host exists for ip already
}
Expand All @@ -129,7 +134,7 @@ func (h *Hosts) Add(ip string, hosts ...string) error {
return nil
}

// merge dupelicate ips and hosts per ip
// Clean merge duplicate ips and hosts per ip
func (h *Hosts) Clean() {
h.RemoveDuplicateIps()
h.RemoveDuplicateHosts()
Expand All @@ -138,12 +143,12 @@ func (h *Hosts) Clean() {
h.HostsPerLine(HostsPerLine)
}

// Return a bool if ip/host combo in hosts file.
// Has return a bool if ip/host combo in hosts file.
func (h Hosts) Has(ip string, host string) bool {
return h.getHostPosition(ip, host) != -1
}

// Return a bool if hostname in hosts file.
// HasHostname return a bool if hostname in hosts file.
func (h Hosts) HasHostname(host string) bool {
return h.getHostnamePosition(host) != -1
}
Expand Down Expand Up @@ -189,7 +194,7 @@ func (h *Hosts) Remove(ip string, hosts ...string) error {
return nil
}

// Remove entries by hostname from the hosts file.
// RemoveByHostname remove entries by hostname from the hosts file.
func (h *Hosts) RemoveByHostname(host string) error {
newLines := []HostsLine{}
for _, line := range h.Lines {
Expand Down Expand Up @@ -243,7 +248,7 @@ func (h *Hosts) SortHosts() {
}
}

// convert to net.IP and byte.Compare
// SortByIp convert to net.IP and byte.Compare
func (h *Hosts) SortByIp() {
sortedIps := make([]net.IP, 0, len(h.Lines))
for _, l := range h.Lines {
Expand All @@ -265,6 +270,8 @@ func (h *Hosts) SortByIp() {
}

func (h *Hosts) HostsPerLine(count int) {
// restacks everything into 1 ip again so we can do the split, do this even if count is -1 so it can reset the slice
h.RemoveDuplicateIps()
if count <= 0 {
return
}
Expand All @@ -281,6 +288,7 @@ func (h *Hosts) HostsPerLine(count int) {
if end > i+count {
end = i + count
}

lineCopy.Hosts = line.Hosts[i:end]
lineCopy.Raw = lineCopy.ToRaw()
newLines = append(newLines, lineCopy)
Expand Down Expand Up @@ -365,3 +373,12 @@ func (h Hosts) getIpPosition(ip string) int {

return -1
}

func buildRawLine(ip string, hosts []string) string {
output := ip
for _, host := range hosts {
output = fmt.Sprintf("%s %s", output, host)
}

return output
}
25 changes: 25 additions & 0 deletions hosts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
)

func TestHostsLineIsComment(t *testing.T) {
Expand Down Expand Up @@ -255,3 +257,26 @@ func TestHostsClean(t *testing.T) {
t.Errorf("Clean did not update Raw properly: %s", hosts.Lines[0].ToRaw())
}
}

func TestHosts_Add(t *testing.T) {
hosts := new(Hosts)
assert.Nil(t, hosts.Add("127.0.0.2", "host1", "host2", "host3", "host4", "host5", "host6", "host7", "host8", "host9", "hosts10")) // valid use with variatic args
assert.Error(t, assert.AnError, hosts.Add("127.0.0.2", "host11 host12 host13 host14 host15 host16 host17 host18 hosts19 hosts20")) // invalid use
assert.Len(t, hosts.Lines, 1)
assert.Nil(t, hosts.Add("127.0.0.3", "host1", "host2", "host3", "host4", "host5", "host6", "host7", "host8", "host9", "hosts10"))
assert.Len(t, hosts.Lines, 2)
assert.Error(t, assert.AnError, hosts.Add("127.0.0.3", "invalid hostname"))
assert.Error(t, assert.AnError, hosts.Add("127.0.0.3", ".invalid*hostname"))
}

func TestHosts_HostsPerLine(t *testing.T) {
hosts := new(Hosts)
assert.Nil(t, hosts.Add("127.0.0.2", "host1", "host2", "host3", "host4", "host5", "host6", "host7", "host8", "host9", "hosts10"))
assert.Nil(t, hosts.Add("127.0.0.2", "host11", "host12", "host13", "host14", "host15", "host16", "host17", "host18", "host19", "hosts20"))
hosts.HostsPerLine(1)
assert.Len(t, hosts.Lines, 20)
hosts.HostsPerLine(2)
assert.Len(t, hosts.Lines, 10)
hosts.HostsPerLine(9) // windows
assert.Len(t, hosts.Lines, 3)
}
2 changes: 1 addition & 1 deletion hostsline.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type HostsLine struct {

const commentChar string = "#"

// Return a new instance of ```HostsLine```.
// NewHostsLine return a new instance of ```HostsLine```.
func NewHostsLine(raw string) HostsLine {
output := HostsLine{Raw: raw}
if output.IsComment() { //whole line is comment
Expand Down
29 changes: 29 additions & 0 deletions slice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package hostsfile

func itemInSlice(item string, list []string) bool {
for _, i := range list {
if i == item {
return true
}
}

return false
}

func removeFromSlice(s string, slice []string) []string {
pos := findPositionInSlice(s, slice)
for pos > -1 {
slice = append(slice[:pos], slice[pos+1:]...)
pos = findPositionInSlice(s, slice)
}
return slice
}

func findPositionInSlice(s string, slice []string) int {
for index, v := range slice {
if v == s {
return index
}
}
return -1
}
File renamed without changes.
55 changes: 7 additions & 48 deletions utils.go
Original file line number Diff line number Diff line change
@@ -1,52 +1,11 @@
//go:build !windows

package hostsfile

import (
"fmt"
const (
HostsPerLine = -1 // unlimited
HostsFilePath = "/etc/hosts"
eol = "\n"
)

func itemInSlice(item string, list []string) bool {
for _, i := range list {
if i == item {
return true
}
}

return false
}

func removeFromSlice(s string, slice []string) []string {
pos := findPositionInSlice(s, slice)
for pos > -1 {
slice = append(slice[:pos], slice[pos+1:]...)
pos = findPositionInSlice(s, slice)
}
return slice
}

func findPositionInSlice(s string, slice []string) int {
for index, v := range slice {
if v == s {
return index
}
}
return -1
}

//func sliceContainsItem(item string, list []string) bool {
// for _, i := range list {
// if strings.Contains(i, item) {
// return true
// }
// }
//
// return false
//}

func buildRawLine(ip string, hosts []string) string {
output := ip
for _, host := range hosts {
output = fmt.Sprintf("%s %s", output, host)
}

return output
}
func (h *Hosts) preFlushClean() {} // no op
12 changes: 12 additions & 0 deletions utils_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package hostsfile

const (
HostsFilePath = "${SystemRoot}/System32/drivers/etc/hosts"
HostsPerLine = 9
eol = "\r\n"
)

func (h *Hosts) preFlushClean() {
// need to force hosts per line always on windows see https://github.com/goodhosts/hostsfile/issues/18
h.HostsPerLine(HostsPerLine)
}
15 changes: 15 additions & 0 deletions vendor/github.com/asaskevich/govalidator/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions vendor/github.com/asaskevich/govalidator/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 142c66e

Please sign in to comment.