diff --git a/Makefile b/Makefile
index a98717e3..657176de 100644
--- a/Makefile
+++ b/Makefile
@@ -77,6 +77,9 @@ go.vet:
go.fmt:
@ test -z "$(shell go fmt $(GO_SOURCE))"
+go.staticcheck:
+ @ go run honnef.co/go/tools/cmd/staticcheck $(GO_SOURCE)
+
go.install:
@ go build --trimpath \
--ldflags="-s -w \
@@ -169,8 +172,8 @@ budjs.test:
##
test: test.dev
-test.dev: go.tools go.generate go.fmt go.vet budjs.check budjs.test go.test
-test.all: go.tools go.generate go.vet budjs.check budjs.test go.test
+test.dev: go.tools go.generate go.fmt go.vet go.staticcheck budjs.check budjs.test go.test
+test.all: go.tools go.generate go.vet go.staticcheck budjs.check budjs.test go.test
##
# CI
diff --git a/framework/controller/controllerrt/request/unmarshal.go b/framework/controller/controllerrt/request/unmarshal.go
index 79851379..27fe7f6b 100644
--- a/framework/controller/controllerrt/request/unmarshal.go
+++ b/framework/controller/controllerrt/request/unmarshal.go
@@ -3,7 +3,6 @@ package request
import (
"encoding/json"
"io"
- "io/ioutil"
"mime"
"net/http"
"net/url"
@@ -60,7 +59,7 @@ func unmarshalForm(r *http.Request, v interface{}) error {
}
func unmarshalJSON(r io.Reader, v interface{}) error {
- data, err := ioutil.ReadAll(r)
+ data, err := io.ReadAll(r)
if err != nil {
return err
}
diff --git a/framework/web/welcome/welcome.go b/framework/web/welcome/welcome.go
index ba5c8646..1999dcb2 100644
--- a/framework/web/welcome/welcome.go
+++ b/framework/web/welcome/welcome.go
@@ -2,7 +2,6 @@ package welcome
import (
"embed"
- _ "embed"
"io/fs"
"net/http"
diff --git a/go.mod b/go.mod
index 55acf025..6f7057d7 100644
--- a/go.mod
+++ b/go.mod
@@ -26,11 +26,13 @@ require (
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f
+ honnef.co/go/tools v0.3.3
rogchap.com/v8go v0.7.0
src.techknowlogick.com/xgo v1.4.1-0.20220413212431-091a0a22b814
)
require (
+ github.com/BurntSushi/toml v0.4.1 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect
github.com/kr/pretty v0.3.0 // indirect
@@ -40,6 +42,7 @@ require (
github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
+ golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e // indirect
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
diff --git a/go.sum b/go.sum
index 812919ec..d5b806bd 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
+github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
@@ -87,6 +89,8 @@ github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
go.kuoruan.net/v8go-polyfills v0.5.1-0.20220727011656-c74c5b408ebd h1:lMfOO39WTD+CxBPmqZvLdISrLVsEjgNfWoV4viBt15M=
go.kuoruan.net/v8go-polyfills v0.5.1-0.20220727011656-c74c5b408ebd/go.mod h1:egHzK8RIHR7dPOYzhnRsomClFTVmYCtvhTWqec4JXaY=
+golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e h1:qyrTQ++p1afMkO4DPEeLGq/3oTsdlvdH4vqZUBWzUKM=
+golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -115,6 +119,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA=
+honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw=
rogchap.com/v8go v0.7.0 h1:kgjbiO4zE5itA962ze6Hqmbs4HgZbGzmueCXsZtremg=
rogchap.com/v8go v0.7.0/go.mod h1:MxgP3pL2MW4dpme/72QRs8sgNMmM0pRc8DPhcuLWPAs=
src.techknowlogick.com/xgo v1.4.1-0.20220413212431-091a0a22b814 h1:/oIyHjKnlyQ3yFzxq7uin83l6h0sHXT7Z+9TpP9wr8s=
diff --git a/internal/cli/testcli/testcli.go b/internal/cli/testcli/testcli.go
index ceabbc6d..aab9b2b9 100644
--- a/internal/cli/testcli/testcli.go
+++ b/internal/cli/testcli/testcli.go
@@ -249,9 +249,9 @@ func checkDate(res *http.Response) error {
return err
}
// Date should be within 1 minute. In reality, it should be almost instant
- elapsed := time.Now().Sub(dt)
+ elapsed := time.Since(dt)
if elapsed > time.Minute {
- return fmt.Errorf("Date header is too old %s", elapsed)
+ return fmt.Errorf("date header is too old %s", elapsed)
}
return nil
}
diff --git a/internal/cli/toolv8/toolv8.go b/internal/cli/toolv8/toolv8.go
index 05f7658c..159aad45 100644
--- a/internal/cli/toolv8/toolv8.go
+++ b/internal/cli/toolv8/toolv8.go
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
v8 "github.com/livebud/bud/package/js/v8"
)
@@ -37,7 +36,7 @@ func (c *Command) Run(ctx context.Context) error {
}
func (c *Command) getScript() (string, error) {
- code, err := ioutil.ReadAll(c.Stdin)
+ code, err := io.ReadAll(c.Stdin)
if err != nil {
return "", err
}
diff --git a/internal/dsync/set/set.go b/internal/dsync/set/set.go
index 43403d2f..46b3ddd6 100644
--- a/internal/dsync/set/set.go
+++ b/internal/dsync/set/set.go
@@ -12,7 +12,6 @@ import (
var (
// helpful to not write everywhere struct{}{}
- keyExists = struct{}{}
nonExistent fs.DirEntry
)
diff --git a/internal/golden/golden.go b/internal/golden/golden.go
index 2556113e..56f7a0f2 100644
--- a/internal/golden/golden.go
+++ b/internal/golden/golden.go
@@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"flag"
- "io/ioutil"
"os"
"path/filepath"
"testing"
@@ -40,7 +39,7 @@ func Test(t testing.TB, actual *txtar.Archive) {
t.Helper()
filename := filepath.Join("testdata", t.Name()+".golden")
formatted := txtar.Format(actual)
- expected, err := ioutil.ReadFile(filename)
+ expected, err := os.ReadFile(filename)
if err != nil {
if len(formatted) == 0 {
return
@@ -63,7 +62,7 @@ func writeFile(name string, data []byte) error {
if err := os.MkdirAll(filepath.Dir(name), 0755); err != nil {
return err
}
- return ioutil.WriteFile(name, data, 0644)
+ return os.WriteFile(name, data, 0644)
}
// TestString diffs two strings
diff --git a/internal/is/is_internal.go b/internal/is/is_internal.go
index 67ac97b2..20436142 100644
--- a/internal/is/is_internal.go
+++ b/internal/is/is_internal.go
@@ -48,6 +48,7 @@ type I struct {
func (is *I) log(args ...interface{}) {
s := is.decorate(fmt.Sprint(args...))
+ //lint:ignore SA1006 - s can be a formatted string
fmt.Fprintf(is.writer, s)
is.fail()
}
diff --git a/internal/is/is_test.go b/internal/is/is_test.go
index 0e332d4e..f299dcd7 100644
--- a/internal/is/is_test.go
+++ b/internal/is/is_test.go
@@ -348,6 +348,7 @@ func TestTrueOk(t *testing.T) {
out := new(bytes.Buffer)
is.writer = out
is.colorful = false
+ //lint:ignore SA4000 this is a test
is.True(1 == 1)
if m.failed {
t.Fatalf(`expected no failure`)
@@ -363,11 +364,12 @@ func TestTrueMessage(t *testing.T) {
out := new(bytes.Buffer)
is.writer = out
is.colorful = false
+ //lint:ignore SA4000 this is a test
is.True(1 != 1, "expected %d and %d to be equal", 1, 1)
if !m.failed {
t.Fatalf(`expected is.True to fail`)
}
- expect := "is_test.go:366: not true: 1 != 1. expected 1 and 1 to be equal\n"
+ expect := "is_test.go:368: not true: 1 != 1. expected 1 and 1 to be equal\n"
if out.String() != expect {
t.Fatalf("expected %q, got %q", expect, out)
}
@@ -383,7 +385,7 @@ func TestInMessage(t *testing.T) {
if !m.failed {
t.Fatalf(`expected is.In to fail`)
}
- expect := "is_test.go:382: hi not in hello. hello doesn't contain hi\n"
+ expect := "is_test.go:384: hi not in hello. hello doesn't contain hi\n"
if out.String() != expect {
t.Fatalf("expected %q, got %q", expect, out)
}
@@ -399,7 +401,7 @@ func TestFail(t *testing.T) {
if !m.failed {
t.Fatalf(`expected is.Fail to fail`)
}
- expect := "is_test.go:398: failed\n"
+ expect := "is_test.go:400: failed\n"
if out.String() != expect {
t.Fatalf("expected %q, got %q", expect, out)
}
@@ -415,7 +417,7 @@ func TestFailMessage(t *testing.T) {
if !m.failed {
t.Fatalf(`expected is.Fail to fail`)
}
- expect := "is_test.go:414: failed. context from \"component\" should have exited\n"
+ expect := "is_test.go:416: failed. context from \"component\" should have exited\n"
if out.String() != expect {
t.Fatalf("expected %q, got %q", expect, out)
}
diff --git a/internal/snapshot/snapshot.go b/internal/snapshot/snapshot.go
index 363bebff..a027106f 100644
--- a/internal/snapshot/snapshot.go
+++ b/internal/snapshot/snapshot.go
@@ -1,15 +1,12 @@
package snapshot
import (
- "encoding/base64"
"io/fs"
"os"
"path/filepath"
"github.com/livebud/bud/internal/dirhash"
"github.com/livebud/bud/internal/targz"
-
- "github.com/cespare/xxhash"
)
func cachePath(key string) (string, error) {
@@ -20,12 +17,6 @@ func cachePath(key string) (string, error) {
return filepath.Join(dir, key+".tar.gz"), nil
}
-func hash(input string) string {
- hash := xxhash.New()
- hash.Write([]byte(input))
- return base64.RawURLEncoding.EncodeToString(hash.Sum(nil))
-}
-
// Hash a filesystem
func Hash(fsys fs.FS) (string, error) {
return dirhash.Hash(fsys)
diff --git a/internal/testdir/testdir.go b/internal/testdir/testdir.go
index 80bcdcc3..8edfb8f2 100644
--- a/internal/testdir/testdir.go
+++ b/internal/testdir/testdir.go
@@ -62,33 +62,6 @@ type Dir struct {
NodeModules map[string]string // name[version]
}
-func merge(mapfs fstest.MapFS, fsys fs.FS, base ...string) error {
- basePath := path.Join(base...)
- return fs.WalkDir(fsys, ".", func(filePath string, de fs.DirEntry, err error) error {
- if err != nil {
- return err
- }
- fi, err := de.Info()
- if err != nil {
- return err
- }
- fullPath := path.Join(basePath, filePath)
- mapfs[fullPath] = &fstest.MapFile{
- ModTime: fi.ModTime(),
- Mode: fi.Mode(),
- }
- if de.IsDir() {
- return nil
- }
- data, err := fs.ReadFile(fsys, filePath)
- if err != nil {
- return err
- }
- mapfs[fullPath].Data = data
- return nil
- })
-}
-
func (d *Dir) mapfs() (fstest.MapFS, error) {
mapfs := fstest.MapFS{}
// Loop over files
diff --git a/internal/testdir/testdir_test.go b/internal/testdir/testdir_test.go
index dbc76b62..58c01c73 100644
--- a/internal/testdir/testdir_test.go
+++ b/internal/testdir/testdir_test.go
@@ -2,7 +2,6 @@ package testdir_test
import (
"context"
- "io/ioutil"
"os"
"path/filepath"
"testing"
@@ -92,18 +91,18 @@ func TestOverwrite(t *testing.T) {
is.NoErr(td.Write(ctx))
is.NoErr(td.Exists("controller/controller.go"))
is.NoErr(td.Exists("view/index.svelte"))
- controller1, err := ioutil.ReadFile(td.Path("controller/controller.go"))
+ controller1, err := os.ReadFile(td.Path("controller/controller.go"))
is.NoErr(err)
- view1, err := ioutil.ReadFile(td.Path("view/index.svelte"))
+ view1, err := os.ReadFile(td.Path("view/index.svelte"))
is.NoErr(err)
is.Equal(string(view1), `
hello
`)
td.Files["view/index.svelte"] = `hi
`
is.NoErr(td.Write(ctx))
is.NoErr(td.Exists("controller/controller.go"))
is.NoErr(td.Exists("view/index.svelte"))
- controller2, err := ioutil.ReadFile(td.Path("controller/controller.go"))
+ controller2, err := os.ReadFile(td.Path("controller/controller.go"))
is.NoErr(err)
- view2, err := ioutil.ReadFile(td.Path("view/index.svelte"))
+ view2, err := os.ReadFile(td.Path("view/index.svelte"))
is.NoErr(err)
is.Equal(string(controller1), string(controller2))
is.Equal(string(view2), `hi
`)
diff --git a/package/budfs/genfs/genfs_test.go b/package/budfs/genfs/genfs_test.go
index 304f8d32..de6061a1 100644
--- a/package/budfs/genfs/genfs_test.go
+++ b/package/budfs/genfs/genfs_test.go
@@ -2,8 +2,8 @@ package genfs_test
import (
"errors"
+ "io"
"io/fs"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -595,7 +595,7 @@ func TestHTTP(t *testing.T) {
handler(w, r)
response := w.Result()
- body, err := ioutil.ReadAll(response.Body)
+ body, err := io.ReadAll(response.Body)
is.NoErr(err)
is.Equal(string(body), `bud/view/_index.svelte's data`)
is.Equal(response.StatusCode, 200)
diff --git a/package/budfs/treefs/treefs.go b/package/budfs/treefs/treefs.go
index 2f1787d2..1d591d8a 100644
--- a/package/budfs/treefs/treefs.go
+++ b/package/budfs/treefs/treefs.go
@@ -172,7 +172,6 @@ func (n *Node) print(tp treeprint.Tree) {
cp := tp.AddBranch(formatNode(child))
child.print(cp)
}
- return
}
func (n *Node) Find(path string) (node *Node, found bool) {
diff --git a/package/commander/subcommand.go b/package/commander/subcommand.go
index c96a9f95..b65a199a 100644
--- a/package/commander/subcommand.go
+++ b/package/commander/subcommand.go
@@ -5,12 +5,12 @@ import (
"errors"
"flag"
"fmt"
- "io/ioutil"
+ "io"
)
func newSubcommand(config *config, name, usage string) *Subcommand {
fset := flag.NewFlagSet(name, flag.ContinueOnError)
- fset.SetOutput(ioutil.Discard)
+ fset.SetOutput(io.Discard)
return &Subcommand{
config: config,
fset: fset,
diff --git a/package/di/di_test.go b/package/di/di_test.go
index 32f924a3..bb2723ed 100644
--- a/package/di/di_test.go
+++ b/package/di/di_test.go
@@ -3,7 +3,6 @@ package di_test
import (
"bytes"
"context"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -81,7 +80,7 @@ func runTest(t testing.TB, test Test) {
err = os.MkdirAll(targetDir, 0755)
is.NoErr(err)
outPath := filepath.Join(targetDir, "di.go")
- err = ioutil.WriteFile(outPath, []byte(code), 0644)
+ err = os.WriteFile(outPath, []byte(code), 0644)
is.NoErr(err)
stdout, err := goRun(ctx, modCache.Directory(), appDir)
is.NoErr(err)
diff --git a/package/di/finder.go b/package/di/finder.go
index bca71feb..31e72d6d 100644
--- a/package/di/finder.go
+++ b/package/di/finder.go
@@ -76,5 +76,5 @@ func (i *Injector) Find(currModule *gomod.Module, dep Dependency) (Declaration,
return decl, nil
}
// TODO: add breadcrumbs to help with finding the root of this error
- return nil, fmt.Errorf("di: unclear how to provide %s.", dep.ID())
+ return nil, fmt.Errorf("di: unclear how to provide %s", dep.ID())
}
diff --git a/package/gomod/file.go b/package/gomod/file.go
index b4ed1650..43331549 100644
--- a/package/gomod/file.go
+++ b/package/gomod/file.go
@@ -42,9 +42,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
// Return a list of replaces
func (f *File) Replaces() (reps []*Replace) {
reps = make([]*Replace, len(f.file.Replace))
- for i, rep := range f.file.Replace {
- reps[i] = rep
- }
+ copy(reps, f.file.Replace)
// Consistent ordering regardless of modfile formatting
sort.Slice(reps, func(i, j int) bool {
return reps[i].Old.Path < reps[j].Old.Path
@@ -55,9 +53,7 @@ func (f *File) Replaces() (reps []*Replace) {
// Return a list of requires
func (f *File) Requires() (reqs []*Require) {
reqs = make([]*Require, len(f.file.Require))
- for i, req := range f.file.Require {
- reqs[i] = req
- }
+ copy(reqs, f.file.Require)
// Consistent ordering regardless of modfile formatting
sort.Slice(reqs, func(i, j int) bool {
switch {
diff --git a/package/hot/client.go b/package/hot/client.go
index db5c7cee..1330e631 100644
--- a/package/hot/client.go
+++ b/package/hot/client.go
@@ -93,6 +93,8 @@ func (s *Stream) loop() {
}
func (s *Stream) Next(ctx context.Context) (*Event, error) {
+ ticker := time.NewTicker(time.Second)
+ defer ticker.Stop()
for {
select {
case <-ctx.Done():
@@ -101,7 +103,7 @@ func (s *Stream) Next(ctx context.Context) (*Event, error) {
return evt, nil
case err := <-s.errorCh:
return nil, err
- case <-time.Tick(time.Second):
+ case <-ticker.C:
s.log.Debug("hot: client waiting for next event")
}
}
@@ -115,10 +117,10 @@ func (s *Stream) close() (err error) {
err = errs.Join(err, s.res.Body.Close())
close(s.closeCh)
// Drain event channel
- if err := <-s.errorCh; err != nil {
+ if e := <-s.errorCh; e != nil {
// Closed errors are expected since we closed the body
- if !errors.Is(err, net.ErrClosed) {
- err = errs.Join(err, err)
+ if !isExpectedCloseError(e) {
+ err = errs.Join(err, e)
}
}
close(s.errorCh)
@@ -126,6 +128,19 @@ func (s *Stream) close() (err error) {
return err
}
+// isExpectedCloseError returns true if the close error is expected
+func isExpectedCloseError(err error) bool {
+ if errors.Is(err, net.ErrClosed) {
+ return true
+ }
+ // Unfortunately this error is not exported
+ // https://github.com/golang/go/blob/f4274e64aac99aaa9af05988f2f8c36c47554889/src/net/http/transport.go#L2636
+ if err.Error() == "http: read on closed response body" {
+ return true
+ }
+ return false
+}
+
func parseLine(line []byte) (key []byte, value []byte) {
key = line
colon := bytes.IndexByte(line, ':')
diff --git a/package/modcache/modcache.go b/package/modcache/modcache.go
index 62389fce..a1c09377 100644
--- a/package/modcache/modcache.go
+++ b/package/modcache/modcache.go
@@ -1,27 +1,15 @@
package modcache
import (
- "archive/zip"
- "bytes"
"errors"
"fmt"
"go/build"
- "io"
- "io/fs"
- "io/ioutil"
"os"
"path/filepath"
"strings"
- "testing/fstest"
- "time"
- "golang.org/x/sync/errgroup"
-
- "golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
- "golang.org/x/mod/sumdb/dirhash"
- modzip "golang.org/x/mod/zip"
)
// Default loads a module cache from the default location
@@ -43,28 +31,6 @@ func (c *Cache) Directory(subpaths ...string) string {
return filepath.Join(append([]string{c.cacheDir}, subpaths...)...)
}
-// type Files = map[string]string
-// type Modules = map[string]Files
-
-// Write modules directly into the cache directory in an acceptable format so
-// that Go thinks these files are cached and doesn't try reading them from the
-// network.
-//
-// This implementation is the minimal format needed to get `go mod tidy` to
-// think the files are cached. This shouldn't be used outside of testing
-// contexts.
-//
-// Based on: https://github.com/golang/go/blob/master/src/cmd/go/internal/modfetch/fetch.go
-// func WriteFS(modules Modules) (fs.FS, error) {
-// mapfs := fstest.MapFS{}
-// for pv, files := range modules {
-// if err := writeModuleFS(mapfs, pv, files); err != nil {
-// return nil, err
-// }
-// }
-// return mapfs, nil
-// }
-
// SplitPathVersion splits a path@version into path & version
func SplitPathVersion(pathVersion string) (path, version string, err error) {
parts := strings.SplitN(pathVersion, "@", 2)
@@ -81,246 +47,6 @@ func SplitPathVersion(pathVersion string) (path, version string, err error) {
return path, version, nil
}
-var zeroTime time.Time
-
-func writeModuleFS(mapfs fstest.MapFS, pv string, files map[string]string) error {
- modulePath, moduleVersion, err := SplitPathVersion(pv)
- if err != nil {
- return err
- }
- goMod, ok := files["go.mod"]
- if !ok {
- goMod = `module ` + modulePath + "\n"
- // Write go.mod back into module to make cached files a valid go.mod
- files["go.mod"] = goMod
- }
- if modfile.ModulePath([]byte(goMod)) != modulePath {
- return fmt.Errorf("modcache: %q does not match module path in go.mod", modulePath)
- }
- downloadDir, err := downloadDir(modulePath)
- if err != nil {
- return err
- }
- escapedVersion, err := module.EscapeVersion(moduleVersion)
- if err != nil {
- return err
- }
- extlessPath := filepath.Join(downloadDir, escapedVersion)
- zipData := new(bytes.Buffer)
- module := module.Version{Path: modulePath, Version: moduleVersion}
- var zipFiles []modzip.File
- for path, data := range files {
- zipFiles = append(zipFiles, &zipEntry{path, data})
- }
- if err := modzip.Create(zipData, module, zipFiles); err != nil {
- return err
- }
- hash, err := hashZip(bytes.NewReader(zipData.Bytes()), int64(zipData.Len()), dirhash.DefaultHash)
- if err != nil {
- return err
- }
- // Write the zip hash
- mapfs[extlessPath+".ziphash"] = &fstest.MapFile{
- Data: []byte(hash),
- ModTime: zeroTime,
- Mode: 0644,
- }
- // Write the info file
- // We use zero-time because it doesn't seem to affect module download
- // functionality and allows us to have consistent hashes for downloaded
- // modules
- infoFile := fmt.Sprintf(`{"Version":%q,"Time":%q}`, moduleVersion, zeroTime.Format(time.RFC3339))
- mapfs[extlessPath+".info"] = &fstest.MapFile{
- Data: []byte(infoFile),
- ModTime: zeroTime,
- Mode: 0644,
- }
- // Write the .mod
- mapfs[extlessPath+".mod"] = &fstest.MapFile{
- Data: []byte(goMod),
- ModTime: zeroTime,
- Mode: 0644,
- }
- // Write the zip
- mapfs[extlessPath+".zip"] = &fstest.MapFile{
- Data: zipData.Bytes(),
- ModTime: zeroTime,
- Mode: 0644,
- }
- // Write all the files
- for path, data := range files {
- mapfs[filepath.Join(pv, path)] = &fstest.MapFile{
- Data: []byte(data),
- ModTime: zeroTime,
- Mode: 0644,
- }
- }
- return nil
-}
-
-// HashZip returns the hash of the file content in the named zip file.
-// Only the file names and their contents are included in the hash:
-// the exact zip file format encoding, compression method,
-// per-file modification times, and other metadata are ignored.
-func hashZip(r io.ReaderAt, size int64, hash dirhash.Hash) (string, error) {
- z, err := zip.NewReader(r, size)
- if err != nil {
- return "", err
- }
- var files []string
- zfiles := make(map[string]*zip.File)
- for _, file := range z.File {
- files = append(files, file.Name)
- zfiles[file.Name] = file
- }
- zipOpen := func(name string) (io.ReadCloser, error) {
- f := zfiles[name]
- if f == nil {
- return nil, fmt.Errorf("file %q not found in zip", name) // should never happen
- }
- return f.Open()
- }
- return hash(files, zipOpen)
-}
-
-// Write modules directly into the cache directory in an acceptable format so
-// that Go thinks these files are cached and doesn't try reading them from the
-// network.
-//
-// This implementation is the minimal format needed to get `go mod tidy` to
-// think the files are cached. This shouldn't be used outside of testing
-// contexts.
-//
-// Based on: https://github.com/golang/go/blob/master/src/cmd/go/internal/modfetch/fetch.go
-// func (c *Cache) Write(modules Modules) error {
-// eg := new(errgroup.Group)
-// for modulePathVersion, files := range modules {
-// modulePathVersion, files := modulePathVersion, files
-// eg.Go(func() error { return c.writeModule(modulePathVersion, files) })
-// }
-// return eg.Wait()
-// }
-
-func (c *Cache) writeModule(modulePathVersion string, files map[string]string) error {
- moduleParts := strings.SplitN(modulePathVersion, "@", 2)
- if len(moduleParts) != 2 {
- return fmt.Errorf("modcache: invalid module key")
- }
- modulePath, moduleVersion := moduleParts[0], moduleParts[1]
- goMod, ok := files["go.mod"]
- if !ok {
- goMod = `module ` + modulePath + "\n"
- // Write go.mod back into module to make cached files a valid go.mod
- files["go.mod"] = goMod
- }
- if modulePath == "" {
- return fmt.Errorf("modcache: missing module path in go.mod")
- }
- if modfile.ModulePath([]byte(goMod)) != modulePath {
- return fmt.Errorf("modcache: %q does not match module path in go.mod", modulePath)
- }
- downloadDir, err := c.downloadDir(modulePath)
- if err != nil {
- return err
- }
- if err := os.MkdirAll(downloadDir, 0755); err != nil {
- return err
- }
- escapedVersion, err := module.EscapeVersion(moduleVersion)
- if err != nil {
- return err
- }
- extlessPath := filepath.Join(downloadDir, escapedVersion)
- zipPath := extlessPath + ".zip"
- zipFile, err := os.Create(zipPath)
- if err != nil {
- return err
- }
- defer zipFile.Close()
- module := module.Version{Path: modulePath, Version: moduleVersion}
- var zipFiles []modzip.File
- for path, data := range files {
- zipFiles = append(zipFiles, &zipEntry{path, data})
- }
- if err := modzip.Create(zipFile, module, zipFiles); err != nil {
- return err
- }
- if err := zipFile.Close(); err != nil {
- return err
- }
- hash, err := dirhash.HashZip(zipPath, dirhash.DefaultHash)
- if err != nil {
- return err
- }
- if err := ioutil.WriteFile(extlessPath+".ziphash", []byte(hash), 0644); err != nil {
- return err
- }
- if err := ioutil.WriteFile(extlessPath+".mod", []byte(goMod), 0644); err != nil {
- return err
- }
- moduleDir, err := c.getModuleDirectory(modulePath, moduleVersion)
- if err != nil {
- return err
- }
- eg := new(errgroup.Group)
- for path, data := range files {
- path := filepath.Join(moduleDir, path)
- dir := filepath.Dir(path)
- data := data
- eg.Go(func() error {
- if err := os.MkdirAll(dir, 0755); err != nil {
- return err
- }
- return ioutil.WriteFile(path, []byte(data), 0644)
- })
- }
- return eg.Wait()
-}
-
-type zipEntry struct {
- path, data string
-}
-
-func (z *zipEntry) Path() string {
- return z.path
-}
-
-// Lstat returns information about the file. If the file is a symbolic link,
-func (z *zipEntry) Lstat() (os.FileInfo, error) {
- return &fileInfo{
- name: filepath.Base(z.path),
- data: []byte(z.data),
- size: int64(len(z.data)),
- mode: fs.FileMode(0644),
- modTime: zeroTime,
- }, nil
-}
-
-// A fileInfo implements fs.FileInfo and fs.DirEntry for a given map file.
-type fileInfo struct {
- name string
- data []byte
- size int64
- mode fs.FileMode
- modTime time.Time
- sys interface{}
-}
-
-func (i *fileInfo) Name() string { return i.name }
-func (i *fileInfo) Mode() fs.FileMode { return i.mode }
-func (i *fileInfo) Type() fs.FileMode { return i.mode.Type() }
-func (i *fileInfo) ModTime() time.Time { return i.modTime }
-func (i *fileInfo) IsDir() bool { return i.mode&fs.ModeDir != 0 }
-func (i *fileInfo) Sys() interface{} { return i.sys }
-func (i *fileInfo) Info() (fs.FileInfo, error) { return i, nil }
-func (i *fileInfo) Size() int64 { return i.size }
-
-// Open provides access to the data within a regular file. Open may return
-// an error if called on a directory or symbolic link.
-func (z *zipEntry) Open() (io.ReadCloser, error) {
- return ioutil.NopCloser(bytes.NewBufferString(z.data)), nil
-}
-
// ResolveDirectory returns the directory to which m should have been
// downloaded. An error will be returned if the module path or version cannot be
// escaped. An error satisfying errors.Is(err, os.ErrNotExist) will be returned
@@ -341,35 +67,6 @@ func (c *Cache) ResolveDirectory(modulePath, version string) (string, error) {
return dir, nil
}
-// InCache returns true if the module with this version is in the cache,
-// otherwise it returns false.
-// func (c *Cache) InCache(modulePath, version string) (bool, error) {
-// if _, err := c.ResolveDirectory(modulePath, version); err != nil {
-// if !errors.Is(err, fs.ErrNotExist) {
-// return false, err
-// }
-// return false, nil
-// }
-// return true, nil
-// }
-
-// Import from a directory
-// func (c *Cache) Import(from string) error {
-// return cp.Copy(from, c.cacheDir, cp.Options{})
-// }
-
-// // Export to a directory
-// func (c *Cache) Export(to string) error {
-// return cp.Copy(c.cacheDir, to, cp.Options{
-// Skip: func(src string) (bool, error) {
-// if src == filepath.Join(c.cacheDir, "cache", "vcs") {
-// return true, nil
-// }
-// return false, nil
-// },
-// })
-// }
-
// Cache for faster subsequent requests
var modDir string
@@ -421,21 +118,3 @@ func (e *downloadDirPartialError) Error() string { return fmt.Sprintf("%s: %v",
// Is fn
func (e *downloadDirPartialError) Is(err error) bool { return err == os.ErrNotExist }
-
-// partialDownloadPath returns the partial download path
-func (c *Cache) downloadDir(modulePath string) (string, error) {
- dir, err := downloadDir(modulePath)
- if err != nil {
- return "", err
- }
- return filepath.Join(c.cacheDir, dir), nil
-}
-
-// partialDownloadPath returns the partial download path
-func downloadDir(modulePath string) (string, error) {
- enc, err := module.EscapePath(modulePath)
- if err != nil {
- return "", err
- }
- return filepath.Join("cache/download", enc, "/@v"), nil
-}
diff --git a/package/remotefs/client.go b/package/remotefs/client.go
index 4f34afa6..09441b43 100644
--- a/package/remotefs/client.go
+++ b/package/remotefs/client.go
@@ -5,7 +5,6 @@ import (
"encoding/gob"
"io/fs"
"strings"
- "time"
"github.com/keegancsmith/rpc"
"github.com/livebud/bud/internal/virtual"
@@ -18,9 +17,6 @@ func init() {
gob.Register(&virtual.DirEntry{})
}
-// client timeout defaults to 10 seconds
-const clientTimeout = 10 * time.Second
-
func Dial(ctx context.Context, addr string) (*Client, error) {
conn, err := socket.Dial(ctx, addr)
if err != nil {
diff --git a/package/router/lex/lex.go b/package/router/lex/lex.go
index ffb31825..fcf4560f 100644
--- a/package/router/lex/lex.go
+++ b/package/router/lex/lex.go
@@ -81,11 +81,6 @@ func (l *lexer) backup() {
l.pos -= l.width
}
-// ignore skips over the pending input before this point.
-func (l *lexer) ignore() {
- l.start = l.pos
-}
-
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
value := fmt.Sprintf(format, args...)
l.tokenCh <- Token{
@@ -221,16 +216,6 @@ func lexSlotRest(l *lexer) stateFn {
}
}
-// The character after the slot can't be a character that could be in the slot
-func lexAfterSlot(l *lexer) stateFn {
- switch r := l.peek(); r {
- case '.', '/', end:
- return lexText
- default:
- return l.errorf(`route %q: invalid value after slot %q`, l.input, string(r))
- }
-}
-
func lexQuestion(l *lexer) stateFn {
// Expect End after
switch r := l.step(); r {
diff --git a/package/router/radix/tree_test.go b/package/router/radix/tree_test.go
index 1cf4408a..5b220814 100644
--- a/package/router/radix/tree_test.go
+++ b/package/router/radix/tree_test.go
@@ -1,7 +1,7 @@
package radix_test
import (
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"sort"
@@ -67,7 +67,7 @@ func ok(t testing.TB, test *test) {
rec := httptest.NewRecorder()
match.Handler.ServeHTTP(rec, req)
res := rec.Result()
- body, err := ioutil.ReadAll(res.Body)
+ body, err := io.ReadAll(res.Body)
is.NoErr(err)
is.Equal(request.route, string(body))
// Test slots
diff --git a/package/router/router_test.go b/package/router/router_test.go
index 06f2cb27..5c8b823a 100644
--- a/package/router/router_test.go
+++ b/package/router/router_test.go
@@ -2,7 +2,7 @@ package router_test
import (
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"testing"
@@ -82,7 +82,7 @@ func ok(t testing.TB, test *test) {
fmt.Println("location", url.Path)
is.Equal(request.location, url.Path)
}
- body, err := ioutil.ReadAll(res.Body)
+ body, err := io.ReadAll(res.Body)
is.NoErr(err)
is.Equal(request.body, string(body))
}
@@ -205,7 +205,7 @@ func TestPut(t *testing.T) {
router.ServeHTTP(rec, req)
res := rec.Result()
is.Equal(200, res.StatusCode)
- body, err := ioutil.ReadAll(res.Body)
+ body, err := io.ReadAll(res.Body)
is.NoErr(err)
is.Equal("id=10", string(body))
}
@@ -219,7 +219,7 @@ func TestAdd(t *testing.T) {
router.ServeHTTP(rec, req)
res := rec.Result()
is.Equal(200, res.StatusCode)
- body, err := ioutil.ReadAll(res.Body)
+ body, err := io.ReadAll(res.Body)
is.NoErr(err)
is.Equal("id=10", string(body))
}
diff --git a/package/socket/socket_test.go b/package/socket/socket_test.go
index 275f1dac..9787a640 100644
--- a/package/socket/socket_test.go
+++ b/package/socket/socket_test.go
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -34,7 +33,7 @@ func TestLoadTCP(t *testing.T) {
}
res, err := client.Get("http://" + listener.Addr().String() + "/hello")
is.NoErr(err)
- body, err := ioutil.ReadAll(res.Body)
+ body, err := io.ReadAll(res.Body)
is.NoErr(err)
is.Equal(string(body), "/hello")
server.Shutdown(context.Background())
@@ -58,7 +57,7 @@ func TestLoadNumberOnly(t *testing.T) {
}
res, err := client.Get("http://" + listener.Addr().String() + "/hello")
is.NoErr(err)
- body, err := ioutil.ReadAll(res.Body)
+ body, err := io.ReadAll(res.Body)
is.NoErr(err)
is.Equal(string(body), "/hello")
server.Shutdown(context.Background())
diff --git a/package/vfs/singleflight.go b/package/vfs/singleflight.go
index 96e06a59..6fab742a 100644
--- a/package/vfs/singleflight.go
+++ b/package/vfs/singleflight.go
@@ -3,7 +3,6 @@ package vfs
import (
"io"
"io/fs"
- "io/ioutil"
"golang.org/x/sync/singleflight"
)
@@ -42,7 +41,7 @@ func (s *singleFlight) Open(name string) (fs.File, error) {
}
return file, nil
}
- data, err := ioutil.ReadAll(file)
+ data, err := io.ReadAll(file)
if err != nil {
return nil, err
}
diff --git a/package/watcher/watcher.go b/package/watcher/watcher.go
index ec4b5124..b618ab15 100644
--- a/package/watcher/watcher.go
+++ b/package/watcher/watcher.go
@@ -18,6 +18,9 @@ import (
"github.com/livebud/bud/internal/gitignore"
)
+// Stop informs the watcher to stop.
+//
+//lint:ignore ST1012 stop is not an error, it's part of the control flow.
var Stop = errors.New("stop watching")
// Arbitrarily picked after some manual testing. OSX is pretty fast, but Ubuntu
diff --git a/tools.go b/tools.go
index 8487d311..8c71c0e4 100644
--- a/tools.go
+++ b/tools.go
@@ -9,5 +9,6 @@ import (
_ "github.com/evanw/esbuild/cmd/esbuild"
_ "github.com/livebud/bud-test-plugin"
_ "github.com/pointlander/peg"
+ _ "honnef.co/go/tools/cmd/staticcheck"
_ "src.techknowlogick.com/xgo"
)