diff options
Diffstat (limited to '')
-rw-r--r-- | .github/workflows/tests.yml | 55 | ||||
-rw-r--r-- | .golangci.yml | 19 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | build.go | 2 | ||||
-rw-r--r-- | changelog/unreleased/pull-322 | 9 | ||||
-rw-r--r-- | cmd/rest-server/listener_unix_test.go | 5 | ||||
-rw-r--r-- | cmd/rest-server/main.go | 16 | ||||
-rw-r--r-- | cmd/rest-server/main_test.go | 12 | ||||
-rw-r--r-- | go.mod | 27 | ||||
-rw-r--r-- | go.sum | 61 | ||||
-rw-r--r-- | handlers.go | 3 | ||||
-rw-r--r-- | handlers_test.go | 21 | ||||
-rw-r--r-- | htpasswd_test.go | 3 | ||||
-rw-r--r-- | quota/quota.go | 2 | ||||
-rw-r--r-- | repo/repo.go | 37 |
15 files changed, 162 insertions, 112 deletions
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7baec42..00e6c99 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,9 +7,13 @@ on: # run tests for all pull requests pull_request: + merge_group: + +permissions: + contents: read env: - latest_go: "1.21.x" + latest_go: "1.23.x" GO111MODULE: on jobs: @@ -17,10 +21,8 @@ jobs: strategy: matrix: go: - - 1.18.x - - 1.19.x - - 1.20.x - - 1.21.x + - 1.23.x + - 1.22.x runs-on: ubuntu-latest name: Go ${{ matrix.go }} @@ -28,25 +30,21 @@ jobs: GOPROXY: https://proxy.golang.org steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Set up Go ${{ matrix.go }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.go }} - - name: Check out code - uses: actions/checkout@v4 - - - name: Build - run: | - go build ./cmd/rest-server - - name: Build with build.go run: | go run build.go --goos linux go run build.go --goos windows go run build.go --goos darwin - - name: Run tests + - name: Run local Tests run: | go test ./... @@ -61,23 +59,25 @@ jobs: lint: name: lint runs-on: ubuntu-latest + permissions: + contents: read + # allow annotating code in the PR + checks: write steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Set up Go ${{ env.latest_go }} uses: actions/setup-go@v5 with: go-version: ${{ env.latest_go }} - - name: Check out code - uses: actions/checkout@v4 - - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.51 - # Optional: show only new issues if it's a pull request. The default value is `false`. - only-new-issues: true - args: --verbose --timeout 10m + version: v1.63.4 + args: --verbose --timeout 5m # only run golangci-lint for pull requests, otherwise ALL hints get # reported. We need to slowly address all issues until we can enable @@ -89,3 +89,18 @@ jobs: echo "check if go.mod and go.sum are up to date" go mod tidy git diff --exit-code go.mod go.sum + + analyze: + name: Analyze results + needs: [test, lint] + if: always() + + permissions: # no need to access code + contents: none + + runs-on: ubuntu-latest + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe + with: + jobs: ${{ toJSON(needs) }} diff --git a/.golangci.yml b/.golangci.yml index 44dfcdc..b44c2c1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,13 +10,10 @@ linters: # make sure all errors returned by functions are handled - errcheck - # find unused code - - deadcode - # show how code can be simplified - gosimple - # # make sure code is formatted + # make sure code is formatted - gofmt # examine code and report suspicious constructs, such as Printf calls whose @@ -35,15 +32,14 @@ linters: # find unused variables, functions, structs, types, etc. - unused - # find unused struct fields - - structcheck - - # find unused global variables - - varcheck - # parse and typecheck code - typecheck + # ensure that http response bodies are closed + - bodyclose + + - importas + issues: # don't use the default exclude rules, this hides (among others) ignored # errors from Close() calls @@ -55,3 +51,6 @@ issues: - exported (function|method|var|type|const) .* should have comment or be unexported # revive: ignore constants in all caps - don't use ALL_CAPS in Go names; use CamelCase + # revive: lots of packages don't have such a comment + - "package-comments: should have a package comment" + - "redefines-builtin-id:" @@ -11,7 +11,7 @@ Rest Server is a high performance HTTP server that implements restic's [REST bac ## Requirements -Rest Server requires Go 1.18 or higher to build. The only tested compiler is the official Go compiler. Building server with `gccgo` may work, but is not supported. +Rest Server requires Go 1.22 or higher to build. The only tested compiler is the official Go compiler. The required version of restic backup client to use with `rest-server` is [v0.7.1](https://github.com/restic/restic/releases/tag/v0.7.1) or higher. @@ -58,7 +58,7 @@ var config = Config{ Namespace: "github.com/restic/rest-server", // subdir of GOPATH, e.g. "github.com/foo/bar" Main: "github.com/restic/rest-server/cmd/rest-server", // package name for the main package Tests: []string{"./..."}, // tests to run - MinVersion: GoVersion{Major: 1, Minor: 15, Patch: 0}, // minimum Go version supported + MinVersion: GoVersion{Major: 1, Minor: 22, Patch: 0}, // minimum Go version supported } // Config configures the build. diff --git a/changelog/unreleased/pull-322 b/changelog/unreleased/pull-322 new file mode 100644 index 0000000..24bc274 --- /dev/null +++ b/changelog/unreleased/pull-322 @@ -0,0 +1,9 @@ +Change: Update dependencies and require Go 1.22 or newer + +We have updated all dependencies. Since some libraries require newer Go standard +library features, support for Go 1.18 to 1.21 has been dropped, which means +that rest-server now requires at least Go 1.22 to build. + +This also disables support for TLS versions older than TLS 1.2. + +https://github.com/restic/rest-server/pull/322 diff --git a/cmd/rest-server/listener_unix_test.go b/cmd/rest-server/listener_unix_test.go index a4f32f4..2143135 100644 --- a/cmd/rest-server/listener_unix_test.go +++ b/cmd/rest-server/listener_unix_test.go @@ -61,7 +61,10 @@ func TestUnixSocket(t *testing.T) { if err != nil { return err } - resp.Body.Close() + err = resp.Body.Close() + if err != nil { + return err + } if resp.StatusCode != test.StatusCode { return fmt.Errorf("expected %d from server, instead got %d (path %s)", test.StatusCode, resp.StatusCode, test.Path) } diff --git a/cmd/rest-server/main.go b/cmd/rest-server/main.go index 0bdd1eb..aa921c9 100644 --- a/cmd/rest-server/main.go +++ b/cmd/rest-server/main.go @@ -22,7 +22,7 @@ import ( type restServerApp struct { CmdRoot *cobra.Command Server restserver.Server - CpuProfile string + CPUProfile string listenerAddressMu sync.Mutex listenerAddress net.Addr // set after startup @@ -36,7 +36,7 @@ func newRestServerApp() *restServerApp { Short: "Run a REST server for use with restic", SilenceErrors: true, SilenceUsage: true, - Args: func(cmd *cobra.Command, args []string) error { + Args: func(_ *cobra.Command, args []string) error { if len(args) != 0 { return fmt.Errorf("rest-server expects no arguments - unknown argument: %s", args[0]) } @@ -52,7 +52,7 @@ func newRestServerApp() *restServerApp { rv.CmdRoot.RunE = rv.runRoot flags := rv.CmdRoot.Flags() - flags.StringVar(&rv.CpuProfile, "cpu-profile", rv.CpuProfile, "write CPU profile to file") + flags.StringVar(&rv.CPUProfile, "cpu-profile", rv.CPUProfile, "write CPU profile to file") flags.BoolVar(&rv.Server.Debug, "debug", rv.Server.Debug, "output debug messages") flags.StringVar(&rv.Server.Listen, "listen", rv.Server.Listen, "listen address") flags.StringVar(&rv.Server.Log, "log", rv.Server.Log, "write HTTP requests in the combined log format to the specified `filename` (use \"-\" for logging to stdout)") @@ -103,17 +103,19 @@ func (app *restServerApp) ListenerAddress() net.Addr { return app.listenerAddress } -func (app *restServerApp) runRoot(cmd *cobra.Command, args []string) error { +func (app *restServerApp) runRoot(_ *cobra.Command, _ []string) error { log.SetFlags(0) log.Printf("Data directory: %s", app.Server.Path) - if app.CpuProfile != "" { - f, err := os.Create(app.CpuProfile) + if app.CPUProfile != "" { + f, err := os.Create(app.CPUProfile) if err != nil { return err } - defer f.Close() + defer func() { + _ = f.Close() + }() if err := pprof.StartCPUProfile(f); err != nil { return err diff --git a/cmd/rest-server/main_test.go b/cmd/rest-server/main_test.go index 7366981..1171530 100644 --- a/cmd/rest-server/main_test.go +++ b/cmd/rest-server/main_test.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" "net/http" "net/url" "os" @@ -94,7 +93,7 @@ func TestTLSSettings(t *testing.T) { } func TestGetHandler(t *testing.T) { - dir, err := ioutil.TempDir("", "rest-server-test") + dir, err := os.MkdirTemp("", "rest-server-test") if err != nil { t.Fatal(err) } @@ -120,7 +119,7 @@ func TestGetHandler(t *testing.T) { } // With NoAuth = false and custom .htpasswd - htpFile, err := ioutil.TempFile(dir, "custom") + htpFile, err := os.CreateTemp(dir, "custom") if err != nil { t.Fatal(err) } @@ -137,7 +136,7 @@ func TestGetHandler(t *testing.T) { // Create .htpasswd htpasswd := filepath.Join(dir, ".htpasswd") - err = ioutil.WriteFile(htpasswd, []byte(""), 0644) + err = os.WriteFile(htpasswd, []byte(""), 0644) if err != nil { t.Fatal(err) } @@ -262,7 +261,10 @@ func TestHttpListen(t *testing.T) { if err != nil { return err } - resp.Body.Close() + err = resp.Body.Close() + if err != nil { + return err + } if resp.StatusCode != test.StatusCode { return fmt.Errorf("expected %d from server, instead got %d (path %s)", test.StatusCode, resp.StatusCode, test.Path) } @@ -1,28 +1,29 @@ module github.com/restic/rest-server -go 1.18 +go 1.22 require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/gorilla/handlers v1.5.2 github.com/minio/sha256-simd v1.0.1 github.com/miolini/datacounter v1.0.3 - github.com/prometheus/client_golang v1.18.0 + github.com/prometheus/client_golang v1.20.5 github.com/spf13/cobra v1.8.1 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.32.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/sys v0.25.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.62.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/spf13/pflag v1.0.6 // indirect + golang.org/x/sys v0.30.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect ) @@ -1,46 +1,57 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= +github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/miolini/datacounter v1.0.3 h1:tanOZPVblGXQl7/bSZWoEM8l4KK83q24qwQLMrO/HOA= github.com/miolini/datacounter v1.0.3/go.mod h1:C45dc2hBumHjDpEU64IqPwR6TDyPVpzOqqRTN7zmBUA= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +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/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handlers.go b/handlers.go index 8163ccf..1bccc60 100644 --- a/handlers.go +++ b/handlers.go @@ -158,7 +158,8 @@ func join(base string, names ...string) (string, error) { // splitURLPath splits the URL path into a folderPath of the subrepo, and // a remainder that can be passed to repo.Handler. // Example: /foo/bar/locks/0123... will be split into: -// ["foo", "bar"] and "/locks/0123..." +// +// ["foo", "bar"] and "/locks/0123..." func splitURLPath(urlPath string, maxDepth int) (folderPath []string, remainder string) { if !strings.HasPrefix(urlPath, "/") { // Really should start with "/" diff --git a/handlers_test.go b/handlers_test.go index 279951f..38773a2 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "fmt" "io" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -165,7 +164,7 @@ func createOverwriteDeleteSeq(t testing.TB, path string, data string) []TestRequ return req } -func createTestHandler(t *testing.T, conf Server) (http.Handler, string, string, string, func()) { +func createTestHandler(t *testing.T, conf *Server) (http.Handler, string, string, string, func()) { buf := make([]byte, 32) _, err := io.ReadFull(rand.Reader, buf) if err != nil { @@ -176,7 +175,7 @@ func createTestHandler(t *testing.T, conf Server) (http.Handler, string, string, fileID := hex.EncodeToString(dataHash[:]) // setup the server with a local backend in a temporary directory - tempdir, err := ioutil.TempDir("", "rest-server-test-") + tempdir, err := os.MkdirTemp("", "rest-server-test-") if err != nil { t.Fatal(err) } @@ -190,7 +189,7 @@ func createTestHandler(t *testing.T, conf Server) (http.Handler, string, string, } conf.Path = tempdir - mux, err := NewHandler(&conf) + mux, err := NewHandler(conf) if err != nil { t.Fatalf("error from NewHandler: %v", err) } @@ -199,7 +198,7 @@ func createTestHandler(t *testing.T, conf Server) (http.Handler, string, string, // TestResticAppendOnlyHandler runs tests on the restic handler code, especially in append-only mode. func TestResticAppendOnlyHandler(t *testing.T) { - mux, data, fileID, _, cleanup := createTestHandler(t, Server{ + mux, data, fileID, _, cleanup := createTestHandler(t, &Server{ AppendOnly: true, NoAuth: true, Debug: true, @@ -300,7 +299,7 @@ func createIdempotentDeleteSeq(t testing.TB, path string, data string) []TestReq // TestResticHandler runs tests on the restic handler code, especially in append-only mode. func TestResticHandler(t *testing.T) { - mux, data, fileID, _, cleanup := createTestHandler(t, Server{ + mux, data, fileID, _, cleanup := createTestHandler(t, &Server{ NoAuth: true, Debug: true, PanicOnError: true, @@ -331,7 +330,7 @@ func TestResticHandler(t *testing.T) { // TestResticErrorHandler runs tests on the restic handler error handling. func TestResticErrorHandler(t *testing.T) { - mux, _, _, tempdir, cleanup := createTestHandler(t, Server{ + mux, _, _, tempdir, cleanup := createTestHandler(t, &Server{ AppendOnly: true, NoAuth: true, Debug: true, @@ -380,7 +379,7 @@ func TestResticErrorHandler(t *testing.T) { } func TestEmptyList(t *testing.T) { - mux, _, _, _, cleanup := createTestHandler(t, Server{ + mux, _, _, _, cleanup := createTestHandler(t, &Server{ AppendOnly: true, NoAuth: true, Debug: true, @@ -404,7 +403,7 @@ func TestEmptyList(t *testing.T) { } func TestListWithUnexpectedFiles(t *testing.T) { - mux, _, _, tempdir, cleanup := createTestHandler(t, Server{ + mux, _, _, tempdir, cleanup := createTestHandler(t, &Server{ AppendOnly: true, NoAuth: true, Debug: true, @@ -510,7 +509,7 @@ func newDelayedErrorReader(err error) *delayErrorReader { } } -func (d *delayErrorReader) Read(p []byte) (int, error) { +func (d *delayErrorReader) Read(_ []byte) (int, error) { d.firstReadOnce.Do(func() { // close the channel to signal that the first read has happened close(d.FirstRead) @@ -522,7 +521,7 @@ func (d *delayErrorReader) Read(p []byte) (int, error) { // TestAbortedRequest runs tests with concurrent upload requests for the same file. func TestAbortedRequest(t *testing.T) { // the race condition doesn't happen for append-only repositories - mux, _, _, _, cleanup := createTestHandler(t, Server{ + mux, _, _, _, cleanup := createTestHandler(t, &Server{ NoAuth: true, Debug: true, PanicOnError: true, diff --git a/htpasswd_test.go b/htpasswd_test.go index 869883b..fe3a46e 100644 --- a/htpasswd_test.go +++ b/htpasswd_test.go @@ -1,7 +1,6 @@ package restserver import ( - "io/ioutil" "os" "testing" ) @@ -12,7 +11,7 @@ func TestValidate(t *testing.T) { rawPwd := "test" wrongPwd := "wrong" - tmpfile, err := ioutil.TempFile("", "rest-validate-") + tmpfile, err := os.CreateTemp("", "rest-validate-") if err != nil { t.Fatal(err) } diff --git a/quota/quota.go b/quota/quota.go index 0b1020e..8437f65 100644 --- a/quota/quota.go +++ b/quota/quota.go @@ -113,7 +113,7 @@ func tallySize(path string) (int64, error) { path = "." } var size int64 - err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { + err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { if err != nil { return err } diff --git a/repo/repo.go b/repo/repo.go index d04879a..cd84929 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "log" "math/rand" "net/http" @@ -251,7 +250,7 @@ func (h *Handler) wrapFileWriter(r *http.Request, w io.Writer) (io.Writer, int, } // checkConfig checks whether a configuration exists. -func (h *Handler) checkConfig(w http.ResponseWriter, r *http.Request) { +func (h *Handler) checkConfig(w http.ResponseWriter, _ *http.Request) { if h.opt.Debug { log.Println("checkConfig()") } @@ -267,13 +266,13 @@ func (h *Handler) checkConfig(w http.ResponseWriter, r *http.Request) { } // getConfig allows for a config to be retrieved. -func (h *Handler) getConfig(w http.ResponseWriter, r *http.Request) { +func (h *Handler) getConfig(w http.ResponseWriter, _ *http.Request) { if h.opt.Debug { log.Println("getConfig()") } cfg := h.getSubPath("config") - bytes, err := ioutil.ReadFile(cfg) + bytes, err := os.ReadFile(cfg) if err != nil { h.fileAccessError(w, err) return @@ -314,7 +313,7 @@ func (h *Handler) saveConfig(w http.ResponseWriter, r *http.Request) { } // deleteConfig removes a config. -func (h *Handler) deleteConfig(w http.ResponseWriter, r *http.Request) { +func (h *Handler) deleteConfig(w http.ResponseWriter, _ *http.Request) { if h.opt.Debug { log.Println("deleteConfig()") } @@ -369,7 +368,7 @@ func (h *Handler) listBlobsV1(w http.ResponseWriter, r *http.Request) { } path := h.getSubPath(objectType) - items, err := ioutil.ReadDir(path) + items, err := os.ReadDir(path) if err != nil { h.fileAccessError(w, err) return @@ -383,8 +382,8 @@ func (h *Handler) listBlobsV1(w http.ResponseWriter, r *http.Request) { continue } subpath := filepath.Join(path, i.Name()) - var subitems []os.FileInfo - subitems, err = ioutil.ReadDir(subpath) + var subitems []os.DirEntry + subitems, err = os.ReadDir(subpath) if err != nil { h.fileAccessError(w, err) return @@ -428,7 +427,7 @@ func (h *Handler) listBlobsV2(w http.ResponseWriter, r *http.Request) { } path := h.getSubPath(objectType) - items, err := ioutil.ReadDir(path) + items, err := os.ReadDir(path) if err != nil { h.fileAccessError(w, err) return @@ -442,17 +441,27 @@ func (h *Handler) listBlobsV2(w http.ResponseWriter, r *http.Request) { continue } subpath := filepath.Join(path, i.Name()) - var subitems []os.FileInfo - subitems, err = ioutil.ReadDir(subpath) + var subitems []os.DirEntry + subitems, err = os.ReadDir(subpath) if err != nil { h.fileAccessError(w, err) return } for _, f := range subitems { - blobs = append(blobs, Blob{Name: f.Name(), Size: f.Size()}) + fi, err := f.Info() + if err != nil { + h.fileAccessError(w, err) + return + } + blobs = append(blobs, Blob{Name: f.Name(), Size: fi.Size()}) } } else { - blobs = append(blobs, Blob{Name: i.Name(), Size: i.Size()}) + fi, err := i.Info() + if err != nil { + h.fileAccessError(w, err) + return + } + blobs = append(blobs, Blob{Name: i.Name(), Size: fi.Size()}) } } @@ -652,7 +661,7 @@ func (h *Handler) saveBlob(w http.ResponseWriter, r *http.Request) { h.sendMetric(objectType, BlobWrite, uint64(written)) } -// tempFile implements a custom version of ioutil.TempFile which allows modifying the file permissions +// tempFile implements a custom version of os.CreateTemp which allows modifying the file permissions func tempFile(fn string, perm os.FileMode) (f *os.File, err error) { for i := 0; i < 10; i++ { name := fn + strconv.FormatInt(rand.Int63(), 10) |