Compare commits

..
Author SHA1 Message Date
omrzk c2c046c7b1 docs: keep S3 credentials out of Docker arguments (#22118) 2026-11-05 21:18:24 +00:00
ump45nose 0039a14381 global: mention the cache dir and user agent environment defaults (#22135) 2026-11-05 21:12:18 +00:00
John Maguire 7f6d8acb85 backend/b2: Support Multi-Bucket Application Keys (#22104) 2026-11-05 20:52:49 +00:00
Michael Eischer 068a324dcd Merge pull request #22124 from pujitha24/auto/issue-22120
prune: report failure to list pack files as a fatal error
2026-11-05 21:24:23 +01:00
Michael Eischer f515b862de prune: simplify test setup 2026-11-05 21:15:09 +01:00
Winfried Plappert 4619a31716 rewrite - more error exit tests (#22142) 2026-11-05 21:08:01 +01:00
Wei-Lun Li 9a0b9e0eb5 data: return an error for too large numbers in ParseDuration (#22163) 2026-11-05 19:36:49 +00:00
alexcastgonz b5d0152014 doc: list RESTIC_HTTP_USER_AGENT in the environment variables (#22123) 2026-11-05 19:26:31 +00:00
subomiandMichael Eischer 83a2726a30 s3: add option to disable AWS dual-stack endpoints (#22060)
Co-authored-by: Michael Eischer <michael.eischer@fau.de>
2026-11-05 19:07:43 +00:00
dependabot[bot] b5463d900d build(deps): bump github.com/klauspost/compress from 1.20.0 to 1.20.3 (#22159)
Signed-off-by: dependabot[bot] <support@github.com>
2026-11-05 20:06:09 +01:00
dependabot[bot] 4416b9fa09 build(deps): bump docker/login-action from 4.6.0 to 4.7.0 (#22155) 2026-11-05 20:03:54 +01:00
Pujitha Paladugu bba1b68082 prune: report failure to list pack files as a fatal error
Motivation: when listing pack files fails during prune (for example due
to a request timeout), the error was returned unwrapped and main printed
it with "%+v", which dumps a stack trace. As discussed in the issue, the
error needs one more level of wrapping before it can be treated as a
fatal error.

Approach: in decidePackAction, wrap an error from listing pack files
with errors.Fatalf("failed to list pack files: %v"). Errors that are
already fatal (e.g. ErrSizeNotMatching) and errors after context
cancellation are returned unchanged. The underlying error is preserved
via Unwrap. Retry log messages are unchanged; only the final error
output is shortened and says where the failure occurred.

Validation: `go test ./internal/repository/ -run Prune` and
`go test ./cmd/restic/ -run Prune` pass. The new test
TestPrunePackListError (backend whose pack list fails) fails without
the change and passes with it. I did not reproduce a real REST backend
timeout.

Report: https://github.com/restic/restic/issues/22120
Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
Assisted-by: claude-sonnet-5-5 (via Claude Code)
2026-10-18 12:58:49 -07:00
22 changed files with 158 additions and 20 deletions

No files matched your search

+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@v7 uses: actions/checkout@v7
- name: Log in to the Container registry - name: Log in to the Container registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
+2
View File
@@ -183,12 +183,14 @@ jobs:
RESTIC_TEST_OS_USERNAME: ${{ secrets.RESTIC_TEST_OS_USERNAME }} RESTIC_TEST_OS_USERNAME: ${{ secrets.RESTIC_TEST_OS_USERNAME }}
RESTIC_TEST_OS_PASSWORD: ${{ secrets.RESTIC_TEST_OS_PASSWORD }} RESTIC_TEST_OS_PASSWORD: ${{ secrets.RESTIC_TEST_OS_PASSWORD }}
RESTIC_TEST_OS_REGION_NAME: ${{ secrets.RESTIC_TEST_OS_REGION_NAME }} RESTIC_TEST_OS_REGION_NAME: ${{ secrets.RESTIC_TEST_OS_REGION_NAME }}
RESTIC_TEST_SWIFT: ${{ secrets.RESTIC_TEST_SWIFT }}
# fail if any of the following tests cannot be run # fail if any of the following tests cannot be run
RESTIC_TEST_DISALLOW_SKIP: "restic/backend/rest.TestBackendREST,\ RESTIC_TEST_DISALLOW_SKIP: "restic/backend/rest.TestBackendREST,\
restic/backend/sftp.TestBackendSFTP,\ restic/backend/sftp.TestBackendSFTP,\
restic/backend/s3.TestBackendSeaweedFS,\ restic/backend/s3.TestBackendSeaweedFS,\
restic/backend/rclone.TestBackendRclone,\ restic/backend/rclone.TestBackendRclone,\
restic/backend/s3.TestBackendS3,\ restic/backend/s3.TestBackendS3,\
restic/backend/swift.TestBackendSwift,\
restic/backend/b2.TestBackendB2,\ restic/backend/b2.TestBackendB2,\
restic/backend/gs.TestBackendGS,\ restic/backend/gs.TestBackendGS,\
restic/backend/azure.TestBackendAzure" restic/backend/azure.TestBackendAzure"
+1 -1
View File
@@ -59,7 +59,7 @@ var config = Config{
// see https://github.com/googleapis/google-cloud-go/issues/11448 // see https://github.com/googleapis/google-cloud-go/issues/11448
DefaultBuildTags: []string{"selfupdate", "disable_grpc_modules"}, // specify build tags which are always used DefaultBuildTags: []string{"selfupdate", "disable_grpc_modules"}, // specify build tags which are always used
Tests: []string{"./..."}, // tests to run Tests: []string{"./..."}, // tests to run
MinVersion: GoVersion{Major: 1, Minor: 26, Patch: 0}, // minimum Go version supported MinVersion: GoVersion{Major: 1, Minor: 26, Patch: 10}, // minimum Go version supported
} }
// Config configures the build. // Config configures the build.
+8
View File
@@ -0,0 +1,8 @@
Enhancement: Show a concise error when listing pack files fails during `prune`
When listing the pack files of a repository failed during `prune`, for
example due to a request timeout, restic printed the error together with a
stack trace. Restic now reports a short error message that states that
listing the pack files failed.
https://github.com/restic/restic/issues/22120
+11
View File
@@ -0,0 +1,11 @@
Enhancement: Add option to disable AWS S3 dual-stack endpoints
Restic used dual-stack endpoints for AWS regions that have them, with no way to
opt out. VPC interface and gateway endpoints do not support dual-stack, so a
repository reachable over a VPC endpoint could not be used.
Passing `-o s3.disable-dualstack=true` now keeps restic on the single-stack
endpoint.
https://github.com/restic/restic/issues/5189
https://github.com/restic/restic/pull/22060
+8
View File
@@ -0,0 +1,8 @@
Enhancement: Support Multi-Bucket Application Keys in the `b2` backend
The `b2` backend now supports Backblaze B2 Multi-Bucket Application Keys,
including single-bucket keys created through the multi-bucket API (for
example by the Backblaze Terraform provider).
https://github.com/restic/restic/issues/5741
https://github.com/restic/restic/pull/22104
+7
View File
@@ -0,0 +1,7 @@
Change: Require Go 1.26.10 or newer
Restic now requires Go 1.26.10 or newer to build, as the library used to
access the B2 backend requires it.
https://github.com/restic/restic/pull/22104
https://github.com/restic/restic/pull/22121
-5
View File
@@ -1,5 +0,0 @@
Change: Require Go 1.26 or newer
Building restic now requires Go 1.26 or newer.
https://github.com/restic/restic/pull/22121
+7
View File
@@ -0,0 +1,7 @@
Bugfix: Report an error for too large numbers in `--keep-within*` durations
Restic crashed with a stack trace when a number in a duration such as the one
passed to `restic forget --keep-within` did not fit into an integer. It now
reports an invalid argument instead.
https://github.com/restic/restic/pull/22163
@@ -352,3 +352,41 @@ func TestRewriteIncludeNothing(t *testing.T) {
rtest.Assert(t, snapsBefore[0] == snapsAfter[0], "snapshots should be identical but are %s and %s", rtest.Assert(t, snapsBefore[0] == snapsAfter[0], "snapshots should be identical but are %s and %s",
snapsBefore[0].Str(), snapsAfter[0].Str()) snapsBefore[0].Str(), snapsAfter[0].Str())
} }
func testRunRewriteOutput(t testing.TB, opts RewriteOptions, gopts global.Options, args []string) error {
t.Helper()
_, _, err := withCaptureStdoutStderr(t, gopts, func(ctx context.Context, gopts global.Options) error {
return runRewrite(ctx, opts, gopts, args, gopts.Term)
})
return err
}
func TestRewriteWrongMetadata(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
createBasicRewriteRepo(t, env)
opts := RewriteOptions{
Metadata: snapshotMetadataArgs{
Time: "2026-10-10 1x:2y:3z",
},
}
err := testRunRewriteOutput(t, opts, env.gopts, []string{})
rtest.Assert(t, err != nil && strings.Contains(err.Error(), "error in time option: parsing time"),
"expected time string related errors, got %v", err)
}
func TestRewriteWrongExcludePattern(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
createBasicRewriteRepo(t, env)
opts := RewriteOptions{
ExcludePatternOptions: filter.ExcludePatternOptions{
Excludes: []string{"a["},
},
}
err := testRunRewriteOutput(t, opts, env.gopts, []string{})
rtest.Assert(t, err != nil && strings.Contains(err.Error(), "--exclude: invalid pattern"),
"expected '--exclude: invalid pattern', got %v", err)
}
+1 -1
View File
@@ -305,7 +305,7 @@ From source
*********** ***********
restic is written in the Go programming language and you need at least restic is written in the Go programming language and you need at least
Go version 1.26. Building restic may also work with older versions of Go, Go version 1.26.10. Building restic may also work with older versions of Go,
but that's not supported. See the `Getting but that's not supported. See the `Getting
started <https://go.dev/doc/install>`__ guide of the Go project for started <https://go.dev/doc/install>`__ guide of the Go project for
instructions how to install Go. instructions how to install Go.
+13
View File
@@ -249,6 +249,14 @@ while creating the bucket.
$ export AWS_ACCESS_KEY_ID=<MY_ACCESS_KEY> $ export AWS_ACCESS_KEY_ID=<MY_ACCESS_KEY>
$ export AWS_SECRET_ACCESS_KEY=<MY_SECRET_ACCESS_KEY> $ export AWS_SECRET_ACCESS_KEY=<MY_SECRET_ACCESS_KEY>
Restic can also read credentials from an AWS shared credentials file. Set
``AWS_SHARED_CREDENTIALS_FILE`` to its path, or use the default location at
``~/.aws/credentials``. When running restic in a container, mount the file
read-only and set ``AWS_SHARED_CREDENTIALS_FILE`` to the path inside the
container. Avoid passing secret values in ``docker run -e NAME=value``
arguments, where they can be exposed in process listings. Docker's
``--env-file`` option also keeps the values out of command-line arguments.
When using temporary credentials make sure to include the session token via When using temporary credentials make sure to include the session token via
the environment variable ``AWS_SESSION_TOKEN``. the environment variable ``AWS_SESSION_TOKEN``.
@@ -308,6 +316,11 @@ To select between path-style and virtual-hosted access, the extended option
- ``dns``: Use virtual-hosted-style bucket access - ``dns``: Use virtual-hosted-style bucket access
- ``path``: Use path-style bucket access - ``path``: Use path-style bucket access
Amazon's dual-stack endpoints are used by default for AWS regions that have
them. VPC interface and gateway endpoints do not support dual-stack, so if
restic cannot reach your bucket from inside a VPC, pass
``-o s3.disable-dualstack=true``.
Certain S3-compatible servers do not properly implement the ``ListObjectsV2`` API, Certain S3-compatible servers do not properly implement the ``ListObjectsV2`` API,
most notably Ceph versions before v14.2.5. On these backends, as a temporary most notably Ceph versions before v14.2.5. On these backends, as a temporary
workaround, you can provide the ``-o s3.list-objects-v1=true`` option to use the workaround, you can provide the ``-o s3.list-objects-v1=true`` option to use the
+1
View File
@@ -37,6 +37,7 @@ override the corresponding environment variables. For example, ``-r`` (or
RESTIC_KEY_HINT ID of key to try decrypting first, before other keys RESTIC_KEY_HINT ID of key to try decrypting first, before other keys
RESTIC_CACERT Location(s) of certificate file(s), comma separated if multiple (overridden by --cacert) RESTIC_CACERT Location(s) of certificate file(s), comma separated if multiple (overridden by --cacert)
RESTIC_TLS_CLIENT_CERT Location of TLS client certificate and private key (overridden by --tls-client-cert) RESTIC_TLS_CLIENT_CERT Location of TLS client certificate and private key (overridden by --tls-client-cert)
RESTIC_HTTP_USER_AGENT HTTP user agent for outgoing HTTP requests (overridden by --http-user-agent)
RESTIC_CACHE_DIR Location of the cache directory RESTIC_CACHE_DIR Location of the cache directory
RESTIC_COMPRESSION Compression mode (only available for repository format version 2) RESTIC_COMPRESSION Compression mode (only available for repository format version 2)
RESTIC_HOST Only consider snapshots for this host / Set the hostname for the snapshot manually (overridden by --host) RESTIC_HOST Only consider snapshots for this host / Set the hostname for the snapshot manually (overridden by --host)
+3 -5
View File
@@ -1,8 +1,6 @@
module github.com/restic/restic module github.com/restic/restic
go 1.26.0 go 1.26.10
toolchain go1.26.9
// keep the old behavior for reparse points on windows until handling reparse points has been improved in restic // keep the old behavior for reparse points on windows until handling reparse points has been improved in restic
// https://forum.restic.net/t/windows-junction-backup-with-go1-23-or-later/8940 // https://forum.restic.net/t/windows-junction-backup-with-go1-23-or-later/8940
@@ -13,7 +11,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.1 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.1
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.8.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.8.1
github.com/Backblaze/blazer v0.7.2 github.com/Backblaze/blazer v0.9.0
github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/go-winio v0.6.2
github.com/ProtonMail/go-crypto v1.5.2 github.com/ProtonMail/go-crypto v1.5.2
github.com/anacrolix/fuse v0.3.1 github.com/anacrolix/fuse v0.3.1
@@ -23,7 +21,7 @@ require (
github.com/go-ole/go-ole v1.3.0 github.com/go-ole/go-ole v1.3.0
github.com/google/go-cmp v0.7.0 github.com/google/go-cmp v0.7.0
github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/klauspost/compress v1.20.0 github.com/klauspost/compress v1.20.3
github.com/minio/minio-go/v7 v7.3.0 github.com/minio/minio-go/v7 v7.3.0
github.com/ncw/swift/v2 v2.0.5 github.com/ncw/swift/v2 v2.0.5
github.com/peterbourgon/unixtransport v0.0.7 github.com/peterbourgon/unixtransport v0.0.7
+4 -4
View File
@@ -36,8 +36,8 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJ
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.8.0 h1:Nljr4q1GRA/5vCrMONS+g4u4LRHNgOXVSh3O43J2CnI= github.com/AzureAD/microsoft-authentication-library-for-go v1.8.0 h1:Nljr4q1GRA/5vCrMONS+g4u4LRHNgOXVSh3O43J2CnI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.8.0/go.mod h1:Y33QHnf0FfdVewFFISOGe20mkZbxX4H839o955/PoeI= github.com/AzureAD/microsoft-authentication-library-for-go v1.8.0/go.mod h1:Y33QHnf0FfdVewFFISOGe20mkZbxX4H839o955/PoeI=
github.com/Backblaze/blazer v0.7.2 h1:UWNHMLB+Nf+UmbO2qkVvgriODLEMz4kIyr2Hm+DVXQM= github.com/Backblaze/blazer v0.9.0 h1:413rZHO8Vnpfjygrfxt8AO56LD6lE4w334MZIpnxdAs=
github.com/Backblaze/blazer v0.7.2/go.mod h1:T4y3EYa9IQ5J0PKc/C/J8/CEnSd3qa/lgNw938wZg10= github.com/Backblaze/blazer v0.9.0/go.mod h1:/JlJELHVlJWBwHknmVqQ92zYyVm0s4EI+Cn3XU6IgCc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.35.0 h1:bN1gA3of5bXtbnLsRPrwfmbbe7A5UWFlcTHseujLnpc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.35.0 h1:bN1gA3of5bXtbnLsRPrwfmbbe7A5UWFlcTHseujLnpc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.35.0/go.mod h1:Yj5vHEz/aAepZGliRJsA6uvHAVAQyEwajq9ORCHPxzM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.35.0/go.mod h1:Yj5vHEz/aAepZGliRJsA6uvHAVAQyEwajq9ORCHPxzM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.57.0 h1:jLdiS1vO+XJFyDSWRHBx56r4s/NNtcl5J6KyCcWUX/w= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.57.0 h1:jLdiS1vO+XJFyDSWRHBx56r4s/NNtcl5J6KyCcWUX/w=
@@ -141,8 +141,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= github.com/klauspost/compress v1.20.3 h1:zWNoFqq/lSuYQRim3dUXlXeA0IqwuZGicdG5ZTfY5j4=
github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/compress v1.20.3/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw=
github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
+1
View File
@@ -32,6 +32,7 @@ type Config struct {
Region string `option:"region" help:"set region"` Region string `option:"region" help:"set region"`
BucketLookup string `option:"bucket-lookup" help:"bucket lookup style: 'auto', 'dns', or 'path'"` BucketLookup string `option:"bucket-lookup" help:"bucket lookup style: 'auto', 'dns', or 'path'"`
ListObjectsV1 bool `option:"list-objects-v1" help:"use deprecated V1 api for ListObjects calls"` ListObjectsV1 bool `option:"list-objects-v1" help:"use deprecated V1 api for ListObjects calls"`
DisableDualstack bool `option:"disable-dualstack" help:"do not use AWS S3 dual-stack endpoints, which VPC endpoints do not support"`
UnsafeAnonymousAuth bool `option:"unsafe-anonymous-auth" help:"use anonymous authentication"` UnsafeAnonymousAuth bool `option:"unsafe-anonymous-auth" help:"use anonymous authentication"`
// For testing only // For testing only
+6
View File
@@ -89,6 +89,12 @@ func open(cfg Config, rt http.RoundTripper) (*s3, error) {
return nil, errors.Wrap(err, "minio.New") return nil, errors.Wrap(err, "minio.New")
} }
if cfg.DisableDualstack {
// VPC interface and gateway endpoints have no dual-stack support, so
// resolving to one makes the bucket unreachable from within the VPC
client.SetS3EnableDualstack(false)
}
be := &s3{ be := &s3{
client: client, client: client,
cfg: cfg, cfg: cfg,
+1 -1
View File
@@ -65,7 +65,7 @@ func nextNumber(input string) (num int, rest string, err error) {
num, err = strconv.Atoi(n) num, err = strconv.Atoi(n)
if err != nil { if err != nil {
panic(err) return 0, input, err
} }
if negative { if negative {
+5
View File
@@ -40,6 +40,9 @@ func TestNextNumber(t *testing.T) {
{ {
input: "5", num: 5, rest: "", input: "5", num: 5, rest: "",
}, },
{
input: "99999999999999999999999999y", num: 0, rest: "99999999999999999999999999y", err: true,
},
} }
for _, test := range tests { for _, test := range tests {
@@ -82,6 +85,8 @@ func TestParseDuration(t *testing.T) {
{input: "1y4m3w1d", err: true}, {input: "1y4m3w1d", err: true},
{input: "s", err: true}, {input: "s", err: true},
{input: "\xdf\x80", err: true}, // NKO DIGIT ZERO; we want ASCII digits {input: "\xdf\x80", err: true}, // NKO DIGIT ZERO; we want ASCII digits
{input: "99999999999999999999999999y", err: true},
{input: "1y-99999999999999999999999999d", err: true},
} }
for _, test := range tests { for _, test := range tests {
+2 -2
View File
@@ -99,7 +99,7 @@ func (opts *Options) AddFlags(f *pflag.FlagSet) {
f.BoolVar(&opts.NoLock, "no-lock", false, "do not lock the repository, this allows some operations on read-only repositories") f.BoolVar(&opts.NoLock, "no-lock", false, "do not lock the repository, this allows some operations on read-only repositories")
f.DurationVar(&opts.RetryLock, "retry-lock", 0, "retry to lock the repository if it is already locked, takes a value like 5m or 2h (default: no retries)") f.DurationVar(&opts.RetryLock, "retry-lock", 0, "retry to lock the repository if it is already locked, takes a value like 5m or 2h (default: no retries)")
f.BoolVarP(&opts.JSON, "json", "", false, "set output mode to JSON for commands that support it") f.BoolVarP(&opts.JSON, "json", "", false, "set output mode to JSON for commands that support it")
f.StringVar(&opts.CacheDir, "cache-dir", "", "set the cache `directory`. (default: use system default cache directory)") f.StringVar(&opts.CacheDir, "cache-dir", "", "set the cache `directory`. (default: use system default cache directory or $RESTIC_CACHE_DIR)")
f.BoolVar(&opts.NoCache, "no-cache", false, "do not use a local cache") f.BoolVar(&opts.NoCache, "no-cache", false, "do not use a local cache")
f.StringSliceVar(&opts.RootCertFilenames, "cacert", nil, "`file` to load root certificates from (default: use system certificates or $RESTIC_CACERT)") f.StringSliceVar(&opts.RootCertFilenames, "cacert", nil, "`file` to load root certificates from (default: use system certificates or $RESTIC_CACERT)")
f.StringVar(&opts.TLSClientCertKeyFilename, "tls-client-cert", "", "path to a `file` containing PEM encoded TLS client certificate and private key (default: $RESTIC_TLS_CLIENT_CERT)") f.StringVar(&opts.TLSClientCertKeyFilename, "tls-client-cert", "", "path to a `file` containing PEM encoded TLS client certificate and private key (default: $RESTIC_TLS_CLIENT_CERT)")
@@ -114,7 +114,7 @@ func (opts *Options) AddFlags(f *pflag.FlagSet) {
const packSizeFlag = "pack-size" const packSizeFlag = "pack-size"
f.UintVar(&opts.PackSize, packSizeFlag, 0, "set target pack `size` in MiB, created pack files may be larger (default: $RESTIC_PACK_SIZE)") f.UintVar(&opts.PackSize, packSizeFlag, 0, "set target pack `size` in MiB, created pack files may be larger (default: $RESTIC_PACK_SIZE)")
f.StringSliceVarP(&opts.Options, "option", "o", []string{}, "set extended option (`key=value`, can be specified multiple times)") f.StringSliceVarP(&opts.Options, "option", "o", []string{}, "set extended option (`key=value`, can be specified multiple times)")
f.StringVar(&opts.HTTPUserAgent, "http-user-agent", "", "set a http user agent for outgoing http requests") f.StringVar(&opts.HTTPUserAgent, "http-user-agent", "", "set a http user agent for outgoing http requests (default: $RESTIC_HTTP_USER_AGENT)")
f.DurationVar(&opts.StuckRequestTimeout, "stuck-request-timeout", 5*time.Minute, "`duration` after which to retry stuck requests") f.DurationVar(&opts.StuckRequestTimeout, "stuck-request-timeout", 5*time.Minute, "`duration` after which to retry stuck requests")
opts.Repo = os.Getenv("RESTIC_REPOSITORY") opts.Repo = os.Getenv("RESTIC_REPOSITORY")
+3
View File
@@ -467,8 +467,11 @@ func decidePackAction(ctx context.Context, opts PruneOptions, repo *Repository,
bar.Done() bar.Done()
if err != nil { if err != nil {
if errors.IsFatal(err) || ctx.Err() != nil {
return PrunePlan{}, err return PrunePlan{}, err
} }
return PrunePlan{}, errors.Fatalf("failed to list pack files: %v", err)
}
// At this point indexPacks contains only missing packs! // At this point indexPacks contains only missing packs!
+35
View File
@@ -2,12 +2,16 @@ package repository_test
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"math" "math"
"math/rand" "math/rand"
"strings"
"testing" "testing"
"time" "time"
"github.com/restic/restic/internal/backend"
resticerrors "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/repository/pack" "github.com/restic/restic/internal/repository/pack"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
@@ -191,3 +195,34 @@ func TestPruneSmall(t *testing.T) {
rtest.Equals(t, lenPackfilesBefore > lenPackfilesAfter, true, rtest.Equals(t, lenPackfilesBefore > lenPackfilesAfter, true,
fmt.Sprintf("the number packfiles before %d and after repack %d", lenPackfilesBefore, lenPackfilesAfter)) fmt.Sprintf("the number packfiles before %d and after repack %d", lenPackfilesBefore, lenPackfilesAfter))
} }
type failingListBackend struct {
backend.Backend
err error
}
func (b *failingListBackend) List(ctx context.Context, t backend.FileType, fn func(backend.FileInfo) error) error {
if t == backend.PackFile {
return b.err
}
return b.Backend.List(ctx, t, fn)
}
func TestPrunePackListError(t *testing.T) {
_, _, be := repository.TestRepositoryWithVersion(t, 0)
listErr := errors.New("request timeout")
repo := repository.TestOpenBackend(t, &failingListBackend{Backend: be, err: listErr})
rtest.OK(t, repo.LoadIndex(context.TODO(), restic.NoopTerminalCounterFactory))
_, err := repository.PlanPrune(context.TODO(), repository.PruneOptions{
MaxRepackBytes: math.MaxUint64,
MaxUnusedBytes: func(used uint64) uint64 { return used },
}, repo, func(ctx context.Context, repo restic.Repository, usedBlobs restic.FindBlobSet) error {
return nil
}, restic.NewNoopPrinter())
rtest.Assert(t, err != nil, "expected an error")
rtest.Assert(t, resticerrors.IsFatal(err), "expected a fatal error, got %v", err)
rtest.Assert(t, errors.Is(err, listErr), "expected error to wrap the list error, got %v", err)
rtest.Assert(t, strings.Contains(err.Error(), "failed to list pack files"), "unexpected message %q", err)
}