Merge pull request #322 from MichaelEischer/bump-go-version

Bump minimum go version to 1.22
This commit is contained in:
Michael Eischer 2025-02-17 21:37:02 +01:00 committed by GitHub
commit 376392a89c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 162 additions and 112 deletions

View file

@ -7,9 +7,13 @@ on:
# run tests for all pull requests # run tests for all pull requests
pull_request: pull_request:
merge_group:
permissions:
contents: read
env: env:
latest_go: "1.21.x" latest_go: "1.23.x"
GO111MODULE: on GO111MODULE: on
jobs: jobs:
@ -17,10 +21,8 @@ jobs:
strategy: strategy:
matrix: matrix:
go: go:
- 1.18.x - 1.23.x
- 1.19.x - 1.22.x
- 1.20.x
- 1.21.x
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Go ${{ matrix.go }} name: Go ${{ matrix.go }}
@ -28,25 +30,21 @@ jobs:
GOPROXY: https://proxy.golang.org GOPROXY: https://proxy.golang.org
steps: steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Go ${{ matrix.go }} - name: Set up Go ${{ matrix.go }}
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ${{ matrix.go }} 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 - name: Build with build.go
run: | run: |
go run build.go --goos linux go run build.go --goos linux
go run build.go --goos windows go run build.go --goos windows
go run build.go --goos darwin go run build.go --goos darwin
- name: Run tests - name: Run local Tests
run: | run: |
go test ./... go test ./...
@ -61,23 +59,25 @@ jobs:
lint: lint:
name: lint name: lint
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
# allow annotating code in the PR
checks: write
steps: steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Go ${{ env.latest_go }} - name: Set up Go ${{ env.latest_go }}
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ${{ env.latest_go }} go-version: ${{ env.latest_go }}
- name: Check out code
uses: actions/checkout@v4
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v6 uses: golangci/golangci-lint-action@v6
with: with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. # 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 version: v1.63.4
# Optional: show only new issues if it's a pull request. The default value is `false`. args: --verbose --timeout 5m
only-new-issues: true
args: --verbose --timeout 10m
# only run golangci-lint for pull requests, otherwise ALL hints get # only run golangci-lint for pull requests, otherwise ALL hints get
# reported. We need to slowly address all issues until we can enable # 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" echo "check if go.mod and go.sum are up to date"
go mod tidy go mod tidy
git diff --exit-code go.mod go.sum 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) }}

View file

@ -10,13 +10,10 @@ linters:
# make sure all errors returned by functions are handled # make sure all errors returned by functions are handled
- errcheck - errcheck
# find unused code
- deadcode
# show how code can be simplified # show how code can be simplified
- gosimple - gosimple
# # make sure code is formatted # make sure code is formatted
- gofmt - gofmt
# examine code and report suspicious constructs, such as Printf calls whose # examine code and report suspicious constructs, such as Printf calls whose
@ -35,15 +32,14 @@ linters:
# find unused variables, functions, structs, types, etc. # find unused variables, functions, structs, types, etc.
- unused - unused
# find unused struct fields
- structcheck
# find unused global variables
- varcheck
# parse and typecheck code # parse and typecheck code
- typecheck - typecheck
# ensure that http response bodies are closed
- bodyclose
- importas
issues: issues:
# don't use the default exclude rules, this hides (among others) ignored # don't use the default exclude rules, this hides (among others) ignored
# errors from Close() calls # errors from Close() calls
@ -55,3 +51,6 @@ issues:
- exported (function|method|var|type|const) .* should have comment or be unexported - exported (function|method|var|type|const) .* should have comment or be unexported
# revive: ignore constants in all caps # revive: ignore constants in all caps
- don't use ALL_CAPS in Go names; use CamelCase - 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:"

View file

@ -11,7 +11,7 @@ Rest Server is a high performance HTTP server that implements restic's [REST bac
## Requirements ## 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. 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.

View file

@ -58,7 +58,7 @@ var config = Config{
Namespace: "github.com/restic/rest-server", // subdir of GOPATH, e.g. "github.com/foo/bar" 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 Main: "github.com/restic/rest-server/cmd/rest-server", // package name for the main package
Tests: []string{"./..."}, // tests to run 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. // Config configures the build.

View file

@ -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

View file

@ -61,7 +61,10 @@ func TestUnixSocket(t *testing.T) {
if err != nil { if err != nil {
return err return err
} }
resp.Body.Close() err = resp.Body.Close()
if err != nil {
return err
}
if resp.StatusCode != test.StatusCode { if resp.StatusCode != test.StatusCode {
return fmt.Errorf("expected %d from server, instead got %d (path %s)", test.StatusCode, resp.StatusCode, test.Path) return fmt.Errorf("expected %d from server, instead got %d (path %s)", test.StatusCode, resp.StatusCode, test.Path)
} }

View file

@ -22,7 +22,7 @@ import (
type restServerApp struct { type restServerApp struct {
CmdRoot *cobra.Command CmdRoot *cobra.Command
Server restserver.Server Server restserver.Server
CpuProfile string CPUProfile string
listenerAddressMu sync.Mutex listenerAddressMu sync.Mutex
listenerAddress net.Addr // set after startup listenerAddress net.Addr // set after startup
@ -36,7 +36,7 @@ func newRestServerApp() *restServerApp {
Short: "Run a REST server for use with restic", Short: "Run a REST server for use with restic",
SilenceErrors: true, SilenceErrors: true,
SilenceUsage: true, SilenceUsage: true,
Args: func(cmd *cobra.Command, args []string) error { Args: func(_ *cobra.Command, args []string) error {
if len(args) != 0 { if len(args) != 0 {
return fmt.Errorf("rest-server expects no arguments - unknown argument: %s", 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 rv.CmdRoot.RunE = rv.runRoot
flags := rv.CmdRoot.Flags() 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.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.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)") 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 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.SetFlags(0)
log.Printf("Data directory: %s", app.Server.Path) log.Printf("Data directory: %s", app.Server.Path)
if app.CpuProfile != "" { if app.CPUProfile != "" {
f, err := os.Create(app.CpuProfile) f, err := os.Create(app.CPUProfile)
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer func() {
_ = f.Close()
}()
if err := pprof.StartCPUProfile(f); err != nil { if err := pprof.StartCPUProfile(f); err != nil {
return err return err

View file

@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -94,7 +93,7 @@ func TestTLSSettings(t *testing.T) {
} }
func TestGetHandler(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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -120,7 +119,7 @@ func TestGetHandler(t *testing.T) {
} }
// With NoAuth = false and custom .htpasswd // With NoAuth = false and custom .htpasswd
htpFile, err := ioutil.TempFile(dir, "custom") htpFile, err := os.CreateTemp(dir, "custom")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -137,7 +136,7 @@ func TestGetHandler(t *testing.T) {
// Create .htpasswd // Create .htpasswd
htpasswd := filepath.Join(dir, ".htpasswd") htpasswd := filepath.Join(dir, ".htpasswd")
err = ioutil.WriteFile(htpasswd, []byte(""), 0644) err = os.WriteFile(htpasswd, []byte(""), 0644)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -262,7 +261,10 @@ func TestHttpListen(t *testing.T) {
if err != nil { if err != nil {
return err return err
} }
resp.Body.Close() err = resp.Body.Close()
if err != nil {
return err
}
if resp.StatusCode != test.StatusCode { if resp.StatusCode != test.StatusCode {
return fmt.Errorf("expected %d from server, instead got %d (path %s)", test.StatusCode, resp.StatusCode, test.Path) return fmt.Errorf("expected %d from server, instead got %d (path %s)", test.StatusCode, resp.StatusCode, test.Path)
} }

27
go.mod
View file

@ -1,28 +1,29 @@
module github.com/restic/rest-server module github.com/restic/rest-server
go 1.18 go 1.22
require ( require (
github.com/coreos/go-systemd/v22 v22.5.0 github.com/coreos/go-systemd/v22 v22.5.0
github.com/gorilla/handlers v1.5.2 github.com/gorilla/handlers v1.5.2
github.com/minio/sha256-simd v1.0.1 github.com/minio/sha256-simd v1.0.1
github.com/miolini/datacounter v1.0.3 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 github.com/spf13/cobra v1.8.1
golang.org/x/crypto v0.27.0 golang.org/x/crypto v0.32.0
) )
require ( require (
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/klauspost/compress v1.17.9 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/prometheus/client_model v0.5.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/prometheus/procfs v0.15.1 // indirect
golang.org/x/sys v0.25.0 // indirect github.com/spf13/pflag v1.0.6 // indirect
google.golang.org/protobuf v1.33.0 // indirect golang.org/x/sys v0.30.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
) )

61
go.sum
View file

@ -1,46 +1,57 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 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/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.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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/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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 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/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 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= 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 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 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 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 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 h1:tanOZPVblGXQl7/bSZWoEM8l4KK83q24qwQLMrO/HOA=
github.com/miolini/datacounter v1.0.3/go.mod h1:C45dc2hBumHjDpEU64IqPwR6TDyPVpzOqqRTN7zmBUA= 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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 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/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 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/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= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -158,7 +158,8 @@ func join(base string, names ...string) (string, error) {
// splitURLPath splits the URL path into a folderPath of the subrepo, and // splitURLPath splits the URL path into a folderPath of the subrepo, and
// a remainder that can be passed to repo.Handler. // a remainder that can be passed to repo.Handler.
// Example: /foo/bar/locks/0123... will be split into: // 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) { func splitURLPath(urlPath string, maxDepth int) (folderPath []string, remainder string) {
if !strings.HasPrefix(urlPath, "/") { if !strings.HasPrefix(urlPath, "/") {
// Really should start with "/" // Really should start with "/"

View file

@ -6,7 +6,6 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
@ -165,7 +164,7 @@ func createOverwriteDeleteSeq(t testing.TB, path string, data string) []TestRequ
return req 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) buf := make([]byte, 32)
_, err := io.ReadFull(rand.Reader, buf) _, err := io.ReadFull(rand.Reader, buf)
if err != nil { if err != nil {
@ -176,7 +175,7 @@ func createTestHandler(t *testing.T, conf Server) (http.Handler, string, string,
fileID := hex.EncodeToString(dataHash[:]) fileID := hex.EncodeToString(dataHash[:])
// setup the server with a local backend in a temporary directory // 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -190,7 +189,7 @@ func createTestHandler(t *testing.T, conf Server) (http.Handler, string, string,
} }
conf.Path = tempdir conf.Path = tempdir
mux, err := NewHandler(&conf) mux, err := NewHandler(conf)
if err != nil { if err != nil {
t.Fatalf("error from NewHandler: %v", err) 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. // TestResticAppendOnlyHandler runs tests on the restic handler code, especially in append-only mode.
func TestResticAppendOnlyHandler(t *testing.T) { func TestResticAppendOnlyHandler(t *testing.T) {
mux, data, fileID, _, cleanup := createTestHandler(t, Server{ mux, data, fileID, _, cleanup := createTestHandler(t, &Server{
AppendOnly: true, AppendOnly: true,
NoAuth: true, NoAuth: true,
Debug: 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. // TestResticHandler runs tests on the restic handler code, especially in append-only mode.
func TestResticHandler(t *testing.T) { func TestResticHandler(t *testing.T) {
mux, data, fileID, _, cleanup := createTestHandler(t, Server{ mux, data, fileID, _, cleanup := createTestHandler(t, &Server{
NoAuth: true, NoAuth: true,
Debug: true, Debug: true,
PanicOnError: true, PanicOnError: true,
@ -331,7 +330,7 @@ func TestResticHandler(t *testing.T) {
// TestResticErrorHandler runs tests on the restic handler error handling. // TestResticErrorHandler runs tests on the restic handler error handling.
func TestResticErrorHandler(t *testing.T) { func TestResticErrorHandler(t *testing.T) {
mux, _, _, tempdir, cleanup := createTestHandler(t, Server{ mux, _, _, tempdir, cleanup := createTestHandler(t, &Server{
AppendOnly: true, AppendOnly: true,
NoAuth: true, NoAuth: true,
Debug: true, Debug: true,
@ -380,7 +379,7 @@ func TestResticErrorHandler(t *testing.T) {
} }
func TestEmptyList(t *testing.T) { func TestEmptyList(t *testing.T) {
mux, _, _, _, cleanup := createTestHandler(t, Server{ mux, _, _, _, cleanup := createTestHandler(t, &Server{
AppendOnly: true, AppendOnly: true,
NoAuth: true, NoAuth: true,
Debug: true, Debug: true,
@ -404,7 +403,7 @@ func TestEmptyList(t *testing.T) {
} }
func TestListWithUnexpectedFiles(t *testing.T) { func TestListWithUnexpectedFiles(t *testing.T) {
mux, _, _, tempdir, cleanup := createTestHandler(t, Server{ mux, _, _, tempdir, cleanup := createTestHandler(t, &Server{
AppendOnly: true, AppendOnly: true,
NoAuth: true, NoAuth: true,
Debug: 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() { d.firstReadOnce.Do(func() {
// close the channel to signal that the first read has happened // close the channel to signal that the first read has happened
close(d.FirstRead) 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. // TestAbortedRequest runs tests with concurrent upload requests for the same file.
func TestAbortedRequest(t *testing.T) { func TestAbortedRequest(t *testing.T) {
// the race condition doesn't happen for append-only repositories // the race condition doesn't happen for append-only repositories
mux, _, _, _, cleanup := createTestHandler(t, Server{ mux, _, _, _, cleanup := createTestHandler(t, &Server{
NoAuth: true, NoAuth: true,
Debug: true, Debug: true,
PanicOnError: true, PanicOnError: true,

View file

@ -1,7 +1,6 @@
package restserver package restserver
import ( import (
"io/ioutil"
"os" "os"
"testing" "testing"
) )
@ -12,7 +11,7 @@ func TestValidate(t *testing.T) {
rawPwd := "test" rawPwd := "test"
wrongPwd := "wrong" wrongPwd := "wrong"
tmpfile, err := ioutil.TempFile("", "rest-validate-") tmpfile, err := os.CreateTemp("", "rest-validate-")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -113,7 +113,7 @@ func tallySize(path string) (int64, error) {
path = "." path = "."
} }
var size int64 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 { if err != nil {
return err return err
} }

View file

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log" "log"
"math/rand" "math/rand"
"net/http" "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. // 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 { if h.opt.Debug {
log.Println("checkConfig()") 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. // 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 { if h.opt.Debug {
log.Println("getConfig()") log.Println("getConfig()")
} }
cfg := h.getSubPath("config") cfg := h.getSubPath("config")
bytes, err := ioutil.ReadFile(cfg) bytes, err := os.ReadFile(cfg)
if err != nil { if err != nil {
h.fileAccessError(w, err) h.fileAccessError(w, err)
return return
@ -314,7 +313,7 @@ func (h *Handler) saveConfig(w http.ResponseWriter, r *http.Request) {
} }
// deleteConfig removes a config. // 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 { if h.opt.Debug {
log.Println("deleteConfig()") log.Println("deleteConfig()")
} }
@ -369,7 +368,7 @@ func (h *Handler) listBlobsV1(w http.ResponseWriter, r *http.Request) {
} }
path := h.getSubPath(objectType) path := h.getSubPath(objectType)
items, err := ioutil.ReadDir(path) items, err := os.ReadDir(path)
if err != nil { if err != nil {
h.fileAccessError(w, err) h.fileAccessError(w, err)
return return
@ -383,8 +382,8 @@ func (h *Handler) listBlobsV1(w http.ResponseWriter, r *http.Request) {
continue continue
} }
subpath := filepath.Join(path, i.Name()) subpath := filepath.Join(path, i.Name())
var subitems []os.FileInfo var subitems []os.DirEntry
subitems, err = ioutil.ReadDir(subpath) subitems, err = os.ReadDir(subpath)
if err != nil { if err != nil {
h.fileAccessError(w, err) h.fileAccessError(w, err)
return return
@ -428,7 +427,7 @@ func (h *Handler) listBlobsV2(w http.ResponseWriter, r *http.Request) {
} }
path := h.getSubPath(objectType) path := h.getSubPath(objectType)
items, err := ioutil.ReadDir(path) items, err := os.ReadDir(path)
if err != nil { if err != nil {
h.fileAccessError(w, err) h.fileAccessError(w, err)
return return
@ -442,17 +441,27 @@ func (h *Handler) listBlobsV2(w http.ResponseWriter, r *http.Request) {
continue continue
} }
subpath := filepath.Join(path, i.Name()) subpath := filepath.Join(path, i.Name())
var subitems []os.FileInfo var subitems []os.DirEntry
subitems, err = ioutil.ReadDir(subpath) subitems, err = os.ReadDir(subpath)
if err != nil { if err != nil {
h.fileAccessError(w, err) h.fileAccessError(w, err)
return return
} }
for _, f := range subitems { 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 { } 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)) 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) { func tempFile(fn string, perm os.FileMode) (f *os.File, err error) {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
name := fn + strconv.FormatInt(rand.Int63(), 10) name := fn + strconv.FormatInt(rand.Int63(), 10)