mirror of
https://github.com/restic/restic.git
synced 2025-12-11 18:47:50 +00:00
Merge pull request #5405 from restic/dependabot/github_actions/golangci/golangci-lint-action-8
build(deps): bump golangci/golangci-lint-action from 6 to 8
This commit is contained in:
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
@@ -250,10 +250,10 @@ jobs:
|
|||||||
go-version: ${{ env.latest_go }}
|
go-version: ${{ env.latest_go }}
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v8
|
||||||
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.64.8
|
version: v2.4.0
|
||||||
args: --verbose --timeout 5m
|
args: --verbose --timeout 5m
|
||||||
|
|
||||||
# only run golangci-lint for pull requests, otherwise ALL hints get
|
# only run golangci-lint for pull requests, otherwise ALL hints get
|
||||||
|
|||||||
121
.golangci.yml
121
.golangci.yml
@@ -1,70 +1,79 @@
|
|||||||
# This is the configuration for golangci-lint for the restic project.
|
version: "2"
|
||||||
#
|
|
||||||
# A sample config with all settings is here:
|
|
||||||
# https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
# only enable the linters listed below
|
# only enable the linters listed below
|
||||||
disable-all: true
|
default: none
|
||||||
enable:
|
enable:
|
||||||
|
- asciicheck
|
||||||
|
# ensure that http response bodies are closed
|
||||||
|
- bodyclose
|
||||||
|
- copyloopvar
|
||||||
# make sure all errors returned by functions are handled
|
# make sure all errors returned by functions are handled
|
||||||
- errcheck
|
- errcheck
|
||||||
|
|
||||||
# show how code can be simplified
|
|
||||||
- gosimple
|
|
||||||
|
|
||||||
# make sure code is formatted
|
|
||||||
- gofmt
|
|
||||||
|
|
||||||
# examine code and report suspicious constructs, such as Printf calls whose
|
# examine code and report suspicious constructs, such as Printf calls whose
|
||||||
# arguments do not align with the format string
|
# arguments do not align with the format string
|
||||||
- govet
|
- govet
|
||||||
|
# consistent imports
|
||||||
# make sure names and comments are used according to the conventions
|
- importas
|
||||||
- revive
|
|
||||||
|
|
||||||
# detect when assignments to existing variables are not used
|
# detect when assignments to existing variables are not used
|
||||||
- ineffassign
|
- ineffassign
|
||||||
|
- nolintlint
|
||||||
|
# make sure names and comments are used according to the conventions
|
||||||
|
- revive
|
||||||
# run static analysis and find errors
|
# run static analysis and find errors
|
||||||
- staticcheck
|
- staticcheck
|
||||||
|
|
||||||
# find unused variables, functions, structs, types, etc.
|
# find unused variables, functions, structs, types, etc.
|
||||||
- unused
|
- unused
|
||||||
|
settings:
|
||||||
# parse and typecheck code
|
importas:
|
||||||
- typecheck
|
alias:
|
||||||
|
- pkg: github.com/restic/restic/internal/test
|
||||||
# ensure that http response bodies are closed
|
alias: rtest
|
||||||
- bodyclose
|
staticcheck:
|
||||||
|
checks:
|
||||||
- importas
|
# default
|
||||||
|
- "all"
|
||||||
issues:
|
- "-ST1000"
|
||||||
# don't use the default exclude rules, this hides (among others) ignored
|
- "-ST1003"
|
||||||
# errors from Close() calls
|
- "-ST1016"
|
||||||
exclude-use-default: false
|
- "-ST1020"
|
||||||
|
- "-ST1021"
|
||||||
# list of things to not warn about
|
- "-ST1022"
|
||||||
exclude:
|
# extra disables
|
||||||
# revive: do not warn about missing comments for exported stuff
|
- "-QF1008" # don't warn about specifing name of embedded field on access
|
||||||
- exported (function|method|var|type|const) .* should have comment or be unexported
|
exclusions:
|
||||||
# revive: ignore constants in all caps
|
rules:
|
||||||
- don't use ALL_CAPS in Go names; use CamelCase
|
# revive: ignore unused parameters in tests
|
||||||
# revive: lots of packages don't have such a comment
|
- path: (_test\.go|testing\.go|backend/.*/tests\.go)
|
||||||
- "package-comments: should have a package comment"
|
text: "unused-parameter:"
|
||||||
# staticcheck: there's no easy way to replace these packages
|
# revive: do not warn about missing comments for exported stuff
|
||||||
- "SA1019: \"golang.org/x/crypto/poly1305\" is deprecated"
|
- path: (.+)\.go$
|
||||||
- "SA1019: \"golang.org/x/crypto/openpgp\" is deprecated"
|
text: exported (function|method|var|type|const) .* should have comment or be unexported
|
||||||
- "redefines-builtin-id:"
|
# revive: ignore constants in all caps
|
||||||
|
- path: (.+)\.go$
|
||||||
exclude-rules:
|
text: don't use ALL_CAPS in Go names; use CamelCase
|
||||||
# revive: ignore unused parameters in tests
|
# revive: lots of packages don't have such a comment
|
||||||
- path: (_test\.go|testing\.go|backend/.*/tests\.go)
|
- path: (.+)\.go$
|
||||||
text: "unused-parameter:"
|
text: "package-comments: should have a package comment"
|
||||||
|
# staticcheck: there's no easy way to replace these packages
|
||||||
linters-settings:
|
- path: (.+)\.go$
|
||||||
importas:
|
text: 'SA1019: "golang.org/x/crypto/poly1305" is deprecated'
|
||||||
alias:
|
- path: (.+)\.go$
|
||||||
- pkg: github.com/restic/restic/internal/test
|
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated'
|
||||||
alias: rtest
|
- path: (.+)\.go$
|
||||||
|
text: "redefines-builtin-id:"
|
||||||
|
# revive: collection of helpers to implement a backend, more descriptive names would be too repetitive
|
||||||
|
- path: internal/backend/util/.*.go$
|
||||||
|
text: "var-naming: avoid meaningless package names"
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
# make sure code is formatted
|
||||||
|
- gofmt
|
||||||
|
exclusions:
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
|||||||
@@ -461,7 +461,6 @@ func TestIncrementalBackup(t *testing.T) {
|
|||||||
t.Logf("repository grown by %d bytes", stat3.size-stat2.size)
|
t.Logf("repository grown by %d bytes", stat3.size-stat2.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: staticcheck // false positive nil pointer dereference check
|
|
||||||
func TestBackupTags(t *testing.T) {
|
func TestBackupTags(t *testing.T) {
|
||||||
env, cleanup := withTestEnvironment(t)
|
env, cleanup := withTestEnvironment(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
@@ -497,7 +496,6 @@ func TestBackupTags(t *testing.T) {
|
|||||||
"expected parent to be %v, got %v", parent.ID, newest.Parent)
|
"expected parent to be %v, got %v", parent.ID, newest.Parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: staticcheck // false positive nil pointer dereference check
|
|
||||||
func TestBackupProgramVersion(t *testing.T) {
|
func TestBackupProgramVersion(t *testing.T) {
|
||||||
env, cleanup := withTestEnvironment(t)
|
env, cleanup := withTestEnvironment(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ func (s *statefulOutput) PrintPatternJSON(path string, node *restic.Node) {
|
|||||||
}
|
}
|
||||||
if s.newsn != s.oldsn {
|
if s.newsn != s.oldsn {
|
||||||
if s.oldsn != nil {
|
if s.oldsn != nil {
|
||||||
_, _ = s.stdout.Write([]byte(fmt.Sprintf("],\"hits\":%d,\"snapshot\":%q},", s.hits, s.oldsn.ID())))
|
_, _ = fmt.Fprintf(s.stdout, "],\"hits\":%d,\"snapshot\":%q},", s.hits, s.oldsn.ID())
|
||||||
}
|
}
|
||||||
_, _ = s.stdout.Write([]byte(`{"matches":[`))
|
_, _ = s.stdout.Write([]byte(`{"matches":[`))
|
||||||
s.oldsn = s.newsn
|
s.oldsn = s.newsn
|
||||||
@@ -255,7 +255,7 @@ func (s *statefulOutput) Finish() {
|
|||||||
if s.JSON {
|
if s.JSON {
|
||||||
// do some finishing up
|
// do some finishing up
|
||||||
if s.oldsn != nil {
|
if s.oldsn != nil {
|
||||||
_, _ = s.stdout.Write([]byte(fmt.Sprintf("],\"hits\":%d,\"snapshot\":%q}", s.hits, s.oldsn.ID())))
|
_, _ = fmt.Fprintf(s.stdout, "],\"hits\":%d,\"snapshot\":%q}", s.hits, s.oldsn.ID())
|
||||||
}
|
}
|
||||||
if s.inuse {
|
if s.inuse {
|
||||||
_, _ = s.stdout.Write([]byte("]\n"))
|
_, _ = s.stdout.Write([]byte("]\n"))
|
||||||
|
|||||||
@@ -65,17 +65,19 @@ func runInit(ctx context.Context, opts InitOptions, gopts GlobalOptions, args []
|
|||||||
printer := newTerminalProgressPrinter(gopts.JSON, gopts.verbosity, term)
|
printer := newTerminalProgressPrinter(gopts.JSON, gopts.verbosity, term)
|
||||||
|
|
||||||
var version uint
|
var version uint
|
||||||
if opts.RepositoryVersion == "latest" || opts.RepositoryVersion == "" {
|
switch opts.RepositoryVersion {
|
||||||
|
case "latest", "":
|
||||||
version = restic.MaxRepoVersion
|
version = restic.MaxRepoVersion
|
||||||
} else if opts.RepositoryVersion == "stable" {
|
case "stable":
|
||||||
version = restic.StableRepoVersion
|
version = restic.StableRepoVersion
|
||||||
} else {
|
default:
|
||||||
v, err := strconv.ParseUint(opts.RepositoryVersion, 10, 32)
|
v, err := strconv.ParseUint(opts.RepositoryVersion, 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Fatal("invalid repository version")
|
return errors.Fatal("invalid repository version")
|
||||||
}
|
}
|
||||||
version = uint(v)
|
version = uint(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if version < restic.MinRepoVersion || version > restic.MaxRepoVersion {
|
if version < restic.MinRepoVersion || version > restic.MaxRepoVersion {
|
||||||
return errors.Fatalf("only repository versions between %v and %v are allowed", restic.MinRepoVersion, restic.MaxRepoVersion)
|
return errors.Fatalf("only repository versions between %v and %v are allowed", restic.MinRepoVersion, restic.MaxRepoVersion)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ func TestRestoreNoMetadataOnIgnoredIntermediateDirs(t *testing.T) {
|
|||||||
fi, err := os.Stat(f2)
|
fi, err := os.Stat(f2)
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
|
||||||
rtest.Assert(t, fi.ModTime() == time.Unix(0, 0),
|
rtest.Assert(t, fi.ModTime().Equal(time.Unix(0, 0)),
|
||||||
"meta data of intermediate directory hasn't been restore")
|
"meta data of intermediate directory hasn't been restore")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ func testRunTag(t testing.TB, opts TagOptions, gopts GlobalOptions) {
|
|||||||
rtest.OK(t, runTag(context.TODO(), opts, gopts, nil, []string{}))
|
rtest.OK(t, runTag(context.TODO(), opts, gopts, nil, []string{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: staticcheck // false positive nil pointer dereference check
|
|
||||||
func TestTag(t *testing.T) {
|
func TestTag(t *testing.T) {
|
||||||
env, cleanup := withTestEnvironment(t)
|
env, cleanup := withTestEnvironment(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|||||||
@@ -498,6 +498,7 @@ func innerOpen(ctx context.Context, s string, gopts GlobalOptions, opts options.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, backend.ErrNoRepository) {
|
if errors.Is(err, backend.ErrNoRepository) {
|
||||||
|
//nolint:staticcheck // capitalized error string is intentional
|
||||||
return nil, fmt.Errorf("Fatal: %w at %v: %v", ErrNoRepository, location.StripPassword(gopts.backends, s), err)
|
return nil, fmt.Errorf("Fatal: %w at %v: %v", ErrNoRepository, location.StripPassword(gopts.backends, s), err)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -552,6 +553,7 @@ func open(ctx context.Context, s string, gopts GlobalOptions, opts options.Optio
|
|||||||
// check if config is there
|
// check if config is there
|
||||||
fi, err := be.Stat(ctx, backend.Handle{Type: restic.ConfigFile})
|
fi, err := be.Stat(ctx, backend.Handle{Type: restic.ConfigFile})
|
||||||
if be.IsNotExist(err) {
|
if be.IsNotExist(err) {
|
||||||
|
//nolint:staticcheck // capitalized error string is intentional
|
||||||
return nil, fmt.Errorf("Fatal: %w: unable to open config file: %v\nIs there a repository at the following location?\n%v", ErrNoRepository, err, location.StripPassword(gopts.backends, s))
|
return nil, fmt.Errorf("Fatal: %w: unable to open config file: %v\nIs there a repository at the following location?\n%v", ErrNoRepository, err, location.StripPassword(gopts.backends, s))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -173,9 +173,10 @@ func main() {
|
|||||||
ctx := createGlobalContext()
|
ctx := createGlobalContext()
|
||||||
err = newRootCommand().ExecuteContext(ctx)
|
err = newRootCommand().ExecuteContext(ctx)
|
||||||
|
|
||||||
if err == nil {
|
switch err {
|
||||||
|
case nil:
|
||||||
err = ctx.Err()
|
err = ctx.Err()
|
||||||
} else if err == ErrOK {
|
case ErrOK:
|
||||||
// ErrOK overwrites context cancellation errors
|
// ErrOK overwrites context cancellation errors
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,7 @@ func readPEMCertKey(filename string) (certs []byte, key []byte, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var block *pem.Block
|
var block *pem.Block
|
||||||
for {
|
for len(data) > 0 {
|
||||||
if len(data) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
block, data = pem.Decode(data)
|
block, data = pem.Decode(data)
|
||||||
if block == nil {
|
if block == nil {
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ func TestRoundTripperReader(t *testing.T) {
|
|||||||
test.Assert(t, bytes.Equal(data, out.Bytes()), "data ping-pong failed")
|
test.Assert(t, bytes.Equal(data, out.Bytes()), "data ping-pong failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:bodyclose // the http response is just a mock
|
//nolint:bodyclose // the http response is just a mock
|
||||||
func TestRoundTripperCornerCases(t *testing.T) {
|
func TestRoundTripperCornerCases(t *testing.T) {
|
||||||
limiter := NewStaticLimiter(Limits{42 * 1024, 42 * 1024})
|
limiter := NewStaticLimiter(Limits{42 * 1024, 42 * 1024})
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func isPath(s string) bool {
|
|||||||
|
|
||||||
// check for drive paths
|
// check for drive paths
|
||||||
drive := s[0]
|
drive := s[0]
|
||||||
|
//nolint:staticcheck // de morgan's law makes this harder to read
|
||||||
if !(drive >= 'a' && drive <= 'z') && !(drive >= 'A' && drive <= 'Z') {
|
if !(drive >= 'a' && drive <= 'z') && !(drive >= 'A' && drive <= 'Z') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ func TestListAPI(t *testing.T) {
|
|||||||
t.Logf("req %v %v, accept: %v", req.Method, req.URL.Path, req.Header["Accept"])
|
t.Logf("req %v %v, accept: %v", req.Method, req.URL.Path, req.Header["Accept"])
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
switch {
|
switch req.Method {
|
||||||
case req.Method == "GET":
|
case "GET":
|
||||||
// list files in data/
|
// list files in data/
|
||||||
res.Header().Set("Content-Type", test.ContentType)
|
res.Header().Set("Content-Type", test.ContentType)
|
||||||
_, err = res.Write([]byte(test.Data))
|
_, err = res.Write([]byte(test.Data))
|
||||||
@@ -89,7 +89,7 @@ func TestListAPI(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case req.Method == "HEAD":
|
case "HEAD":
|
||||||
// stat file in data/, use the first two bytes in the name
|
// stat file in data/, use the first two bytes in the name
|
||||||
// of the file as the size :)
|
// of the file as the size :)
|
||||||
filename := req.URL.Path[6:]
|
filename := req.URL.Path[6:]
|
||||||
|
|||||||
@@ -176,7 +176,6 @@ func (r *SFTP) mkdirAllDataSubdirs(ctx context.Context, nconn uint) error {
|
|||||||
g.SetLimit(int(nconn))
|
g.SetLimit(int(nconn))
|
||||||
|
|
||||||
for _, d := range r.Paths() {
|
for _, d := range r.Paths() {
|
||||||
d := d
|
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
// First try Mkdir. For most directories in Paths, this takes one
|
// First try Mkdir. For most directories in Paths, this takes one
|
||||||
// round trip, not counting duplicate parent creations causes by
|
// round trip, not counting duplicate parent creations causes by
|
||||||
|
|||||||
@@ -669,7 +669,6 @@ func benchmarkSnapshotScaling(t *testing.B, newSnapshots int) {
|
|||||||
func BenchmarkCheckerSnapshotScaling(b *testing.B) {
|
func BenchmarkCheckerSnapshotScaling(b *testing.B) {
|
||||||
counts := []int{50, 100, 200}
|
counts := []int{50, 100, 200}
|
||||||
for _, count := range counts {
|
for _, count := range counts {
|
||||||
count := count
|
|
||||||
b.Run(strconv.Itoa(count), func(b *testing.B) {
|
b.Run(strconv.Itoa(count), func(b *testing.B) {
|
||||||
benchmarkSnapshotScaling(b, count)
|
benchmarkSnapshotScaling(b, count)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -64,10 +64,11 @@ func parseFilter(envname string, pad func(string) string) map[string]bool {
|
|||||||
for _, fn := range strings.Split(env, ",") {
|
for _, fn := range strings.Split(env, ",") {
|
||||||
t := pad(strings.TrimSpace(fn))
|
t := pad(strings.TrimSpace(fn))
|
||||||
val := true
|
val := true
|
||||||
if t[0] == '-' {
|
switch t[0] {
|
||||||
|
case '-':
|
||||||
val = false
|
val = false
|
||||||
t = t[1:]
|
t = t[1:]
|
||||||
} else if t[0] == '+' {
|
case '+':
|
||||||
val = true
|
val = true
|
||||||
t = t[1:]
|
t = t[1:]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,13 +116,13 @@ func TestMatch(t *testing.T) {
|
|||||||
|
|
||||||
// Test with native path separator
|
// Test with native path separator
|
||||||
if filepath.Separator != '/' {
|
if filepath.Separator != '/' {
|
||||||
pattern := strings.Replace(test.pattern, "/", string(filepath.Separator), -1)
|
pattern := strings.ReplaceAll(test.pattern, "/", string(filepath.Separator))
|
||||||
// Test with pattern as native
|
// Test with pattern as native
|
||||||
t.Run("pattern-native", func(t *testing.T) {
|
t.Run("pattern-native", func(t *testing.T) {
|
||||||
testpattern(t, pattern, test.path, test.match)
|
testpattern(t, pattern, test.path, test.match)
|
||||||
})
|
})
|
||||||
|
|
||||||
path := strings.Replace(test.path, "/", string(filepath.Separator), -1)
|
path := strings.ReplaceAll(test.path, "/", string(filepath.Separator))
|
||||||
t.Run("path-native", func(t *testing.T) {
|
t.Run("path-native", func(t *testing.T) {
|
||||||
// Test with path as native
|
// Test with path as native
|
||||||
testpattern(t, test.pattern, path, test.match)
|
testpattern(t, test.pattern, path, test.match)
|
||||||
@@ -206,13 +206,13 @@ func TestChildMatch(t *testing.T) {
|
|||||||
|
|
||||||
// Test with native path separator
|
// Test with native path separator
|
||||||
if filepath.Separator != '/' {
|
if filepath.Separator != '/' {
|
||||||
pattern := strings.Replace(test.pattern, "/", string(filepath.Separator), -1)
|
pattern := strings.ReplaceAll(test.pattern, "/", string(filepath.Separator))
|
||||||
// Test with pattern as native
|
// Test with pattern as native
|
||||||
t.Run("pattern-native", func(t *testing.T) {
|
t.Run("pattern-native", func(t *testing.T) {
|
||||||
testchildpattern(t, pattern, test.path, test.match)
|
testchildpattern(t, pattern, test.path, test.match)
|
||||||
})
|
})
|
||||||
|
|
||||||
path := strings.Replace(test.path, "/", string(filepath.Separator), -1)
|
path := strings.ReplaceAll(test.path, "/", string(filepath.Separator))
|
||||||
t.Run("path-native", func(t *testing.T) {
|
t.Run("path-native", func(t *testing.T) {
|
||||||
// Test with path as native
|
// Test with path as native
|
||||||
testchildpattern(t, test.pattern, path, test.match)
|
testchildpattern(t, test.pattern, path, test.match)
|
||||||
|
|||||||
@@ -253,11 +253,7 @@ func TestFSReaderDir(t *testing.T) {
|
|||||||
})
|
})
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
dir := path.Dir(tst.filename)
|
dir := path.Dir(tst.filename)
|
||||||
for {
|
for dir != "/" && dir != "." {
|
||||||
if dir == "/" || dir == "." {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
fi, err := fs.Lstat(dir)
|
fi, err := fs.Lstat(dir)
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/restic/restic/internal/errors"
|
"github.com/restic/restic/internal/errors"
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
"github.com/restic/restic/internal/test"
|
|
||||||
rtest "github.com/restic/restic/internal/test"
|
rtest "github.com/restic/restic/internal/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -296,5 +295,5 @@ func TestNodeRestoreMetadataError(t *testing.T) {
|
|||||||
// This will fail because the target file does not exist
|
// This will fail because the target file does not exist
|
||||||
err := NodeRestoreMetadata(node, nodePath, func(msg string) { rtest.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", nodePath, msg)) },
|
err := NodeRestoreMetadata(node, nodePath, func(msg string) { rtest.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", nodePath, msg)) },
|
||||||
func(_ string) bool { return true })
|
func(_ string) bool { return true })
|
||||||
test.Assert(t, errors.Is(err, os.ErrNotExist), "failed for an unexpected reason")
|
rtest.Assert(t, errors.Is(err, os.ErrNotExist), "failed for an unexpected reason")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type ExtendedFileInfo struct {
|
|||||||
ModTime time.Time // last (content) modification time stamp
|
ModTime time.Time // last (content) modification time stamp
|
||||||
ChangeTime time.Time // last status change time stamp
|
ChangeTime time.Time // last status change time stamp
|
||||||
|
|
||||||
// nolint:unused // only used on Windows
|
//nolint:unused // only used on Windows
|
||||||
sys any // Value returned by os.FileInfo.Sys()
|
sys any // Value returned by os.FileInfo.Sys()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -297,11 +297,12 @@ func TestIndexUnserialize(t *testing.T) {
|
|||||||
rtest.Equals(t, test.tpe, blob.Type)
|
rtest.Equals(t, test.tpe, blob.Type)
|
||||||
rtest.Equals(t, test.offset, blob.Offset)
|
rtest.Equals(t, test.offset, blob.Offset)
|
||||||
rtest.Equals(t, test.length, blob.Length)
|
rtest.Equals(t, test.length, blob.Length)
|
||||||
if task.version == 1 {
|
switch task.version {
|
||||||
|
case 1:
|
||||||
rtest.Equals(t, uint(0), blob.UncompressedLength)
|
rtest.Equals(t, uint(0), blob.UncompressedLength)
|
||||||
} else if task.version == 2 {
|
case 2:
|
||||||
rtest.Equals(t, test.uncompressedLength, blob.UncompressedLength)
|
rtest.Equals(t, test.uncompressedLength, blob.UncompressedLength)
|
||||||
} else {
|
default:
|
||||||
t.Fatal("Invalid index version")
|
t.Fatal("Invalid index version")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (p *Packer) Finalize() error {
|
|||||||
encryptedHeader = binary.LittleEndian.AppendUint32(encryptedHeader, uint32(len(encryptedHeader)))
|
encryptedHeader = binary.LittleEndian.AppendUint32(encryptedHeader, uint32(len(encryptedHeader)))
|
||||||
|
|
||||||
if err := verifyHeader(p.k, encryptedHeader, p.blobs); err != nil {
|
if err := verifyHeader(p.k, encryptedHeader, p.blobs); err != nil {
|
||||||
//nolint:revive // ignore linter warnings about error message spelling
|
//nolint:revive,staticcheck // ignore linter warnings about error message spelling
|
||||||
return fmt.Errorf("Detected data corruption while writing pack-file header: %w\nCorrupted data is either caused by hardware issues or software bugs. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting.", err)
|
return fmt.Errorf("Detected data corruption while writing pack-file header: %w\nCorrupted data is either caused by hardware issues or software bugs. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ func (r *Repository) saveAndEncrypt(ctx context.Context, t restic.BlobType, data
|
|||||||
ciphertext = r.key.Seal(ciphertext, nonce, data, nil)
|
ciphertext = r.key.Seal(ciphertext, nonce, data, nil)
|
||||||
|
|
||||||
if err := r.verifyCiphertext(ciphertext, uncompressedLength, id); err != nil {
|
if err := r.verifyCiphertext(ciphertext, uncompressedLength, id); err != nil {
|
||||||
//nolint:revive // ignore linter warnings about error message spelling
|
//nolint:revive,staticcheck // ignore linter warnings about error message spelling
|
||||||
return 0, fmt.Errorf("Detected data corruption while saving blob %v: %w\nCorrupted blobs are either caused by hardware issues or software bugs. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting.", id, err)
|
return 0, fmt.Errorf("Detected data corruption while saving blob %v: %w\nCorrupted blobs are either caused by hardware issues or software bugs. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting.", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +500,7 @@ func (r *Repository) saveUnpacked(ctx context.Context, t restic.FileType, buf []
|
|||||||
ciphertext = r.key.Seal(ciphertext, nonce, p, nil)
|
ciphertext = r.key.Seal(ciphertext, nonce, p, nil)
|
||||||
|
|
||||||
if err := r.verifyUnpacked(ciphertext, t, buf); err != nil {
|
if err := r.verifyUnpacked(ciphertext, t, buf); err != nil {
|
||||||
//nolint:revive // ignore linter warnings about error message spelling
|
//nolint:revive,staticcheck // ignore linter warnings about error message spelling
|
||||||
return restic.ID{}, fmt.Errorf("Detected data corruption while saving file of type %v: %w\nCorrupted data is either caused by hardware issues or software bugs. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting.", t, err)
|
return restic.ID{}, fmt.Errorf("Detected data corruption while saving file of type %v: %w\nCorrupted data is either caused by hardware issues or software bugs. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting.", t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -413,7 +413,6 @@ func handleUnknownGenericAttributeFound(genericAttributeType GenericAttributeTyp
|
|||||||
|
|
||||||
// HandleAllUnknownGenericAttributesFound performs validations for all generic attributes of a node.
|
// HandleAllUnknownGenericAttributesFound performs validations for all generic attributes of a node.
|
||||||
// This is not used on windows currently because windows has handling for generic attributes.
|
// This is not used on windows currently because windows has handling for generic attributes.
|
||||||
// nolint:unused
|
|
||||||
func HandleAllUnknownGenericAttributesFound(attributes map[GenericAttributeType]json.RawMessage, warn func(msg string)) error {
|
func HandleAllUnknownGenericAttributesFound(attributes map[GenericAttributeType]json.RawMessage, warn func(msg string)) error {
|
||||||
for name := range attributes {
|
for name := range attributes {
|
||||||
handleUnknownGenericAttributeFound(name, warn)
|
handleUnknownGenericAttributeFound(name, warn)
|
||||||
|
|||||||
@@ -593,10 +593,11 @@ func shouldOverwrite(overwrite OverwriteBehavior, node *restic.Node, destination
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if overwrite == OverwriteIfNewer {
|
switch overwrite {
|
||||||
|
case OverwriteIfNewer:
|
||||||
// return if node is newer
|
// return if node is newer
|
||||||
return node.ModTime.After(fi.ModTime()), nil
|
return node.ModTime.After(fi.ModTime()), nil
|
||||||
} else if overwrite == OverwriteNever {
|
case OverwriteNever:
|
||||||
// file exists
|
// file exists
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func TestBucketWidth(t *testing.T) {
|
|||||||
|
|
||||||
b := e.buckets.Back().Value.(*rateBucket)
|
b := e.buckets.Back().Value.(*rateBucket)
|
||||||
rtest.Assert(t, b.totalBytes == 2, "b.totalBytes is %d, want 2", b.totalBytes)
|
rtest.Assert(t, b.totalBytes == 2, "b.totalBytes is %d, want 2", b.totalBytes)
|
||||||
rtest.Assert(t, b.end == when.Add(bucketWidth), "b.end is %v, want %v", b.end, when.Add(bucketWidth))
|
rtest.Assert(t, b.end.Equal(when.Add(bucketWidth)), "b.end is %v, want %v", b.end, when.Add(bucketWidth))
|
||||||
|
|
||||||
// Recording a byte outside the bucket width causes another bucket.
|
// Recording a byte outside the bucket width causes another bucket.
|
||||||
e.recordBytes(when.Add(bucketWidth), 1)
|
e.recordBytes(when.Add(bucketWidth), 1)
|
||||||
@@ -72,7 +72,7 @@ func TestBucketWidth(t *testing.T) {
|
|||||||
|
|
||||||
b = e.buckets.Back().Value.(*rateBucket)
|
b = e.buckets.Back().Value.(*rateBucket)
|
||||||
rtest.Assert(t, b.totalBytes == 1, "b.totalBytes is %d, want 1", b.totalBytes)
|
rtest.Assert(t, b.totalBytes == 1, "b.totalBytes is %d, want 1", b.totalBytes)
|
||||||
rtest.Assert(t, b.end == when.Add(2*bucketWidth), "b.end is %v, want %v", b.end, when.Add(bucketWidth))
|
rtest.Assert(t, b.end.Equal(when.Add(2*bucketWidth)), "b.end is %v, want %v", b.end, when.Add(bucketWidth))
|
||||||
|
|
||||||
// Recording a byte after a longer delay creates a sparse bucket list.
|
// Recording a byte after a longer delay creates a sparse bucket list.
|
||||||
e.recordBytes(when.Add(time.Hour+time.Millisecond), 7)
|
e.recordBytes(when.Add(time.Hour+time.Millisecond), 7)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
// GetProgressChannel returns a channel with which a single listener
|
// GetProgressChannel returns a channel with which a single listener
|
||||||
// receives each incoming signal.
|
// receives each incoming signal.
|
||||||
func GetProgressChannel() <-chan os.Signal {
|
func GetProgressChannel() <-chan os.Signal {
|
||||||
signals.Once.Do(func() {
|
signals.once.Do(func() {
|
||||||
signals.ch = make(chan os.Signal, 1)
|
signals.ch = make(chan os.Signal, 1)
|
||||||
setupSignals()
|
setupSignals()
|
||||||
})
|
})
|
||||||
@@ -19,6 +19,6 @@ func GetProgressChannel() <-chan os.Signal {
|
|||||||
// XXX The fact that signals is a single global variable means that only one
|
// XXX The fact that signals is a single global variable means that only one
|
||||||
// listener receives each incoming signal.
|
// listener receives each incoming signal.
|
||||||
var signals struct {
|
var signals struct {
|
||||||
ch chan os.Signal
|
ch chan os.Signal
|
||||||
sync.Once
|
once sync.Once
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user