From 5d182ed1abce54d81e20fe5d0f0d103952c7d93f Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Mon, 31 Mar 2025 18:04:54 +0200 Subject: [PATCH 01/51] forget: fix ignored RESTIC_HOST environment variable --- changelog/unreleased/issue-5325 | 7 +++++++ cmd/restic/cmd_forget.go | 3 ++- cmd/restic/cmd_forget_test.go | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/issue-5325 diff --git a/changelog/unreleased/issue-5325 b/changelog/unreleased/issue-5325 new file mode 100644 index 000000000..883391a0a --- /dev/null +++ b/changelog/unreleased/issue-5325 @@ -0,0 +1,7 @@ +Bugfix: Correctly handle `RESTIC_HOST` in `forget` command + +The `forget` command did not use the host name from the `RESTIC_HOST` +environment variable. This has been fixed. + +https://github.com/restic/restic/issues/5325 +https://github.com/restic/restic/pull/5327 diff --git a/cmd/restic/cmd_forget.go b/cmd/restic/cmd_forget.go index 2bfacc4de..3a410e223 100644 --- a/cmd/restic/cmd_forget.go +++ b/cmd/restic/cmd_forget.go @@ -137,13 +137,14 @@ func (opts *ForgetOptions) AddFlags(f *pflag.FlagSet) { f.Var(&opts.KeepTags, "keep-tag", "keep snapshots with this `taglist` (can be specified multiple times)") f.BoolVar(&opts.UnsafeAllowRemoveAll, "unsafe-allow-remove-all", false, "allow deleting all snapshots of a snapshot group") - initMultiSnapshotFilter(f, &opts.SnapshotFilter, false) f.StringArrayVar(&opts.Hosts, "hostname", nil, "only consider snapshots with the given `hostname` (can be specified multiple times)") err := f.MarkDeprecated("hostname", "use --host") if err != nil { // MarkDeprecated only returns an error when the flag is not found panic(err) } + // must be defined after `--hostname` to not override the default value from the environment + initMultiSnapshotFilter(f, &opts.SnapshotFilter, false) f.BoolVarP(&opts.Compact, "compact", "c", false, "use compact output format") opts.GroupBy = restic.SnapshotGroupByOptions{Host: true, Path: true} diff --git a/cmd/restic/cmd_forget_test.go b/cmd/restic/cmd_forget_test.go index ddeef028a..0d60f7445 100644 --- a/cmd/restic/cmd_forget_test.go +++ b/cmd/restic/cmd_forget_test.go @@ -5,6 +5,7 @@ import ( "github.com/restic/restic/internal/restic" rtest "github.com/restic/restic/internal/test" + "github.com/spf13/pflag" ) func TestForgetPolicyValues(t *testing.T) { @@ -92,3 +93,10 @@ func TestForgetOptionValues(t *testing.T) { } } } + +func TestForgetHostnameDefaulting(t *testing.T) { + t.Setenv("RESTIC_HOST", "testhost") + opts := ForgetOptions{} + opts.AddFlags(pflag.NewFlagSet("test", pflag.ContinueOnError)) + rtest.Equals(t, []string{"testhost"}, opts.Hosts) +} From 3d4fb876f4a0d2fd5fa9beb7b587ad03c9476be5 Mon Sep 17 00:00:00 2001 From: Gilbert Gilb's Date: Thu, 27 Mar 2025 21:20:50 +0100 Subject: [PATCH 02/51] docs: fix unit for S3 restore timeout "d" is not a valid unit. --- doc/faq.rst | 2 +- internal/backend/s3/config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/faq.rst b/doc/faq.rst index 3b62f641d..0df4aa0ea 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -253,7 +253,7 @@ Archive** storage classes is available: .. code-block:: console $ restic backup -o s3.storage-class=GLACIER somedir/ - $ RESTIC_FEATURES=s3-restore restic restore -o s3.enable-restore=1 -o s3.restore-days=7 -o s3.restore-timeout=1d latest + $ RESTIC_FEATURES=s3-restore restic restore -o s3.enable-restore=1 -o s3.restore-days=7 -o s3.restore-timeout=24h latest **Notes:** diff --git a/internal/backend/s3/config.go b/internal/backend/s3/config.go index 77f27408e..365b16bf1 100644 --- a/internal/backend/s3/config.go +++ b/internal/backend/s3/config.go @@ -26,7 +26,7 @@ type Config struct { EnableRestore bool `option:"enable-restore" help:"restore objects from GLACIER or DEEP_ARCHIVE storage classes (default: false, requires \"s3-restore\" feature flag)"` RestoreDays int `option:"restore-days" help:"lifetime in days of restored object (default: 7)"` - RestoreTimeout time.Duration `option:"restore-timeout" help:"maximum time to wait for objects transition (default: 1d)"` + RestoreTimeout time.Duration `option:"restore-timeout" help:"maximum time to wait for objects transition (default: 24h)"` RestoreTier string `option:"restore-tier" help:"Retrieval tier at which the restore will be processed. (Standard, Bulk or Expedited) (default: Standard)"` Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"` From 1fe6fbc4b82d39f0218c6d7f0639f2c095d2f5f9 Mon Sep 17 00:00:00 2001 From: Mohammad Javad Naderi Date: Sat, 29 Mar 2025 12:40:47 +0330 Subject: [PATCH 03/51] doc: fix typos --- doc/030_preparing_a_new_repo.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/030_preparing_a_new_repo.rst b/doc/030_preparing_a_new_repo.rst index 34a0cd8bc..ac9657460 100644 --- a/doc/030_preparing_a_new_repo.rst +++ b/doc/030_preparing_a_new_repo.rst @@ -854,6 +854,6 @@ with an empty password, use the following command. restic init --insecure-no-password -The ``init`` and ``copy`` command also support the option ``--from-insecure-no-password`` +The ``init`` and ``copy`` commands also support the option ``--from-insecure-no-password`` which applies to the source repository. The ``key add`` and ``key passwd`` commands -include the ``--new-insecure-no-password`` option to add or set and empty password. +include the ``--new-insecure-no-password`` option to add or set an empty password. From e9ae67c9685eed9cb9a5e4da719420b3047e60c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Apr 2025 20:54:17 +0200 Subject: [PATCH 04/51] build(deps): bump docker/login-action from 3.3.0 to 3.4.0 (#5333) Bumps [docker/login-action](https://github.com/docker/login-action) from 3.3.0 to 3.4.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/9780b0c442fbb1117ed29e0efdff1e18412f7567...74a5d142397b4f367a81961eba4e8cd7edddf772) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 3.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5e9713618..5156228ba 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v4 - name: Log in to the Container registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} From a22b9d573511479db0a78686db3e79fdb3cbaf3f Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Wed, 2 Apr 2025 21:10:40 +0200 Subject: [PATCH 05/51] update direct dependencies (#5340) --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 1e1ba52f2..da26ac878 100644 --- a/go.mod +++ b/go.mod @@ -21,33 +21,33 @@ require ( github.com/google/go-cmp v0.7.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/klauspost/compress v1.18.0 - github.com/minio/minio-go/v7 v7.0.88 + github.com/minio/minio-go/v7 v7.0.89 github.com/ncw/swift/v2 v2.0.3 github.com/peterbourgon/unixtransport v0.0.4 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.7.0 - github.com/pkg/sftp v1.13.8 + github.com/pkg/sftp v1.13.9 github.com/pkg/xattr v0.4.10 github.com/restic/chunker v0.4.0 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 go.uber.org/automaxprocs v1.6.0 golang.org/x/crypto v0.36.0 - golang.org/x/net v0.37.0 + golang.org/x/net v0.38.0 golang.org/x/oauth2 v0.28.0 golang.org/x/sync v0.12.0 golang.org/x/sys v0.31.0 golang.org/x/term v0.30.0 golang.org/x/text v0.23.0 golang.org/x/time v0.11.0 - google.golang.org/api v0.227.0 + google.golang.org/api v0.228.0 ) require ( cel.dev/expr v0.19.2 // indirect cloud.google.com/go v0.118.3 // indirect cloud.google.com/go/auth v0.15.0 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/iam v1.4.1 // indirect cloud.google.com/go/monitoring v1.24.0 // indirect @@ -74,7 +74,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/kr/fs v0.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/minio/crc64nvme v1.0.1 // indirect @@ -96,6 +96,6 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect google.golang.org/grpc v1.71.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 54770e377..0dd0741b6 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ cloud.google.com/go v0.118.3 h1:jsypSnrE/w4mJysioGdMBg4MiW/hHx/sArFpaBWHdME= cloud.google.com/go v0.118.3/go.mod h1:Lhs3YLnBlwJ4KA6nuObNMZ/fCbOQBPuWKPoE0Wa/9Vc= cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= -cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= -cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/iam v1.4.1 h1:cFC25Nv+u5BkTR/BT1tXdoF2daiVbZ1RLx2eqfQ9RMM= @@ -136,8 +136,8 @@ github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeW github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -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/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -155,8 +155,8 @@ github.com/minio/crc64nvme v1.0.1 h1:DHQPrYPdqK7jQG/Ls5CTBZWeex/2FMS3G5XGkycuFrY github.com/minio/crc64nvme v1.0.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.88 h1:v8MoIJjwYxOkehp+eiLIuvXk87P2raUtoU5klrAAshs= -github.com/minio/minio-go/v7 v7.0.88/go.mod h1:33+O8h0tO7pCeCWwBVa07RhVVfB/3vS4kEX7rwYKmIg= +github.com/minio/minio-go/v7 v7.0.89 h1:hx4xV5wwTUfyv8LarhJAwNecnXpoTsj9v3f3q/ZkiJU= +github.com/minio/minio-go/v7 v7.0.89/go.mod h1:2rFnGAp02p7Dddo1Fq4S2wYOfpF0MUTSeLTRC90I204= github.com/ncw/swift/v2 v2.0.3 h1:8R9dmgFIWs+RiVlisCEfiQiik1hjuR0JnOkLxaP9ihg= github.com/ncw/swift/v2 v2.0.3/go.mod h1:cbAO76/ZwcFrFlHdXPjaqWZ9R7Hdar7HpjRXBfbjigk= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= @@ -171,8 +171,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= -github.com/pkg/sftp v1.13.8 h1:Xt7eJ/xqXv7s0VuzFw7JXhZj6Oc1zI6l4GK8KP9sFB0= -github.com/pkg/sftp v1.13.8/go.mod h1:DmvEkvKE2lshEeuo2JMp06yqcx9HVnR7e3zqQl42F3U= +github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw= +github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA= github.com/pkg/xattr v0.4.10 h1:Qe0mtiNFHQZ296vRgUjRCoPHPqH7VdTOrZx3g0T+pGA= github.com/pkg/xattr v0.4.10/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= @@ -266,8 +266,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -339,8 +339,8 @@ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxb golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.227.0 h1:QvIHF9IuyG6d6ReE+BNd11kIB8hZvjN8Z5xY5t21zYc= -google.golang.org/api v0.227.0/go.mod h1:EIpaG6MbTgQarWF5xJvX0eOJPK9n/5D4Bynb9j2HXvQ= +google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs= +google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4= google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= @@ -349,8 +349,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -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= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From f61cf4a1e5d8bebc19e8670b0186042450138a60 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Wed, 2 Apr 2025 21:12:43 +0200 Subject: [PATCH 06/51] docs: fix typos in developer information (#5329) --- doc/developer_information.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/doc/developer_information.rst b/doc/developer_information.rst index a2d7adfe1..ce28317c6 100644 --- a/doc/developer_information.rst +++ b/doc/developer_information.rst @@ -18,7 +18,7 @@ depends on the following things: * The path to the Go workspace (``GOPATH=/home/build/go``) * Other environment variables (mostly ``$GOOS``, ``$GOARCH``, ``$CGO_ENABLED``) -In addition, The compressed ZIP files for Windows depends on the modification +In addition, the compressed ZIP files for Windows depends on the modification timestamp and filename of the binary contained in it. In order to reproduce the exact same ZIP file every time, we update the timestamp of the file ``VERSION`` in the source code archive and set the timezone to Europe/Berlin. @@ -52,10 +52,10 @@ In the following example, we'll use the file ``restic-0.14.0.tar.gz`` and Go $ go version go version go1.19 linux/amd64 - $ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-s -w" -tags selfupdate -o restic_linux_amd64 ./cmd/restic + $ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-s -w" -tags selfupdate,disable_grpc_modules -o restic_linux_amd64 ./cmd/restic $ bzip2 restic_linux_amd64 - $ GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-s -w" -tags selfupdate -o restic_0.14.0_windows_amd64.exe ./cmd/restic + $ GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-s -w" -tags selfupdate,disable_grpc_modules -o restic_0.14.0_windows_amd64.exe ./cmd/restic $ touch --reference VERSION restic_0.14.0_windows_amd64.exe $ TZ=Europe/Berlin zip -q -X restic_0.14.0_windows_amd64.zip restic_0.14.0_windows_amd64.exe @@ -66,7 +66,7 @@ The released binaries for restic are built using a Docker container. You can find it on `Docker Hub `__ as ``restic/builder``, the ``Dockerfile`` and instructions on how to build the container can be found in the `GitHub repository -`__ +`__. The container serves the following goals: * Have a very controlled environment which is independent from the local system @@ -93,7 +93,7 @@ The following steps are necessary to build the binaries: mkdir output -3. Mount the source code and the output directory in the container and run the default command, which starts ``helpers/build-release-binaries/main.go``: +4. Mount the source code and the output directory in the container and run the default command, which starts ``helpers/build-release-binaries/main.go``: .. code:: @@ -103,7 +103,7 @@ The following steps are necessary to build the binaries: restic/builder \ go run helpers/build-release-binaries/main.go --version 0.14.0 -4. If anything goes wrong, you can enable debug output like this: +5. If anything goes wrong, you can enable debug output like this: .. code:: @@ -114,7 +114,7 @@ The following steps are necessary to build the binaries: go run helpers/build-release-binaries/main.go --version 0.14.0 --verbose Verifying SLSA Provenance for GHCR Docker Images -******************************************* +************************************************ Our Docker images in the GitHub Container Registry (GHCR) are built with SLSA (Supply-chain Levels for Software Artifacts) provenance. @@ -131,9 +131,8 @@ To verify this provenance: --source-uri github.com/restic/restic \ @ - Replace `` with the Git tag of the release you're verifying, `` - with the full name of the Docker image (including the registry), and `` - with the SHA256 digest of the image. + Replace `` with the full name of the Docker image (including the registry), + and `` with the SHA256 digest of the image. 3. If the verification is successful, you'll see output indicating that the provenance is valid. @@ -146,7 +145,7 @@ Verifying the Official Binaries To verify the official binaries, you can either build them yourself using the above instructions or use the ``helpers/verify-release-binaries.sh`` script from the restic -repository. Run it as ``helpers/verify-release-binaries.sh restic_version go_version``. +repository. Run it as ``helpers/verify-release-binaries.sh $restic_version $go_version``. The specified go compiler version must match the one used to build the official binaries. For example, for restic 0.16.2 the command would be ``helpers/verify-release-binaries.sh 0.16.2 1.21.3``. From aaa48e765ae69de64915356349bae1a5e074d39d Mon Sep 17 00:00:00 2001 From: Markus Hansmair Date: Wed, 16 Apr 2025 09:36:48 +0200 Subject: [PATCH 07/51] doc: typo & minor rewording in 'Removing files from snapshots' --- doc/045_working_with_repos.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/045_working_with_repos.rst b/doc/045_working_with_repos.rst index d5f2240b8..5fadac637 100644 --- a/doc/045_working_with_repos.rst +++ b/doc/045_working_with_repos.rst @@ -297,7 +297,7 @@ Note that it is not possible to change the chunker parameters of an existing rep Removing files from snapshots ============================= -Snapshots sometimes turn out to include more files that intended. Instead of +Snapshots sometimes turn out to include more files than intended. Instead of removing the snapshots entirely and running the corresponding backup commands again (which is not always practical after the fact) it is possible to remove the unwanted files from affected snapshots by rewriting them using the @@ -338,8 +338,8 @@ the only fields added are ``TotalFilesProcessed`` and ``TotalBytesProcessed``. By default, the ``rewrite`` command will keep the original snapshots and create new ones for every snapshot which was modified during rewriting. The new -snapshots are marked with the tag ``rewrite`` to differentiate them from the -original, rewritten snapshots. +snapshots are marked with the tag ``rewrite`` to distinguish them from the +original, untouched snapshots. Alternatively, you can use the ``--forget`` option to immediately remove the original snapshots. In this case, no tag is added to the new snapshots. Please From 72d70d94f97d436f2ce63bdb3ed4a8ac37d075ff Mon Sep 17 00:00:00 2001 From: Samuel Chambers Date: Sun, 11 May 2025 14:02:07 -0400 Subject: [PATCH 08/51] updated doc/faq.rst_commitsSquashed --- doc/faq.rst | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/doc/faq.rst b/doc/faq.rst index 0df4aa0ea..a235ea916 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -110,9 +110,8 @@ How can I specify encryption passwords automatically? When you run ``restic backup``, you need to enter the passphrase on the console. This is not very convenient for automated backups, so you can also provide the password through the ``--password-file`` option, or one of -the environment variables ``RESTIC_PASSWORD`` or ``RESTIC_PASSWORD_FILE``. -A discussion is in progress over implementing unattended backups happens in -:issue:`533`. +the environment variables: ``RESTIC_PASSWORD``, ``RESTIC_PASSWORD_FILE``, +or ``RESTIC_PASSWORD_COMMAND``. .. important:: Be careful how you set the environment; using the env command, a `system()` call or using inline shell @@ -124,10 +123,33 @@ A discussion is in progress over implementing unattended backups happens in `accessible only to that user`_. Please make sure that the permissions on the files where the password is eventually stored are safe (e.g. `0600` and owned by - root). + root). Note also that ``RESTIC_PASSWORD_COMMAND`` is + safe because it does not export the password itself to + the environment. .. _accessible only to that user: https://security.stackexchange.com/questions/14000/environment-variable-accessibility-in-linux/14009#14009 +On platforms with an available keychain, keyring or similar secret store, a +user can add and then dynamically retrieve passwords, cloud credentials, +repository paths, or any other data deemed sensitive. Here's an example of +part of a shell script using the `built-in`_ ``security`` command on macOS +to retrieve credentials from the system's Keychain before running various +``restic`` commands: + +.. _built-in: https://ss64.com/mac/security.html + +:: + + export GOOGLE_PROJECT_ID=$(security find-generic-password -a resticGCS -s restic_project_ID -w) + + export GOOGLE_APPLICATION_CREDENTIALS=$(security find-generic-password -a resticGCS -s restic_key -w) + + export RESTIC_REPOSITORY=$(security find-generic-password -a resticGCS -s restic_repo_path -w) + + export RESTIC_PASSWORD_COMMAND='security find-generic-password -a resticGCS -s restic_pwd -w' + + + How to prioritize restic's IO and CPU time ------------------------------------------ From 590dc82719d62819b897b9f8855235f96c585ae2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 01:25:20 +0000 Subject: [PATCH 09/51] build(deps): bump golang.org/x/sys from 0.31.0 to 0.33.0 Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.31.0 to 0.33.0. - [Commits](https://github.com/golang/sys/compare/v0.31.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index da26ac878..ae461251c 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( golang.org/x/net v0.38.0 golang.org/x/oauth2 v0.28.0 golang.org/x/sync v0.12.0 - golang.org/x/sys v0.31.0 + golang.org/x/sys v0.33.0 golang.org/x/term v0.30.0 golang.org/x/text v0.23.0 golang.org/x/time v0.11.0 diff --git a/go.sum b/go.sum index 0dd0741b6..18eaca30a 100644 --- a/go.sum +++ b/go.sum @@ -299,8 +299,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= From ee0cb7d1aa3eb479963727ca6f578404c51bf3a1 Mon Sep 17 00:00:00 2001 From: Mark Lopez Date: Sat, 3 May 2025 10:27:50 -0500 Subject: [PATCH 10/51] docs: updated installation docs for Windows --- doc/020_installation.rst | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/doc/020_installation.rst b/doc/020_installation.rst index a39ca896b..f79819837 100644 --- a/doc/020_installation.rst +++ b/doc/020_installation.rst @@ -175,15 +175,19 @@ restic can be installed from the official repo of Solus via the ``eopkg`` packag Windows ======= -restic can be installed using `Scoop `__: +restic can be installed using either `Scoop `__ or `WinGet `__. + +Regardless of the method, the ``restic.exe`` binary will be added to your ``PATH`` automatically, making the ``restic`` command accessible in Powershell or CMD. .. code-block:: console scoop install restic -Using this installation method, ``restic.exe`` will automatically be available -in the ``PATH``. It can be called from cmd.exe or PowerShell by typing ``restic``. +.. code-block:: console + winget install --exact --id restic.restic --scope Machine + +By default, WinGet will install restic into the ``User`` scope, which is typically in your user's ``%LOCALAPPDATA%`` directory. This behavior may be undesirable for system-wide backups, so specifying ``--scope Machine`` is recommended so that restic is installed into ``%ProgramFiles%``. This requires elevation. .. _official_binaries: @@ -253,13 +257,6 @@ the `restic beta download site and ready to run, and a new version is built every time a push is made to the master branch. -Windows -======= - -On Windows, put the `restic.exe` binary into `%SystemRoot%\\System32` to use restic -in scripts without the need for absolute paths to the binary. This requires -administrator rights. - Docker Container **************** From d708c5ea73f6ffe84f46739a19a5bcd7d097a882 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 16:45:38 +0000 Subject: [PATCH 11/51] build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.8.2 to 1.10.0. - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/go-mgmt-sdk-release-guideline.md) - [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azidentity/v1.8.2...sdk/azcore/v1.10.0) --- updated-dependencies: - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity dependency-version: 1.10.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 18 +++++++++--------- go.sum | 44 ++++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index ae461251c..2f77c941d 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,8 @@ godebug winsymlink=0 require ( cloud.google.com/go/storage v1.51.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 github.com/Backblaze/blazer v0.7.2 github.com/Microsoft/go-winio v0.6.2 @@ -32,13 +32,13 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 go.uber.org/automaxprocs v1.6.0 - golang.org/x/crypto v0.36.0 - golang.org/x/net v0.38.0 + golang.org/x/crypto v0.38.0 + golang.org/x/net v0.40.0 golang.org/x/oauth2 v0.28.0 - golang.org/x/sync v0.12.0 + golang.org/x/sync v0.14.0 golang.org/x/sys v0.33.0 - golang.org/x/term v0.30.0 - golang.org/x/text v0.23.0 + golang.org/x/term v0.32.0 + golang.org/x/text v0.25.0 golang.org/x/time v0.11.0 google.golang.org/api v0.228.0 ) @@ -51,8 +51,8 @@ require ( cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/iam v1.4.1 // indirect cloud.google.com/go/monitoring v1.24.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect diff --git a/go.sum b/go.sum index 18eaca30a..533858ae9 100644 --- a/go.sum +++ b/go.sum @@ -20,22 +20,22 @@ cloud.google.com/go/storage v1.51.0 h1:ZVZ11zCiD7b3k+cH5lQs/qcNaoSz3U9I0jgwVzqDl cloud.google.com/go/storage v1.51.0/go.mod h1:YEJfu/Ki3i5oHC/7jyTgsGZwdQ8P9hqMqvpi5kRKGgc= cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE= cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1 h1:DSDNVxqkoXJiko6x8a90zidoYqnYYa6c1MTzDKzKkTo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1/go.mod h1:zGqV2R4Cr/k8Uye5w+dgQ06WJtEcbQG/8J7BB6hnCr4= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 h1:UXT0o77lXQrikd1kgwIPQOUect7EoR/+sbP4wQKdzxM= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0/go.mod h1:cTvi54pg19DoT07ekoeMgE/taAwNtCShVeZqA+Iv2xI= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= 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.3.3 h1:H5xDQaE3XowWfhZRUpnfC+rGZMEVoSiji+b+/HFAPU4= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Backblaze/blazer v0.7.2 h1:UWNHMLB+Nf+UmbO2qkVvgriODLEMz4kIyr2Hm+DVXQM= github.com/Backblaze/blazer v0.7.2/go.mod h1:T4y3EYa9IQ5J0PKc/C/J8/CEnSd3qa/lgNw938wZg10= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= @@ -131,8 +131,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +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/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -181,8 +181,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= -github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/restic/chunker v0.4.0 h1:YUPYCUn70MYP7VO4yllypp2SjmsRhRJaad3xKu1QFRw= github.com/restic/chunker v0.4.0/go.mod h1:z0cH2BejpW636LXw0R/BGyv+Ey8+m9QGiOanDHItzyw= github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s= @@ -243,8 +243,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4= golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -266,8 +266,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -278,8 +278,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -311,8 +311,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -324,8 +324,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 4dbed5f9058e14787f682c7e8b46f6556584ce9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:32:18 +0000 Subject: [PATCH 12/51] build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md) - [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.6.0...sdk/azcore/v1.6.1) --- updated-dependencies: - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob dependency-version: 1.6.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 2f77c941d..b187d6d78 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( cloud.google.com/go/storage v1.51.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 github.com/Backblaze/blazer v0.7.2 github.com/Microsoft/go-winio v0.6.2 github.com/anacrolix/fuse v0.3.1 diff --git a/go.sum b/go.sum index 533858ae9..853ca916d 100644 --- a/go.sum +++ b/go.sum @@ -28,10 +28,10 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+ github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 h1:UXT0o77lXQrikd1kgwIPQOUect7EoR/+sbP4wQKdzxM= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0/go.mod h1:cTvi54pg19DoT07ekoeMgE/taAwNtCShVeZqA+Iv2xI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= 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.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= From 4686a12a2d5c02f26e01748ac647e602c0d6c2bd Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Mon, 2 Jun 2025 10:57:07 -0700 Subject: [PATCH 13/51] bugfix: have `--{cpu,mem,...}-profile` work even if Restic exits with error code (#5373) * bugfix: write pprof file for `--{cpu,mem,...}-profile` even on error code Before this, if `restic backup --cpu-profile dir/ backup-dir/` couldn't read some of the input files (e.g. they weren't readable by the user restic was running under), the `cpu.pprof` file it outputs would be empty. https://github.com/spf13/cobra/issues/1893 * drop changelog as it's not relevant for end users --------- Co-authored-by: Michael Eischer --- cmd/restic/global_debug.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cmd/restic/global_debug.go b/cmd/restic/global_debug.go index 1fe35146a..e536bffea 100644 --- a/cmd/restic/global_debug.go +++ b/cmd/restic/global_debug.go @@ -30,14 +30,12 @@ func registerProfiling(cmd *cobra.Command) { return profiler.Start(profiler.opts) } - origPostRun := cmd.PersistentPostRunE - cmd.PersistentPostRunE = func(cmd *cobra.Command, args []string) error { + // Once https://github.com/spf13/cobra/issues/1893 is fixed, + // this could use PersistentPostRunE instead of OnFinalize, + // reverting https://github.com/restic/restic/pull/5373. + cobra.OnFinalize(func() { profiler.Stop() - if origPostRun != nil { - return origPostRun(cmd, args) - } - return nil - } + }) profiler.opts.AddFlags(cmd.PersistentFlags()) } From 67a572fa0d4651b38d78f83cffac006fd8d01d8e Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Sun, 27 Apr 2025 19:31:09 -0700 Subject: [PATCH 14/51] docs: document profiling options a bit better Previously, the docs were a bit mysterious about what "enables profiling support" means or how one could take advantage of it. --- doc/090_participating.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/090_participating.rst b/doc/090_participating.rst index 890bd9018..2793833fe 100644 --- a/doc/090_participating.rst +++ b/doc/090_participating.rst @@ -71,8 +71,10 @@ The program can be built with debug support like this: $ go run build.go -tags debug This will make the ``restic debug `` available which can be used to -inspect internal data structures. In addition, this enables profiling support -which can help with investigation performance and memory usage issues. +inspect internal data structures. In addition, this enables profiling flags such +as ``--cpu-profile`` and ``--mem-profile`` which can help with investigation +performance and memory usage issues. See ``restic help`` for more details and a +few additional ``--...-profile`` flags. ************ From 16850c61faab89c23e902558b0131e305dc38bc2 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Sun, 27 Apr 2025 20:20:05 -0700 Subject: [PATCH 15/51] docs: when describing profiling, briefly explain .pprof files --- doc/090_participating.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/090_participating.rst b/doc/090_participating.rst index 2793833fe..a035af7ca 100644 --- a/doc/090_participating.rst +++ b/doc/090_participating.rst @@ -71,10 +71,17 @@ The program can be built with debug support like this: $ go run build.go -tags debug This will make the ``restic debug `` available which can be used to -inspect internal data structures. In addition, this enables profiling flags such -as ``--cpu-profile`` and ``--mem-profile`` which can help with investigation -performance and memory usage issues. See ``restic help`` for more details and a -few additional ``--...-profile`` flags. +inspect internal data structures. + +In addition, this enables profiling flags such as ``--cpu-profile`` and +``--mem-profile`` which can help with investigation performance and memory usage +issues. See ``restic help`` for more details and a few additional +``--...-profile`` flags. + +Running Restic with profiling enabled generates a ``.pprof`` file such as +``cpu.pprof``. To view a profile in a web browser, first make sure that the +``dot`` command from `Graphviz `__ is in the PATH. Then, +run ``go tool pprof -http : cpu.pprof``. ************ From 236f81758e24823595297587c48627908ffc700b Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 21:37:32 +0200 Subject: [PATCH 16/51] fs: rewrite Reader to build fs tree up front This adds proper support for filenames that include directories. For example, `/foo/bar` would result in an error when trying to open `/foo`. The directory tree is now build upfront. This ensures let's the directory tree construction be handled only once. All accessors then only have to look up the constructed directory entries. --- cmd/restic/cmd_backup.go | 10 +-- internal/archiver/archiver_test.go | 20 ++--- internal/fs/fs_reader.go | 138 ++++++++++++++++++----------- internal/fs/fs_reader_test.go | 118 +++++++++++++++--------- internal/restorer/restorer_test.go | 8 +- 5 files changed, 177 insertions(+), 117 deletions(-) diff --git a/cmd/restic/cmd_backup.go b/cmd/restic/cmd_backup.go index 70c0d2fb9..62f2184ae 100644 --- a/cmd/restic/cmd_backup.go +++ b/cmd/restic/cmd_backup.go @@ -591,12 +591,10 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter return err } } - targetFS = &fs.Reader{ - ModTime: timeStamp, - Name: filename, - Mode: 0644, - ReadCloser: source, - } + targetFS = fs.NewReader(filename, source, fs.ReaderOptions{ + ModTime: timeStamp, + Mode: 0644, + }) targets = []string{filename} } diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index 9a25f7fad..7b511ec84 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -174,12 +174,10 @@ func TestArchiverSaveFileReaderFS(t *testing.T) { ts := time.Now() filename := "xx" - readerFs := &fs.Reader{ - ModTime: ts, - Mode: 0123, - Name: filename, - ReadCloser: io.NopCloser(strings.NewReader(test.Data)), - } + readerFs := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ + ModTime: ts, + Mode: 0123, + }) node, stats := saveFile(t, repo, filename, readerFs) @@ -288,12 +286,10 @@ func TestArchiverSaveReaderFS(t *testing.T) { ts := time.Now() filename := "xx" - readerFs := &fs.Reader{ - ModTime: ts, - Mode: 0123, - Name: filename, - ReadCloser: io.NopCloser(strings.NewReader(test.Data)), - } + readerFs := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ + ModTime: ts, + Mode: 0123, + }) arch := New(repo, readerFs, Options{}) arch.Error = func(item string, err error) error { diff --git a/internal/fs/fs_reader.go b/internal/fs/fs_reader.go index bbe5c95ab..7334bd5be 100644 --- a/internal/fs/fs_reader.go +++ b/internal/fs/fs_reader.go @@ -19,97 +19,129 @@ import ( // be opened once, all subsequent open calls return syscall.EIO. For Lstat(), // the provided FileInfo is returned. type Reader struct { - Name string - io.ReadCloser + items map[string]readerItem +} - // for FileInfo +type ReaderOptions struct { Mode os.FileMode ModTime time.Time Size int64 AllowEmptyFile bool +} - open sync.Once +type readerItem struct { + open *sync.Once + fi *ExtendedFileInfo + rc io.ReadCloser + allowEmptyFile bool + + children []string } // statically ensure that Local implements FS. var _ FS = &Reader{} +func NewReader(name string, r io.ReadCloser, opts ReaderOptions) *Reader { + items := make(map[string]readerItem) + name = readerCleanPath(name) + + isFile := true + for { + if isFile { + fi := &ExtendedFileInfo{ + Name: path.Base(name), + Mode: opts.Mode, + ModTime: opts.ModTime, + Size: opts.Size, + } + items[name] = readerItem{ + open: &sync.Once{}, + fi: fi, + rc: r, + allowEmptyFile: opts.AllowEmptyFile, + } + isFile = false + } else { + fi := &ExtendedFileInfo{ + Name: path.Base(name), + Mode: os.ModeDir | 0755, + ModTime: time.Now(), // FIXME + Size: 0, + } + items[name] = readerItem{ + fi: fi, + // keep the children set during the previous iteration + children: items[name].children, + } + } + + parent := path.Dir(name) + if parent == name { + break + } + // add the current file to the children of the parent directory + item := items[parent] + item.children = append(item.children, path.Base(name)) + items[parent] = item + + name = parent + } + return &Reader{ + items: items, + } +} + +func readerCleanPath(name string) string { + return path.Clean("/" + name) +} + // VolumeName returns leading volume name, for the Reader file system it's // always the empty string. func (fs *Reader) VolumeName(_ string) string { return "" } -func (fs *Reader) fi() *ExtendedFileInfo { - return &ExtendedFileInfo{ - Name: fs.Name, - Mode: fs.Mode, - ModTime: fs.ModTime, - Size: fs.Size, - } -} - func (fs *Reader) OpenFile(name string, flag int, _ bool) (f File, err error) { if flag & ^(O_RDONLY|O_NOFOLLOW) != 0 { return nil, pathError("open", name, fmt.Errorf("invalid combination of flags 0x%x", flag)) } - switch name { - case fs.Name: - fs.open.Do(func() { - f = newReaderFile(fs.ReadCloser, fs.fi(), fs.AllowEmptyFile) + name = readerCleanPath(name) + item, ok := fs.items[name] + if !ok { + return nil, pathError("open", name, syscall.ENOENT) + } + + // Check if the path matches our target file + if item.rc != nil { + item.open.Do(func() { + f = newReaderFile(item.rc, item.fi, item.allowEmptyFile) }) if f == nil { return nil, pathError("open", name, syscall.EIO) } - return f, nil - case "/", ".": - f = fakeDir{ - entries: []string{fs.fi().Name}, - } return f, nil } - return nil, pathError("open", name, syscall.ENOENT) + f = fakeDir{ + entries: slices.Clone(item.children), + } + return f, nil } // Lstat returns the FileInfo structure describing the named file. -// If the file is a symbolic link, the returned FileInfo -// describes the symbolic link. Lstat makes no attempt to follow the link. // If there is an error, it will be of type *os.PathError. func (fs *Reader) Lstat(name string) (*ExtendedFileInfo, error) { - getDirInfo := func(name string) *ExtendedFileInfo { - return &ExtendedFileInfo{ - Name: fs.Base(name), - Size: 0, - Mode: os.ModeDir | 0755, - ModTime: time.Now(), - } + name = readerCleanPath(name) + item, ok := fs.items[name] + if !ok { + return nil, pathError("lstat", name, os.ErrNotExist) } - - switch name { - case fs.Name: - return fs.fi(), nil - case "/", ".": - return getDirInfo(name), nil - } - - dir := fs.Dir(fs.Name) - for { - if dir == "/" || dir == "." { - break - } - if name == dir { - return getDirInfo(name), nil - } - dir = fs.Dir(dir) - } - - return nil, pathError("lstat", name, os.ErrNotExist) + return item.fi, nil } // Join joins any number of path elements into a single path, adding a @@ -137,7 +169,7 @@ func (fs *Reader) IsAbs(_ string) bool { // // For the Reader, all paths are absolute. func (fs *Reader) Abs(p string) (string, error) { - return path.Clean(p), nil + return readerCleanPath(p), nil } // Clean returns the cleaned path. For details, see filepath.Clean. diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index 257bfbbac..cd2a68b1b 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -82,27 +82,30 @@ func checkFileInfo(t testing.TB, fi *ExtendedFileInfo, filename string, modtime } } -func TestFSReader(t *testing.T) { - data := test.Random(55, 1<<18+588) - now := time.Now() - filename := "foobar" +type fsTest []struct { + name string + f func(t *testing.T, fs FS) +} - var tests = []struct { - name string - f func(t *testing.T, fs FS) - }{ +func createReadDirTest(fpath, filename string) fsTest { + return fsTest{ { - name: "Readdirnames-slash", + name: "Readdirnames-slash-" + fpath, f: func(t *testing.T, fs FS) { - verifyDirectoryContents(t, fs, "/", []string{filename}) + verifyDirectoryContents(t, fs, "/"+fpath, []string{filename}) }, }, { - name: "Readdirnames-current", + name: "Readdirnames-current-" + fpath, f: func(t *testing.T, fs FS) { - verifyDirectoryContents(t, fs, ".", []string{filename}) + verifyDirectoryContents(t, fs, path.Clean(fpath), []string{filename}) }, }, + } +} + +func createFileTest(filename string, now time.Time, data []byte) fsTest { + return fsTest{ { name: "file/OpenFile", f: func(t *testing.T, fs FS) { @@ -141,70 +144,108 @@ func TestFSReader(t *testing.T) { checkFileInfo(t, fi, filename, now, 0644, false) }, }, + } +} + +func createDirTest(fpath string) fsTest { + return fsTest{ { - name: "dir/Lstat-slash", + name: "dir/Lstat-slash-" + fpath, f: func(t *testing.T, fs FS) { - fi, err := fs.Lstat("/") + fi, err := fs.Lstat("/" + fpath) if err != nil { t.Fatal(err) } - checkFileInfo(t, fi, "/", time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) }, }, { - name: "dir/Lstat-current", + name: "dir/Lstat-current-" + fpath, f: func(t *testing.T, fs FS) { - fi, err := fs.Lstat(".") + fi, err := fs.Lstat("./" + fpath) if err != nil { t.Fatal(err) } - checkFileInfo(t, fi, ".", time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) }, }, { - name: "dir/Lstat-error-not-exist", + name: "dir/Lstat-error-not-exist-" + fpath, f: func(t *testing.T, fs FS) { - _, err := fs.Lstat("other") + _, err := fs.Lstat(fpath + "/other") if !errors.Is(err, os.ErrNotExist) { t.Fatal(err) } }, }, { - name: "dir/Open-slash", + name: "dir/Open-slash-" + fpath, f: func(t *testing.T, fs FS) { - fi, err := fs.Lstat("/") + fi, err := fs.Lstat("/" + fpath) if err != nil { t.Fatal(err) } - checkFileInfo(t, fi, "/", time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) }, }, { - name: "dir/Open-current", + name: "dir/Open-current-" + fpath, f: func(t *testing.T, fs FS) { - fi, err := fs.Lstat(".") + fi, err := fs.Lstat("./" + fpath) if err != nil { t.Fatal(err) } - checkFileInfo(t, fi, ".", time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) }, }, } +} + +func TestFSReader(t *testing.T) { + data := test.Random(55, 1<<18+588) + now := time.Now() + filename := "foobar" + + tests := createReadDirTest("", filename) + tests = append(tests, createFileTest(filename, now, data)...) + tests = append(tests, createDirTest("")...) for _, test := range tests { - fs := &Reader{ - Name: filename, - ReadCloser: io.NopCloser(bytes.NewReader(data)), - + fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, - } + }) + + t.Run(test.name, func(t *testing.T) { + test.f(t, fs) + }) + } +} + +func TestFSReaderNested(t *testing.T) { + data := test.Random(55, 1<<18+588) + now := time.Now() + filename := "foo/sub/bar" + + tests := createReadDirTest("", "foo") + tests = append(tests, createReadDirTest("foo", "sub")...) + tests = append(tests, createReadDirTest("foo/sub", "bar")...) + tests = append(tests, createFileTest(filename, now, data)...) + tests = append(tests, createDirTest("")...) + tests = append(tests, createDirTest("foo")...) + tests = append(tests, createDirTest("foo/sub")...) + + for _, test := range tests { + fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + Mode: 0644, + Size: int64(len(data)), + ModTime: now, + }) t.Run(test.name, func(t *testing.T) { test.f(t, fs) @@ -232,16 +273,13 @@ func TestFSReaderDir(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fs := &Reader{ - Name: test.filename, - ReadCloser: io.NopCloser(bytes.NewReader(data)), - + fs := NewReader(test.filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, - } + }) - dir := path.Dir(fs.Name) + dir := path.Dir(test.filename) for { if dir == "/" || dir == "." { break @@ -287,13 +325,11 @@ func TestFSReaderMinFileSize(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fs := &Reader{ - Name: "testfile", - ReadCloser: io.NopCloser(strings.NewReader(test.data)), + fs := NewReader("testfile", io.NopCloser(strings.NewReader(test.data)), ReaderOptions{ Mode: 0644, ModTime: time.Now(), AllowEmptyFile: test.allowEmpty, - } + }) f, err := fs.OpenFile("testfile", O_RDONLY, false) if err != nil { diff --git a/internal/restorer/restorer_test.go b/internal/restorer/restorer_test.go index b48ae137c..cd0307359 100644 --- a/internal/restorer/restorer_test.go +++ b/internal/restorer/restorer_test.go @@ -908,11 +908,9 @@ func TestRestorerSparseFiles(t *testing.T) { var zeros [1<<20 + 13]byte - target := &fs.Reader{ - Mode: 0600, - Name: "/zeros", - ReadCloser: io.NopCloser(bytes.NewReader(zeros[:])), - } + target := fs.NewReader("/zeros", io.NopCloser(bytes.NewReader(zeros[:])), fs.ReaderOptions{ + Mode: 0600, + }) sc := archiver.NewScanner(target) err := sc.Scan(context.TODO(), []string{"/zeros"}) rtest.OK(t, err) From 07e4a78e4651af667a86aeb7d4191c14cad94b7f Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 21:43:31 +0200 Subject: [PATCH 17/51] fs/reader: use modification time for file and directories This ensures that a fixed input generates a fully deterministic output file structure. --- internal/fs/fs_reader.go | 2 +- internal/fs/fs_reader_test.go | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/fs/fs_reader.go b/internal/fs/fs_reader.go index 7334bd5be..7e6aa0f58 100644 --- a/internal/fs/fs_reader.go +++ b/internal/fs/fs_reader.go @@ -66,7 +66,7 @@ func NewReader(name string, r io.ReadCloser, opts ReaderOptions) *Reader { fi := &ExtendedFileInfo{ Name: path.Base(name), Mode: os.ModeDir | 0755, - ModTime: time.Now(), // FIXME + ModTime: opts.ModTime, Size: 0, } items[name] = readerItem{ diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index cd2a68b1b..f49cc0d8d 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -69,7 +69,7 @@ func checkFileInfo(t testing.TB, fi *ExtendedFileInfo, filename string, modtime t.Errorf("Mode has wrong value, want 0%o, got 0%o", mode, fi.Mode) } - if !modtime.Equal(time.Time{}) && !fi.ModTime.Equal(modtime) { + if !fi.ModTime.Equal(modtime) { t.Errorf("ModTime has wrong value, want %v, got %v", modtime, fi.ModTime) } @@ -147,7 +147,7 @@ func createFileTest(filename string, now time.Time, data []byte) fsTest { } } -func createDirTest(fpath string) fsTest { +func createDirTest(fpath string, now time.Time) fsTest { return fsTest{ { name: "dir/Lstat-slash-" + fpath, @@ -157,7 +157,7 @@ func createDirTest(fpath string) fsTest { t.Fatal(err) } - checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, { @@ -168,7 +168,7 @@ func createDirTest(fpath string) fsTest { t.Fatal(err) } - checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, { @@ -188,7 +188,7 @@ func createDirTest(fpath string) fsTest { t.Fatal(err) } - checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, { @@ -199,7 +199,7 @@ func createDirTest(fpath string) fsTest { t.Fatal(err) } - checkFileInfo(t, fi, "/"+fpath, time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, } @@ -212,7 +212,7 @@ func TestFSReader(t *testing.T) { tests := createReadDirTest("", filename) tests = append(tests, createFileTest(filename, now, data)...) - tests = append(tests, createDirTest("")...) + tests = append(tests, createDirTest("", now)...) for _, test := range tests { fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ @@ -236,9 +236,9 @@ func TestFSReaderNested(t *testing.T) { tests = append(tests, createReadDirTest("foo", "sub")...) tests = append(tests, createReadDirTest("foo/sub", "bar")...) tests = append(tests, createFileTest(filename, now, data)...) - tests = append(tests, createDirTest("")...) - tests = append(tests, createDirTest("foo")...) - tests = append(tests, createDirTest("foo/sub")...) + tests = append(tests, createDirTest("", now)...) + tests = append(tests, createDirTest("foo", now)...) + tests = append(tests, createDirTest("foo/sub", now)...) for _, test := range tests { fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ @@ -290,7 +290,7 @@ func TestFSReaderDir(t *testing.T) { t.Fatal(err) } - checkFileInfo(t, fi, dir, time.Time{}, os.ModeDir|0755, true) + checkFileInfo(t, fi, dir, now, os.ModeDir|0755, true) dir = path.Dir(dir) } From 04898e41d13c784fbcb51baf99732f3b70810ed5 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 21:49:25 +0200 Subject: [PATCH 18/51] fs/reader: fix open+stat handling --- internal/fs/fs_reader.go | 3 +++ internal/fs/fs_reader_test.go | 30 ++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/internal/fs/fs_reader.go b/internal/fs/fs_reader.go index 7e6aa0f58..97e09d1d2 100644 --- a/internal/fs/fs_reader.go +++ b/internal/fs/fs_reader.go @@ -128,6 +128,9 @@ func (fs *Reader) OpenFile(name string, flag int, _ bool) (f File, err error) { } f = fakeDir{ + fakeFile: fakeFile{ + fi: item.fi, + }, entries: slices.Clone(item.children), } return f, nil diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index f49cc0d8d..ef95083ae 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -183,28 +183,38 @@ func createDirTest(fpath string, now time.Time) fsTest { { name: "dir/Open-slash-" + fpath, f: func(t *testing.T, fs FS) { - fi, err := fs.Lstat("/" + fpath) - if err != nil { - t.Fatal(err) - } - + fi := fsStatDir(t, fs, "/"+fpath) checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, { name: "dir/Open-current-" + fpath, f: func(t *testing.T, fs FS) { - fi, err := fs.Lstat("./" + fpath) - if err != nil { - t.Fatal(err) - } - + fi := fsStatDir(t, fs, "./"+fpath) checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, } } +func fsStatDir(t *testing.T, fs FS, fpath string) *ExtendedFileInfo { + f, err := fs.OpenFile(fpath, O_RDONLY, false) + if err != nil { + t.Fatal(err) + } + + fi, err := f.Stat() + if err != nil { + t.Fatal(err) + } + + err = f.Close() + if err != nil { + t.Fatal(err) + } + return fi +} + func TestFSReader(t *testing.T) { data := test.Random(55, 1<<18+588) now := time.Now() From 37a4235e4d65118d1a2561f7715bcad14bfc6451 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 21:50:47 +0200 Subject: [PATCH 19/51] fs/reader: deduplicate test code --- internal/fs/fs_reader_test.go | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index ef95083ae..3df3906aa 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -126,21 +126,7 @@ func createFileTest(filename string, now time.Time, data []byte) fsTest { { name: "file/Stat", f: func(t *testing.T, fs FS) { - f, err := fs.OpenFile(filename, O_RDONLY, true) - if err != nil { - t.Fatal(err) - } - - fi, err := f.Stat() - if err != nil { - t.Fatal(err) - } - - err = f.Close() - if err != nil { - t.Fatal(err) - } - + fi := fsOpenAndStat(t, fs, filename, true) checkFileInfo(t, fi, filename, now, 0644, false) }, }, @@ -183,22 +169,22 @@ func createDirTest(fpath string, now time.Time) fsTest { { name: "dir/Open-slash-" + fpath, f: func(t *testing.T, fs FS) { - fi := fsStatDir(t, fs, "/"+fpath) + fi := fsOpenAndStat(t, fs, "/"+fpath, false) checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, { name: "dir/Open-current-" + fpath, f: func(t *testing.T, fs FS) { - fi := fsStatDir(t, fs, "./"+fpath) + fi := fsOpenAndStat(t, fs, "./"+fpath, false) checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, }, } } -func fsStatDir(t *testing.T, fs FS, fpath string) *ExtendedFileInfo { - f, err := fs.OpenFile(fpath, O_RDONLY, false) +func fsOpenAndStat(t *testing.T, fs FS, fpath string, metadataOnly bool) *ExtendedFileInfo { + f, err := fs.OpenFile(fpath, O_RDONLY, metadataOnly) if err != nil { t.Fatal(err) } From ba2b0b2cc70b4d71e102161c0781340e7591287d Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 21:54:15 +0200 Subject: [PATCH 20/51] fs/reader: use test helpers --- internal/fs/fs_reader_test.go | 98 ++++++++++------------------------- 1 file changed, 28 insertions(+), 70 deletions(-) diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index 3df3906aa..5176e467d 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -17,19 +17,11 @@ import ( func verifyFileContentOpenFile(t testing.TB, fs FS, filename string, want []byte) { f, err := fs.OpenFile(filename, O_RDONLY, false) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) buf, err := io.ReadAll(f) - if err != nil { - t.Fatal(err) - } - - err = f.Close() - if err != nil { - t.Fatal(err) - } + test.OK(t, err) + test.OK(t, f.Close()) if !cmp.Equal(want, buf) { t.Error(cmp.Diff(want, buf)) @@ -38,19 +30,11 @@ func verifyFileContentOpenFile(t testing.TB, fs FS, filename string, want []byte func verifyDirectoryContents(t testing.TB, fs FS, dir string, want []string) { f, err := fs.OpenFile(dir, O_RDONLY, false) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) entries, err := f.Readdirnames(-1) - if err != nil { - t.Fatal(err) - } - - err = f.Close() - if err != nil { - t.Fatal(err) - } + test.OK(t, err) + test.OK(t, f.Close()) sort.Strings(want) sort.Strings(entries) @@ -116,9 +100,7 @@ func createFileTest(filename string, now time.Time, data []byte) fsTest { name: "file/Lstat", f: func(t *testing.T, fs FS) { fi, err := fs.Lstat(filename) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) checkFileInfo(t, fi, filename, now, 0644, false) }, @@ -139,9 +121,7 @@ func createDirTest(fpath string, now time.Time) fsTest { name: "dir/Lstat-slash-" + fpath, f: func(t *testing.T, fs FS) { fi, err := fs.Lstat("/" + fpath) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, @@ -150,9 +130,7 @@ func createDirTest(fpath string, now time.Time) fsTest { name: "dir/Lstat-current-" + fpath, f: func(t *testing.T, fs FS) { fi, err := fs.Lstat("./" + fpath) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) checkFileInfo(t, fi, "/"+fpath, now, os.ModeDir|0755, true) }, @@ -161,9 +139,7 @@ func createDirTest(fpath string, now time.Time) fsTest { name: "dir/Lstat-error-not-exist-" + fpath, f: func(t *testing.T, fs FS) { _, err := fs.Lstat(fpath + "/other") - if !errors.Is(err, os.ErrNotExist) { - t.Fatal(err) - } + test.Assert(t, errors.Is(err, os.ErrNotExist), "unexpected error, got %v, expected %v", err, os.ErrNotExist) }, }, { @@ -185,19 +161,11 @@ func createDirTest(fpath string, now time.Time) fsTest { func fsOpenAndStat(t *testing.T, fs FS, fpath string, metadataOnly bool) *ExtendedFileInfo { f, err := fs.OpenFile(fpath, O_RDONLY, metadataOnly) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) fi, err := f.Stat() - if err != nil { - t.Fatal(err) - } - - err = f.Close() - if err != nil { - t.Fatal(err) - } + test.OK(t, err) + test.OK(t, f.Close()) return fi } @@ -267,24 +235,22 @@ func TestFSReaderDir(t *testing.T) { }, } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - fs := NewReader(test.filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + for _, tst := range tests { + t.Run(tst.name, func(t *testing.T) { + fs := NewReader(tst.filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, }) - dir := path.Dir(test.filename) + dir := path.Dir(tst.filename) for { if dir == "/" || dir == "." { break } fi, err := fs.Lstat(dir) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) checkFileInfo(t, fi, dir, now, os.ModeDir|0755, true) @@ -319,38 +285,30 @@ func TestFSReaderMinFileSize(t *testing.T) { }, } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - fs := NewReader("testfile", io.NopCloser(strings.NewReader(test.data)), ReaderOptions{ + for _, tst := range tests { + t.Run(tst.name, func(t *testing.T) { + fs := NewReader("testfile", io.NopCloser(strings.NewReader(tst.data)), ReaderOptions{ Mode: 0644, ModTime: time.Now(), - AllowEmptyFile: test.allowEmpty, + AllowEmptyFile: tst.allowEmpty, }) f, err := fs.OpenFile("testfile", O_RDONLY, false) - if err != nil { - t.Fatal(err) - } + test.OK(t, err) buf, err := io.ReadAll(f) - if test.readMustErr { + if tst.readMustErr { if err == nil { t.Fatal("expected error not found, got nil") } } else { - if err != nil { - t.Fatal(err) - } + test.OK(t, err) } - if string(buf) != test.data { - t.Fatalf("wrong data returned, want %q, got %q", test.data, string(buf)) - } - - err = f.Close() - if err != nil { - t.Fatal(err) + if string(buf) != tst.data { + t.Fatalf("wrong data returned, want %q, got %q", tst.data, string(buf)) } + test.OK(t, f.Close()) }) } } From 81ac49f59db427f029939d8a4a6e9b0b88bfbeb8 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 21:57:45 +0200 Subject: [PATCH 21/51] fs/reader: test file not exist case --- internal/fs/fs_reader_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index 5176e467d..bde097d5c 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -96,6 +96,13 @@ func createFileTest(filename string, now time.Time, data []byte) fsTest { verifyFileContentOpenFile(t, fs, filename, data) }, }, + { + name: "file/Open-error-not-exist", + f: func(t *testing.T, fs FS) { + _, err := fs.OpenFile(filename+"/other", O_RDONLY, false) + test.Assert(t, errors.Is(err, os.ErrNotExist), "unexpected error, got %v, expected %v", err, os.ErrNotExist) + }, + }, { name: "file/Lstat", f: func(t *testing.T, fs FS) { From ef1e137e7a31cefe6bf164f0de1335b918bedcdb Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 22:07:31 +0200 Subject: [PATCH 22/51] fs/reader: return proper error on invalid filename --- cmd/restic/cmd_backup.go | 5 ++++- internal/archiver/archiver_test.go | 7 ++++--- internal/fs/fs_reader.go | 7 +++++-- internal/fs/fs_reader_test.go | 26 ++++++++++++++------------ internal/restorer/restorer_test.go | 5 +++-- 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/cmd/restic/cmd_backup.go b/cmd/restic/cmd_backup.go index 62f2184ae..acb5500fd 100644 --- a/cmd/restic/cmd_backup.go +++ b/cmd/restic/cmd_backup.go @@ -591,10 +591,13 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter return err } } - targetFS = fs.NewReader(filename, source, fs.ReaderOptions{ + targetFS, err = fs.NewReader(filename, source, fs.ReaderOptions{ ModTime: timeStamp, Mode: 0644, }) + if err != nil { + return fmt.Errorf("failed to backup from stdin: %w", err) + } targets = []string{filename} } diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index 7b511ec84..906c83011 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -174,10 +174,11 @@ func TestArchiverSaveFileReaderFS(t *testing.T) { ts := time.Now() filename := "xx" - readerFs := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ + readerFs, err := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ ModTime: ts, Mode: 0123, }) + rtest.OK(t, err) node, stats := saveFile(t, repo, filename, readerFs) @@ -286,11 +287,11 @@ func TestArchiverSaveReaderFS(t *testing.T) { ts := time.Now() filename := "xx" - readerFs := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ + readerFs, err := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ ModTime: ts, Mode: 0123, }) - + rtest.OK(t, err) arch := New(repo, readerFs, Options{}) arch.Error = func(item string, err error) error { t.Errorf("archiver error for %v: %v", item, err) diff --git a/internal/fs/fs_reader.go b/internal/fs/fs_reader.go index 97e09d1d2..c4e98be0f 100644 --- a/internal/fs/fs_reader.go +++ b/internal/fs/fs_reader.go @@ -42,9 +42,12 @@ type readerItem struct { // statically ensure that Local implements FS. var _ FS = &Reader{} -func NewReader(name string, r io.ReadCloser, opts ReaderOptions) *Reader { +func NewReader(name string, r io.ReadCloser, opts ReaderOptions) (*Reader, error) { items := make(map[string]readerItem) name = readerCleanPath(name) + if name == "/" { + return nil, fmt.Errorf("invalid filename specified") + } isFile := true for { @@ -89,7 +92,7 @@ func NewReader(name string, r io.ReadCloser, opts ReaderOptions) *Reader { } return &Reader{ items: items, - } + }, nil } func readerCleanPath(name string) string { diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index bde097d5c..083e8a1a5 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -185,15 +185,16 @@ func TestFSReader(t *testing.T) { tests = append(tests, createFileTest(filename, now, data)...) tests = append(tests, createDirTest("", now)...) - for _, test := range tests { - fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + for _, tst := range tests { + fs, err := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, }) + test.OK(t, err) - t.Run(test.name, func(t *testing.T) { - test.f(t, fs) + t.Run(tst.name, func(t *testing.T) { + tst.f(t, fs) }) } } @@ -211,15 +212,16 @@ func TestFSReaderNested(t *testing.T) { tests = append(tests, createDirTest("foo", now)...) tests = append(tests, createDirTest("foo/sub", now)...) - for _, test := range tests { - fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + for _, tst := range tests { + fs, err := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, }) + test.OK(t, err) - t.Run(test.name, func(t *testing.T) { - test.f(t, fs) + t.Run(tst.name, func(t *testing.T) { + tst.f(t, fs) }) } } @@ -244,12 +246,12 @@ func TestFSReaderDir(t *testing.T) { for _, tst := range tests { t.Run(tst.name, func(t *testing.T) { - fs := NewReader(tst.filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + fs, err := NewReader(tst.filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, }) - + test.OK(t, err) dir := path.Dir(tst.filename) for { if dir == "/" || dir == "." { @@ -294,12 +296,12 @@ func TestFSReaderMinFileSize(t *testing.T) { for _, tst := range tests { t.Run(tst.name, func(t *testing.T) { - fs := NewReader("testfile", io.NopCloser(strings.NewReader(tst.data)), ReaderOptions{ + fs, err := NewReader("testfile", io.NopCloser(strings.NewReader(tst.data)), ReaderOptions{ Mode: 0644, ModTime: time.Now(), AllowEmptyFile: tst.allowEmpty, }) - + test.OK(t, err) f, err := fs.OpenFile("testfile", O_RDONLY, false) test.OK(t, err) diff --git a/internal/restorer/restorer_test.go b/internal/restorer/restorer_test.go index cd0307359..0b5e34d12 100644 --- a/internal/restorer/restorer_test.go +++ b/internal/restorer/restorer_test.go @@ -908,11 +908,12 @@ func TestRestorerSparseFiles(t *testing.T) { var zeros [1<<20 + 13]byte - target := fs.NewReader("/zeros", io.NopCloser(bytes.NewReader(zeros[:])), fs.ReaderOptions{ + target, err := fs.NewReader("/zeros", io.NopCloser(bytes.NewReader(zeros[:])), fs.ReaderOptions{ Mode: 0600, }) + rtest.OK(t, err) sc := archiver.NewScanner(target) - err := sc.Scan(context.TODO(), []string{"/zeros"}) + err = sc.Scan(context.TODO(), []string{"/zeros"}) rtest.OK(t, err) arch := archiver.New(repo, target, archiver.Options{}) From 91d582a66726a1bae1bee98e22bf0fa896898768 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 22:14:27 +0200 Subject: [PATCH 23/51] backup: test subdirectories in stdin filenames work --- cmd/restic/cmd_backup_integration_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/restic/cmd_backup_integration_test.go b/cmd/restic/cmd_backup_integration_test.go index 06d71e345..0002b207f 100644 --- a/cmd/restic/cmd_backup_integration_test.go +++ b/cmd/restic/cmd_backup_integration_test.go @@ -632,12 +632,15 @@ func TestStdinFromCommand(t *testing.T) { testSetupBackupData(t, env) opts := BackupOptions{ - StdinCommand: true, - StdinFilename: "stdin", + StdinCommand: true, + // test that subdirectories are handled correctly + StdinFilename: "stdin/subdir/file", } testRunBackup(t, filepath.Dir(env.testdata), []string{"python", "-c", "import sys; print('something'); sys.exit(0)"}, opts, env.gopts) - testListSnapshots(t, env.gopts, 1) + snapshots := testListSnapshots(t, env.gopts, 1) + files := testRunLs(t, env.gopts, snapshots[0].String()) + rtest.Assert(t, includes(files, "/stdin/subdir/file"), "file %q missing from snapshot, got %v", "stdin/subdir/file", files) testRunCheck(t, env.gopts) } From 6bdca9a7d59db40b61a5e4661cc09e210e9b3aa0 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 11 Apr 2025 22:19:33 +0200 Subject: [PATCH 24/51] add changelog for --stdin-filename with/directory --- changelog/unreleased/issue-5324 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 changelog/unreleased/issue-5324 diff --git a/changelog/unreleased/issue-5324 b/changelog/unreleased/issue-5324 new file mode 100644 index 000000000..0f5ff77e4 --- /dev/null +++ b/changelog/unreleased/issue-5324 @@ -0,0 +1,14 @@ +Bugfix: Correctly handle `backup --stdin-filename` with directories + +In restic 0.18.0, the `backup` command failed if a filename that includes +a least a directory was passed to `--stdin-filename`. For example, +`--stdin-filename /foo/bar` resulted in the following error: + +``` +Fatal: unable to save snapshot: open /foo: no such file or directory +``` + +This has been fixed now. + +https://github.com/restic/restic/issues/5324 +https://github.com/restic/restic/pull/5356 From d64bad1a9037fd3118289c5eafc96f29f70bbd7d Mon Sep 17 00:00:00 2001 From: Patrick Wolf Date: Mon, 2 Jun 2025 14:40:04 -0400 Subject: [PATCH 25/51] Update 047_tuning_backup_parameters.rst - local backend (#5355) users would find it helpful to know how to adjust the "local" backend and they might not get the idea that the local backend is just called local... which in turn leads them to think restic is slow as they can't adjust away from 2 threads for restore and backup. --- doc/047_tuning_backup_parameters.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/047_tuning_backup_parameters.rst b/doc/047_tuning_backup_parameters.rst index 650f111be..670828239 100644 --- a/doc/047_tuning_backup_parameters.rst +++ b/doc/047_tuning_backup_parameters.rst @@ -34,11 +34,12 @@ Backend Connections Restic uses a global limit for the number of concurrent connections to a backend. This limit can be configured using ``-o .connections=5``, for example for -the REST backend the parameter would be ``-o rest.connections=5``. By default restic uses -``5`` connections for each backend, except for the local backend which uses a limit of ``2``. -The defaults should work well in most cases. For high-latency backends it can be beneficial -to increase the number of connections. Please be aware that this increases the resource -consumption of restic and that a too high connection count *will degrade performance*. +the REST backend the parameter would be ``-o rest.connections=5`` or for the local backend +``-o local.connections=2``. By default restic uses ``5`` connections for each backend, +except for the local backend which uses a limit of ``2``. The defaults should work well in +most cases. For high-latency backends it can be beneficial to increase the number of +connections. Please be aware that this increases the resource consumption of restic and +that a too high connection count *will degrade performance*. CPU Usage From 5070e62b18e152f25f9587d911bcfac05e348d7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 05:46:21 +0000 Subject: [PATCH 26/51] build(deps): bump golang.org/x/crypto from 0.38.0 to 0.39.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.38.0 to 0.39.0. - [Commits](https://github.com/golang/crypto/compare/v0.38.0...v0.39.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.39.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index b187d6d78..74490dcd4 100644 --- a/go.mod +++ b/go.mod @@ -32,13 +32,13 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 go.uber.org/automaxprocs v1.6.0 - golang.org/x/crypto v0.38.0 + golang.org/x/crypto v0.39.0 golang.org/x/net v0.40.0 golang.org/x/oauth2 v0.28.0 - golang.org/x/sync v0.14.0 + golang.org/x/sync v0.15.0 golang.org/x/sys v0.33.0 golang.org/x/term v0.32.0 - golang.org/x/text v0.25.0 + golang.org/x/text v0.26.0 golang.org/x/time v0.11.0 google.golang.org/api v0.228.0 ) diff --git a/go.sum b/go.sum index 853ca916d..53aa73a69 100644 --- a/go.sum +++ b/go.sum @@ -243,8 +243,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4= golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -278,8 +278,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -324,8 +324,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 3c8fc9d9bc3b40580c0bcdee1d1bfa962a4f4fd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 05:07:50 +0000 Subject: [PATCH 27/51] build(deps): bump github.com/peterbourgon/unixtransport Bumps [github.com/peterbourgon/unixtransport](https://github.com/peterbourgon/unixtransport) from 0.0.4 to 0.0.6. - [Release notes](https://github.com/peterbourgon/unixtransport/releases) - [Commits](https://github.com/peterbourgon/unixtransport/compare/v0.0.4...v0.0.6) --- updated-dependencies: - dependency-name: github.com/peterbourgon/unixtransport dependency-version: 0.0.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 74490dcd4..f22dc0205 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/klauspost/compress v1.18.0 github.com/minio/minio-go/v7 v7.0.89 github.com/ncw/swift/v2 v2.0.3 - github.com/peterbourgon/unixtransport v0.0.4 + github.com/peterbourgon/unixtransport v0.0.6 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.7.0 github.com/pkg/sftp v1.13.9 diff --git a/go.sum b/go.sum index 53aa73a69..ed1971da3 100644 --- a/go.sum +++ b/go.sum @@ -162,8 +162,8 @@ github.com/ncw/swift/v2 v2.0.3/go.mod h1:cbAO76/ZwcFrFlHdXPjaqWZ9R7Hdar7HpjRXBfb github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/ff/v3 v3.3.1/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= -github.com/peterbourgon/unixtransport v0.0.4 h1:UTF0FxXCAglvoZz9jaGPYjEg52DjBLDYGMJvJni6Tfw= -github.com/peterbourgon/unixtransport v0.0.4/go.mod h1:o8aUkOCa8W/BIXpi15uKvbSabjtBh0JhSOJGSfoOhAU= +github.com/peterbourgon/unixtransport v0.0.6 h1:sWIViDoRIg2MeyRbWTUDdvvY5XbKaaSr9ionmzNGXWY= +github.com/peterbourgon/unixtransport v0.0.6/go.mod h1:o8aUkOCa8W/BIXpi15uKvbSabjtBh0JhSOJGSfoOhAU= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= From 22bbbf42f59dda66fe34abe03c4636e0e4f46b3a Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Mon, 2 Jun 2025 21:12:37 +0200 Subject: [PATCH 28/51] Fix release note typos --- CHANGELOG.md | 10 +++++----- changelog/0.18.0_2025-03-27/issue-5287 | 2 +- changelog/0.18.0_2025-03-27/pull-5162 | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32d6ffa6e..f797834aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,7 +54,7 @@ restic users. The changes are ordered by importance. * Fix #5249: Fix creation of oversized index by `repair index --read-all-packs` * Fix #5259: Fix rare crash in command output * Chg #4938: Update dependencies and require Go 1.23 or newer - * Chg #5162: Promote feature flags + * Chg #5162: Graduate feature flags * Enh #1378: Add JSON support to `check` command * Enh #2511: Support generating shell completions to stdout * Enh #3697: Allow excluding online-only cloud files (e.g. OneDrive) @@ -76,7 +76,7 @@ restic users. The changes are ordered by importance. * Enh #5173: Add experimental S3 cold storage support * Enh #5174: Add xattr support for NetBSD 10+ * Enh #5251: Improve retry handling for flaky `rclone` backends - * Enh #52897: Make `recover` automatically rebuild index when needed + * Enh #5287: Make `recover` automatically rebuild index when needed ## Details @@ -208,7 +208,7 @@ restic users. The changes are ordered by importance. https://github.com/restic/restic/pull/4938 - * Change #5162: Promote feature flags + * Change #5162: Graduate feature flags The `deprecate-legacy-index`, `deprecate-s3-legacy-layout`, `explicit-s3-anonymous-auth` and `safe-forget-keep-tags` features are now stable @@ -408,13 +408,13 @@ restic users. The changes are ordered by importance. https://github.com/restic/restic/pull/5251 - * Enhancement #52897: Make `recover` automatically rebuild index when needed + * Enhancement #5287: Make `recover` automatically rebuild index when needed When trying to recover data from an interrupted snapshot, it was previously necessary to manually run `repair index` before runnning `recover`. This now happens automatically so that only `recover` is necessary. - https://github.com/restic/restic/issues/52897 + https://github.com/restic/restic/issues/5287 https://github.com/restic/restic/pull/5296 diff --git a/changelog/0.18.0_2025-03-27/issue-5287 b/changelog/0.18.0_2025-03-27/issue-5287 index ba5499ead..3d25126f1 100644 --- a/changelog/0.18.0_2025-03-27/issue-5287 +++ b/changelog/0.18.0_2025-03-27/issue-5287 @@ -4,5 +4,5 @@ When trying to recover data from an interrupted snapshot, it was previously necessary to manually run `repair index` before runnning `recover`. This now happens automatically so that only `recover` is necessary. -https://github.com/restic/restic/issues/52897 +https://github.com/restic/restic/issues/5287 https://github.com/restic/restic/pull/5296 diff --git a/changelog/0.18.0_2025-03-27/pull-5162 b/changelog/0.18.0_2025-03-27/pull-5162 index 6a0d75547..8efe8f66d 100644 --- a/changelog/0.18.0_2025-03-27/pull-5162 +++ b/changelog/0.18.0_2025-03-27/pull-5162 @@ -1,4 +1,4 @@ -Change: Promote feature flags +Change: Graduate feature flags The `deprecate-legacy-index`, `deprecate-s3-legacy-layout`, `explicit-s3-anonymous-auth` and `safe-forget-keep-tags` features are From 242b607bf6a6a83fd30d409d9c3474499ea2c1d8 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Mon, 2 Jun 2025 19:44:47 +0200 Subject: [PATCH 29/51] walker: fix error handling if tree cannot be loaded A tree that cannot be loaded is a fatal error when walking the tree. Thus, return the error and exit the tree walk. --- internal/walker/walker.go | 2 ++ internal/walker/walker_test.go | 64 ++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/internal/walker/walker.go b/internal/walker/walker.go index 252bc3530..0d69106bf 100644 --- a/internal/walker/walker.go +++ b/internal/walker/walker.go @@ -91,6 +91,8 @@ func walk(ctx context.Context, repo restic.BlobLoader, prefix string, parentTree if err == ErrSkipNode { continue } + + return err } err = walk(ctx, repo, p, *node.Subtree, subtree, visitor) diff --git a/internal/walker/walker_test.go b/internal/walker/walker_test.go index 3614a2397..47d872d97 100644 --- a/internal/walker/walker_test.go +++ b/internal/walker/walker_test.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/restic/restic/internal/restic" + rtest "github.com/restic/restic/internal/test" ) // TestTree is used to construct a list of trees for testing the walker. @@ -93,12 +94,12 @@ func (t TreeMap) Connections() uint { // checkFunc returns a function suitable for walking the tree to check // something, and a function which will check the final result. -type checkFunc func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB)) +type checkFunc func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB, error)) // checkItemOrder ensures that the order of the 'path' arguments is the one passed in as 'want'. func checkItemOrder(want []string) checkFunc { pos := 0 - return func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB)) { + return func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB, error)) { walker = func(treeID restic.ID, path string, node *restic.Node, err error) error { if err != nil { t.Errorf("error walking %v: %v", path, err) @@ -121,7 +122,8 @@ func checkItemOrder(want []string) checkFunc { return walker(restic.ID{}, "leave: "+path, nil, nil) } - final = func(t testing.TB) { + final = func(t testing.TB, err error) { + rtest.OK(t, err) if pos != len(want) { t.Errorf("not enough items returned, want %d, got %d", len(want), pos) } @@ -134,7 +136,7 @@ func checkItemOrder(want []string) checkFunc { // checkParentTreeOrder ensures that the order of the 'parentID' arguments is the one passed in as 'want'. func checkParentTreeOrder(want []string) checkFunc { pos := 0 - return func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB)) { + return func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB, error)) { walker = func(treeID restic.ID, path string, node *restic.Node, err error) error { if err != nil { t.Errorf("error walking %v: %v", path, err) @@ -153,7 +155,8 @@ func checkParentTreeOrder(want []string) checkFunc { return nil } - final = func(t testing.TB) { + final = func(t testing.TB, err error) { + rtest.OK(t, err) if pos != len(want) { t.Errorf("not enough items returned, want %d, got %d", len(want), pos) } @@ -168,7 +171,7 @@ func checkParentTreeOrder(want []string) checkFunc { func checkSkipFor(skipFor map[string]struct{}, wantPaths []string) checkFunc { var pos int - return func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB)) { + return func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB, error)) { walker = func(treeID restic.ID, path string, node *restic.Node, err error) error { if err != nil { t.Errorf("error walking %v: %v", path, err) @@ -196,7 +199,8 @@ func checkSkipFor(skipFor map[string]struct{}, wantPaths []string) checkFunc { return walker(restic.ID{}, "leave: "+path, nil, nil) } - final = func(t testing.TB) { + final = func(t testing.TB, err error) { + rtest.OK(t, err) if pos != len(wantPaths) { t.Errorf("wrong number of paths returned, want %d, got %d", len(wantPaths), pos) } @@ -206,6 +210,32 @@ func checkSkipFor(skipFor map[string]struct{}, wantPaths []string) checkFunc { } } +func checkErrorReturned(errForPath string) checkFunc { + expectedErr := fmt.Errorf("error for %v", errForPath) + + return func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB, error)) { + walker = func(treeID restic.ID, path string, node *restic.Node, err error) error { + if path == errForPath { + return expectedErr + } + return nil + } + + leaveDir = func(path string) error { + return walker(restic.ID{}, "leave: "+path, nil, nil) + } + + final = func(t testing.TB, err error) { + if err == nil { + t.Errorf("expected error for %v, got nil", errForPath) + } + rtest.Assert(t, err == expectedErr, "expected error for %v, got %v", errForPath, err) + } + + return walker, leaveDir, final + } +} + func TestWalker(t *testing.T) { var tests = []struct { tree TestTree @@ -427,6 +457,21 @@ func TestWalker(t *testing.T) { }), }, }, + { + tree: TestTree{ + "subdir1": TestTree{ + "file": TestFile{}, + }, + "subdir2": TestTree{}, + }, + checks: []checkFunc{ + checkErrorReturned("/subdir1"), + checkErrorReturned("/subdir2"), + checkErrorReturned("/subdir1/file"), + checkErrorReturned("leave: /subdir1"), + checkErrorReturned("leave: /subdir2"), + }, + }, } for _, test := range tests { @@ -442,10 +487,7 @@ func TestWalker(t *testing.T) { ProcessNode: fn, LeaveDir: leaveDir, }) - if err != nil { - t.Error(err) - } - last(t) + last(t, err) }) } }) From 4f03e03b2ca54269353fa4c28021157a93b3c20c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 05:07:41 +0000 Subject: [PATCH 30/51] build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.10.0 to 1.10.1. - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/go-mgmt-sdk-release-guideline.md) - [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.10.0...sdk/azidentity/v1.10.1) --- updated-dependencies: - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity dependency-version: 1.10.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f22dc0205..97cb6eee1 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ godebug winsymlink=0 require ( cloud.google.com/go/storage v1.51.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 github.com/Backblaze/blazer v0.7.2 github.com/Microsoft/go-winio v0.6.2 diff --git a/go.sum b/go.sum index ed1971da3..6cd85a605 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,8 @@ cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= From 7b986795deab2e5a41f8b25535e39718d807b3a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 19:46:35 +0000 Subject: [PATCH 31/51] build(deps): bump golang.org/x/time from 0.11.0 to 0.12.0 Bumps [golang.org/x/time](https://github.com/golang/time) from 0.11.0 to 0.12.0. - [Commits](https://github.com/golang/time/compare/v0.11.0...v0.12.0) --- updated-dependencies: - dependency-name: golang.org/x/time dependency-version: 0.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 97cb6eee1..459e9911e 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( golang.org/x/sys v0.33.0 golang.org/x/term v0.32.0 golang.org/x/text v0.26.0 - golang.org/x/time v0.11.0 + golang.org/x/time v0.12.0 google.golang.org/api v0.228.0 ) diff --git a/go.sum b/go.sum index 6cd85a605..1c45f3179 100644 --- a/go.sum +++ b/go.sum @@ -326,8 +326,8 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= From 20f472a67fdabb24523572c482e39cbc5567c727 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Fri, 4 Apr 2025 10:22:54 -0400 Subject: [PATCH 32/51] backend/local: ignore chmod "not supported" errors --- changelog/unreleased/issue-5342 | 7 +++++++ internal/backend/local/local_unix.go | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/issue-5342 diff --git a/changelog/unreleased/issue-5342 b/changelog/unreleased/issue-5342 new file mode 100644 index 000000000..e9887fda2 --- /dev/null +++ b/changelog/unreleased/issue-5342 @@ -0,0 +1,7 @@ +Bugfix: Ignore "chmod not supported" errors when writing files + +Restic 0.18.0 introduced a bug that caused "chmod xxx: operation not supported" +errors to appear when writing to a local file repository that did not support +chmod (like CIFS or WebDAV mounted via FUSE). Restic now ignores those errors. + +https://github.com/restic/restic/issues/5342 diff --git a/internal/backend/local/local_unix.go b/internal/backend/local/local_unix.go index e52587456..b885ae1a3 100644 --- a/internal/backend/local/local_unix.go +++ b/internal/backend/local/local_unix.go @@ -43,5 +43,12 @@ func isMacENOTTY(err error) bool { // set file to readonly func setFileReadonly(f string, mode os.FileMode) error { - return os.Chmod(f, mode&^0222) + err := os.Chmod(f, mode&^0222) + + // ignore the error if the FS does not support setting this mode (e.g. CIFS with gvfs on Linux) + if err != nil && errors.Is(err, errors.ErrUnsupported) { + return nil + } + + return err } From ac051c3dcd597d5a9e931a2ccef88d46087911e2 Mon Sep 17 00:00:00 2001 From: A Crutcher Date: Sat, 2 Aug 2025 13:03:43 -0500 Subject: [PATCH 33/51] doc: Correct Wasabi link --- doc/030_preparing_a_new_repo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/030_preparing_a_new_repo.rst b/doc/030_preparing_a_new_repo.rst index ac9657460..fb7963739 100644 --- a/doc/030_preparing_a_new_repo.rst +++ b/doc/030_preparing_a_new_repo.rst @@ -349,7 +349,7 @@ Wasabi S3 storage from `Wasabi `__ can be used as follows. -- Determine the correct Wasabi service URL for your bucket `here `__. +- Determine the correct Wasabi service URL for your bucket `here `__. - Set environment variables with the necessary account credentials .. code-block:: console From d839850ed4087ba5a229d8ec62f2c6108483601d Mon Sep 17 00:00:00 2001 From: rhhub <7444613+rhhub@users.noreply.github.com> Date: Wed, 28 May 2025 18:32:34 -0700 Subject: [PATCH 34/51] docs: clarify ** must me between path separators --- doc/040_backup.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/040_backup.rst b/doc/040_backup.rst index a30d80402..a2092e486 100644 --- a/doc/040_backup.rst +++ b/doc/040_backup.rst @@ -346,9 +346,10 @@ A trailing ``/`` is ignored, a leading ``/`` anchors the pattern at the root dir This means, ``/bin`` matches ``/bin/bash`` but does not match ``/usr/bin/restic``. Regular wildcards cannot be used to match over the directory separator ``/``, -e.g. ``b*ash`` matches ``/bin/bash`` but does not match ``/bin/ash``. For this, -the special wildcard ``**`` can be used to match arbitrary sub-directories: The -pattern ``foo/**/bar`` matches: +e.g. ``b*ash`` matches ``/bin/bash`` but does not match ``/bin/ash``. To match +across an arbitrary number of subdirectories, use the special ``**`` wildcard. +The ``**`` must be positioned between path separators. The pattern +``foo/**/bar`` matches: * ``/dir1/foo/dir2/bar/file`` * ``/foo/bar/file`` From 91e9f659910e43ddc1068b251effbcd1d04772d1 Mon Sep 17 00:00:00 2001 From: Michele Testa Date: Tue, 5 Aug 2025 15:16:37 +0200 Subject: [PATCH 35/51] Update 020_installation.rst adding instruction for Gentoo Linux --- doc/020_installation.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/020_installation.rst b/doc/020_installation.rst index f79819837..43f5afe66 100644 --- a/doc/020_installation.rst +++ b/doc/020_installation.rst @@ -74,6 +74,16 @@ avoid any conflicts: $ dnf copr remove copart/restic +Gentoo Linux +============ + +On `Gentoo Linux `__, you can install the ``restic`` +package from the official repos using ``emerge``: + +.. code-block:: console + + # emerge -av restic + macOS ===== From c62f523e6da60d9716f780a635dc8d249ebc925e Mon Sep 17 00:00:00 2001 From: y0n3d4 <185196609+y0n3d4@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:57:29 +0200 Subject: [PATCH 36/51] Update 020_installation.rst removing command options Removed command options: their use is a user choice --- doc/020_installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/020_installation.rst b/doc/020_installation.rst index 43f5afe66..c6f368f21 100644 --- a/doc/020_installation.rst +++ b/doc/020_installation.rst @@ -82,7 +82,7 @@ package from the official repos using ``emerge``: .. code-block:: console - # emerge -av restic + # emerge restic macOS ===== From 518fbbcdc265bf3d5f29634f34347b5a37145935 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 02:10:03 +0000 Subject: [PATCH 37/51] build(deps): bump golang.org/x/crypto from 0.39.0 to 0.41.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.39.0 to 0.41.0. - [Commits](https://github.com/golang/crypto/compare/v0.39.0...v0.41.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.41.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 459e9911e..b9f8b5c80 100644 --- a/go.mod +++ b/go.mod @@ -32,13 +32,13 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 go.uber.org/automaxprocs v1.6.0 - golang.org/x/crypto v0.39.0 - golang.org/x/net v0.40.0 + golang.org/x/crypto v0.41.0 + golang.org/x/net v0.42.0 golang.org/x/oauth2 v0.28.0 - golang.org/x/sync v0.15.0 - golang.org/x/sys v0.33.0 - golang.org/x/term v0.32.0 - golang.org/x/text v0.26.0 + golang.org/x/sync v0.16.0 + golang.org/x/sys v0.35.0 + golang.org/x/term v0.34.0 + golang.org/x/text v0.28.0 golang.org/x/time v0.12.0 google.golang.org/api v0.228.0 ) diff --git a/go.sum b/go.sum index 1c45f3179..cc89c4b48 100644 --- a/go.sum +++ b/go.sum @@ -243,8 +243,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4= golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -266,8 +266,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -278,8 +278,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -299,8 +299,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -311,8 +311,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -324,8 +324,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 86a453200a1de3ff22cf2f5eba78715ec56b8d70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:36:17 +0000 Subject: [PATCH 38/51] build(deps): bump google.golang.org/api from 0.228.0 to 0.248.0 Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.228.0 to 0.248.0. - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.228.0...v0.248.0) --- updated-dependencies: - dependency-name: google.golang.org/api dependency-version: 0.248.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 55 ++++++++++++++------------- go.sum | 118 ++++++++++++++++++++++++++++++--------------------------- 2 files changed, 91 insertions(+), 82 deletions(-) diff --git a/go.mod b/go.mod index b9f8b5c80..402355a53 100644 --- a/go.mod +++ b/go.mod @@ -33,30 +33,30 @@ require ( github.com/spf13/pflag v1.0.6 go.uber.org/automaxprocs v1.6.0 golang.org/x/crypto v0.41.0 - golang.org/x/net v0.42.0 - golang.org/x/oauth2 v0.28.0 + golang.org/x/net v0.43.0 + golang.org/x/oauth2 v0.30.0 golang.org/x/sync v0.16.0 golang.org/x/sys v0.35.0 golang.org/x/term v0.34.0 golang.org/x/text v0.28.0 golang.org/x/time v0.12.0 - google.golang.org/api v0.228.0 + google.golang.org/api v0.248.0 ) require ( - cel.dev/expr v0.19.2 // indirect - cloud.google.com/go v0.118.3 // indirect - cloud.google.com/go/auth v0.15.0 // indirect + cel.dev/expr v0.24.0 // indirect + cloud.google.com/go v0.120.0 // indirect + cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.6.0 // indirect - cloud.google.com/go/iam v1.4.1 // indirect - cloud.google.com/go/monitoring v1.24.0 // indirect + cloud.google.com/go/compute/metadata v0.8.0 // indirect + cloud.google.com/go/iam v1.5.2 // indirect + cloud.google.com/go/monitoring v1.24.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect - github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect + github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect @@ -64,7 +64,8 @@ require ( github.com/felixge/fgprof v0.9.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-ini/ini v1.67.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-jose/go-jose/v4 v4.0.5 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect @@ -72,7 +73,7 @@ require ( github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect - github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/googleapis/gax-go/v2 v2.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/kr/fs v0.1.0 // indirect @@ -83,19 +84,21 @@ require ( github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect + github.com/zeebo/errs v1.4.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect - go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/sdk v1.34.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect - google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect - google.golang.org/grpc v1.71.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect + google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect + google.golang.org/grpc v1.74.2 // indirect + google.golang.org/protobuf v1.36.7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index cc89c4b48..f553414c6 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,25 @@ -cel.dev/expr v0.19.2 h1:V354PbqIXr9IQdwy4SYA4xa0HXaWq1BUPAGzugBY5V4= -cel.dev/expr v0.19.2/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= -cloud.google.com/go v0.118.3 h1:jsypSnrE/w4mJysioGdMBg4MiW/hHx/sArFpaBWHdME= -cloud.google.com/go v0.118.3/go.mod h1:Lhs3YLnBlwJ4KA6nuObNMZ/fCbOQBPuWKPoE0Wa/9Vc= -cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= -cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= +cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA= +cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q= +cloud.google.com/go/auth v0.16.5 h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI= +cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= -cloud.google.com/go/iam v1.4.1 h1:cFC25Nv+u5BkTR/BT1tXdoF2daiVbZ1RLx2eqfQ9RMM= -cloud.google.com/go/iam v1.4.1/go.mod h1:2vUEJpUG3Q9p2UdsyksaKpDzlwOrnMzS30isdReIcLM= +cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= +cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8= +cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE= cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc= cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA= -cloud.google.com/go/longrunning v0.6.5 h1:sD+t8DO8j4HKW4QfouCklg7ZC1qC4uzVZt8iz3uTW+Q= -cloud.google.com/go/longrunning v0.6.5/go.mod h1:Et04XK+0TTLKa5IPYryKf5DkpwImy6TluQ1QTLwlKmY= -cloud.google.com/go/monitoring v1.24.0 h1:csSKiCJ+WVRgNkRzzz3BPoGjFhjPY23ZTcaenToJxMM= -cloud.google.com/go/monitoring v1.24.0/go.mod h1:Bd1PRK5bmQBQNnuGwHBfUamAV1ys9049oEPHnn4pcsc= +cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE= +cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY= +cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM= +cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U= cloud.google.com/go/storage v1.51.0 h1:ZVZ11zCiD7b3k+cH5lQs/qcNaoSz3U9I0jgwVzqDlCw= cloud.google.com/go/storage v1.51.0/go.mod h1:YEJfu/Ki3i5oHC/7jyTgsGZwdQ8P9hqMqvpi5kRKGgc= -cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE= -cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= +cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4= +cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= @@ -38,8 +38,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Backblaze/blazer v0.7.2 h1:UWNHMLB+Nf+UmbO2qkVvgriODLEMz4kIyr2Hm+DVXQM= github.com/Backblaze/blazer v0.7.2/go.mod h1:T4y3EYa9IQ5J0PKc/C/J8/CEnSd3qa/lgNw938wZg10= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 h1:fYE9p3esPxA/C0rQ0AHhP0drtPXDRhaWiwg1DPqO7IU= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0/go.mod h1:BnBReJLvVYx2CS/UHOgVz2BXKXD9wsQPxZug20nZhd0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0 h1:OqVGm6Ei3x5+yZmSJG1Mh2NwHvpVmZ08CB5qJhT9Nuk= @@ -65,8 +65,8 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= -github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -96,9 +96,11 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= @@ -124,8 +126,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= @@ -199,6 +201,8 @@ github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= +github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -214,26 +218,28 @@ github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDH github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= +github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//snGVIM3Tx6QRzlQBao= -go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -266,10 +272,10 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -339,18 +345,18 @@ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxb golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs= -google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/api v0.248.0 h1:hUotakSkcwGdYUqzCRc5yGYsg4wXxpkKlW5ryVqvC1Y= +google.golang.org/api v0.248.0/go.mod h1:yAFUAF56Li7IuIQbTFoLwXTCI6XCFKueOlS7S9e4F9k= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= +google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= +google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 2403d1f139967e2cbb3d190e8d1214d9eedf1d1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:38:46 +0000 Subject: [PATCH 39/51] build(deps): bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 2 +- .github/workflows/tests.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5156228ba..2b4c71121 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Log in to the Container registry uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4da17a047..790a2d2a4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -57,7 +57,7 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Go ${{ matrix.go }} uses: actions/setup-go@v5 @@ -220,7 +220,7 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Go ${{ env.latest_go }} uses: actions/setup-go@v5 @@ -242,7 +242,7 @@ jobs: checks: write steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Go ${{ env.latest_go }} uses: actions/setup-go@v5 @@ -287,7 +287,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Docker meta id: meta From 0a6296bfde2b1271426f932bbe59e3fbe2129ecc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:58:21 +0000 Subject: [PATCH 40/51] build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.6.1 to 1.6.2. - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/go-mgmt-sdk-release-guideline.md) - [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.6.1...sdk/storage/azblob/v1.6.2) --- updated-dependencies: - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob dependency-version: 1.6.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 402355a53..65eba8d20 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,9 @@ godebug winsymlink=0 require ( cloud.google.com/go/storage v1.51.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Backblaze/blazer v0.7.2 github.com/Microsoft/go-winio v0.6.2 github.com/anacrolix/fuse v0.3.1 @@ -68,7 +68,7 @@ require ( github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/goccy/go-json v0.10.5 // indirect - github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.3 // indirect github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect diff --git a/go.sum b/go.sum index f553414c6..ad1804f6f 100644 --- a/go.sum +++ b/go.sum @@ -20,18 +20,18 @@ cloud.google.com/go/storage v1.51.0 h1:ZVZ11zCiD7b3k+cH5lQs/qcNaoSz3U9I0jgwVzqDl cloud.google.com/go/storage v1.51.0/go.mod h1:YEJfu/Ki3i5oHC/7jyTgsGZwdQ8P9hqMqvpi5kRKGgc= cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4= cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 h1:Wc1ml6QlJs2BHQ/9Bqu1jiyggbsSjramq2oUmp5WeIo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 h1:FwladfywkNirM+FZYLBR2kBz5C8Tg0fw5w5Y7meRXWI= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2/go.mod h1:vv5Ad0RrIoT1lJFdWBZwt4mB1+j+V8DUroixmKDTCdk= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= 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.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= @@ -107,8 +107,8 @@ github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= +github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= From f18b8ad42530a5079b8d0d5ed80ab1049ece77fa Mon Sep 17 00:00:00 2001 From: Dominik Schulz Date: Sun, 27 Jul 2025 17:14:06 +0200 Subject: [PATCH 41/51] Mark HTTP Error 507 as permanent This change classifies HTTP error 507 (Insufficient Storage) as a permanent error that should not be retried. I keep running into this once in a while and there is literally no point in retrying when the server is full. Fixes #5429 Signed-off-by: Dominik Schulz --- internal/backend/rest/rest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/backend/rest/rest.go b/internal/backend/rest/rest.go index 8df91beb3..5776f284f 100644 --- a/internal/backend/rest/rest.go +++ b/internal/backend/rest/rest.go @@ -182,7 +182,7 @@ func (b *Backend) IsPermanentError(err error) bool { var rerr *restError if errors.As(err, &rerr) { - if rerr.StatusCode == http.StatusRequestedRangeNotSatisfiable || rerr.StatusCode == http.StatusUnauthorized || rerr.StatusCode == http.StatusForbidden { + if rerr.StatusCode == http.StatusRequestedRangeNotSatisfiable || rerr.StatusCode == http.StatusUnauthorized || rerr.StatusCode == http.StatusForbidden || rerr.StatusCode == http.StatusInsufficientStorage { return true } } From 49abea6952b6b54c5dcb22387e81fa42526b24c0 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 5 Sep 2025 19:07:09 +0200 Subject: [PATCH 42/51] add changelog --- changelog/unreleased/issue-5429 | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 changelog/unreleased/issue-5429 diff --git a/changelog/unreleased/issue-5429 b/changelog/unreleased/issue-5429 new file mode 100644 index 000000000..e8e7ca513 --- /dev/null +++ b/changelog/unreleased/issue-5429 @@ -0,0 +1,8 @@ +Bugfix: do not retry if rest-server runs out of space + +Rest-server return error `507 Insufficient Storage` if no more storage +capacity is available at the server. Restic now no longer retries uploads +in this case. + +https://github.com/restic/restic/issues/5429 +https://github.com/restic/restic/pull/5452 From 73995b818a62a36ff1a7f9641a9c6b51c58958e2 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Thu, 12 Jun 2025 22:17:57 +0200 Subject: [PATCH 43/51] backup: do not crash if nodeFromFileInfo fails this could crash in two cases: - if a directory is deleted between restic stating it and trying to list its directory content. - when restic tries to list the parent directory of a backup target, but the parent directory has been deleted. return an error in this case instead. --- internal/archiver/archiver.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index 4a6577d27..e509f9f85 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -264,6 +264,11 @@ func (arch *Archiver) trackItem(item string, previous, current *restic.Node, s I // nodeFromFileInfo returns the restic node from an os.FileInfo. func (arch *Archiver) nodeFromFileInfo(snPath, filename string, meta ToNoder, ignoreXattrListError bool) (*restic.Node, error) { node, err := meta.ToNode(ignoreXattrListError) + // node does not exist. This prevents all further processing for this file. + // If an error and a node are returned, then preserve as much data as possible (see below). + if err != nil && node == nil { + return nil, err + } if !arch.WithAtime { node.AccessTime = node.ModTime } From fc81df3f5448f4f263a34f04207c4bcc9c06ce49 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Thu, 12 Jun 2025 22:23:40 +0200 Subject: [PATCH 44/51] backup: do not fail backup is some parent folder is inaccessible Handle errors for parent directories of backup directories in the same way as all other file access errors during a backup. --- internal/archiver/archiver.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index e509f9f85..981b1fecc 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -723,8 +723,14 @@ func (arch *Archiver) saveTree(ctx context.Context, snPath string, atree *tree, arch.trackItem(snItem, oldNode, n, is, time.Since(start)) }) if err != nil { + err = arch.error(join(snPath, name), err) + if err == nil { + // ignore error + continue + } return futureNode{}, 0, err } + nodes = append(nodes, fn) } From d57b01d6ebd91461f5c797aa6a6e4c78899bcc4b Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Thu, 12 Jun 2025 22:37:57 +0200 Subject: [PATCH 45/51] backup: test that missing parent directory is correctly handled --- internal/archiver/archiver_test.go | 39 +++++++++++++++++++----------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index 906c83011..9cbce7c76 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -1870,12 +1870,13 @@ func TestArchiverErrorReporting(t *testing.T) { } var tests = []struct { - name string - src TestDir - want TestDir - prepare func(t testing.TB) - errFn ErrorFunc - mustError bool + name string + targets []string + src TestDir + want TestDir + prepare func(t testing.TB) + errFn ErrorFunc + errStr string }{ { name: "no-error", @@ -1888,8 +1889,8 @@ func TestArchiverErrorReporting(t *testing.T) { src: TestDir{ "targetfile": TestFile{Content: "foobar"}, }, - prepare: chmodUnreadable("targetfile"), - mustError: true, + prepare: chmodUnreadable("targetfile"), + errStr: "open targetfile: permission denied", }, { name: "file-unreadable-ignore-error", @@ -1910,8 +1911,8 @@ func TestArchiverErrorReporting(t *testing.T) { "targetfile": TestFile{Content: "foobar"}, }, }, - prepare: chmodUnreadable("subdir/targetfile"), - mustError: true, + prepare: chmodUnreadable("subdir/targetfile"), + errStr: "open subdir/targetfile: permission denied", }, { name: "file-subdir-unreadable-ignore-error", @@ -1929,6 +1930,12 @@ func TestArchiverErrorReporting(t *testing.T) { prepare: chmodUnreadable("subdir/targetfile"), errFn: ignoreErrorForBasename("targetfile"), }, + { + name: "parent-dir-missing", + targets: []string{"subdir/missing"}, + src: TestDir{}, + errStr: "stat subdir: no such file or directory", + }, } for _, test := range tests { @@ -1948,14 +1955,18 @@ func TestArchiverErrorReporting(t *testing.T) { arch := New(repo, fs.Track{FS: fs.Local{}}, Options{}) arch.Error = test.errFn - _, snapshotID, _, err := arch.Snapshot(ctx, []string{"."}, SnapshotOptions{Time: time.Now()}) - if test.mustError { - if err != nil { + target := test.targets + if len(target) == 0 { + target = []string{"."} + } + _, snapshotID, _, err := arch.Snapshot(ctx, target, SnapshotOptions{Time: time.Now()}) + if test.errStr != "" { + if strings.Contains(err.Error(), test.errStr) { t.Logf("found expected error (%v), skipping further checks", err) return } - t.Fatalf("expected error not returned by archiver") + t.Fatalf("expected error (%v) not returned by archiver, got (%v)", test.errStr, err) return } From b67b88a0c0c92681a13c90f8fa6dc509f28eea74 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Thu, 12 Jun 2025 22:43:45 +0200 Subject: [PATCH 46/51] backup: test that parent directory errors can be correctly filtered --- internal/archiver/archiver_test.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index 9cbce7c76..cc858eeee 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -1846,8 +1846,8 @@ func TestArchiverParent(t *testing.T) { func TestArchiverErrorReporting(t *testing.T) { ignoreErrorForBasename := func(basename string) ErrorFunc { return func(item string, err error) error { - if filepath.Base(item) == "targetfile" { - t.Logf("ignoring error for targetfile: %v", err) + if filepath.Base(item) == basename { + t.Logf("ignoring error for %v: %v", basename, err) return nil } @@ -1936,6 +1936,14 @@ func TestArchiverErrorReporting(t *testing.T) { src: TestDir{}, errStr: "stat subdir: no such file or directory", }, + { + name: "parent-dir-missing-filtered", + targets: []string{"targetfile", "subdir/missing"}, + src: TestDir{ + "targetfile": TestFile{Content: "foobar"}, + }, + errFn: ignoreErrorForBasename("subdir"), + }, } for _, test := range tests { From 31f87b61886376f3a4115009158853d6d1c9db38 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Mon, 21 Jul 2025 21:57:05 +0200 Subject: [PATCH 47/51] add changelog --- changelog/unreleased/pull-5421 | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 changelog/unreleased/pull-5421 diff --git a/changelog/unreleased/pull-5421 b/changelog/unreleased/pull-5421 new file mode 100644 index 000000000..3a76d4fcd --- /dev/null +++ b/changelog/unreleased/pull-5421 @@ -0,0 +1,8 @@ +Bugfix: Fix rare crash if directory is removed during backup + +In restic 0.18.0, the `backup` command could crash if a directory is removed +inbetween reading its metadata and listing its directory content. + +This has been fixed. + +https://github.com/restic/restic/pull/5421 From b75f80ae5f59c8c4383f45feda17afd2a45987ab Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 5 Sep 2025 19:35:25 +0200 Subject: [PATCH 48/51] backup: fix test on windows --- internal/archiver/archiver_test.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index cc858eeee..098e13395 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -1876,7 +1876,7 @@ func TestArchiverErrorReporting(t *testing.T) { want TestDir prepare func(t testing.TB) errFn ErrorFunc - errStr string + errStr []string }{ { name: "no-error", @@ -1890,7 +1890,7 @@ func TestArchiverErrorReporting(t *testing.T) { "targetfile": TestFile{Content: "foobar"}, }, prepare: chmodUnreadable("targetfile"), - errStr: "open targetfile: permission denied", + errStr: []string{"open targetfile: permission denied"}, }, { name: "file-unreadable-ignore-error", @@ -1912,7 +1912,7 @@ func TestArchiverErrorReporting(t *testing.T) { }, }, prepare: chmodUnreadable("subdir/targetfile"), - errStr: "open subdir/targetfile: permission denied", + errStr: []string{"open subdir/targetfile: permission denied"}, }, { name: "file-subdir-unreadable-ignore-error", @@ -1934,7 +1934,7 @@ func TestArchiverErrorReporting(t *testing.T) { name: "parent-dir-missing", targets: []string{"subdir/missing"}, src: TestDir{}, - errStr: "stat subdir: no such file or directory", + errStr: []string{"stat subdir: no such file or directory", "CreateFile subdir: The system cannot find the file specified"}, }, { name: "parent-dir-missing-filtered", @@ -1968,10 +1968,13 @@ func TestArchiverErrorReporting(t *testing.T) { target = []string{"."} } _, snapshotID, _, err := arch.Snapshot(ctx, target, SnapshotOptions{Time: time.Now()}) - if test.errStr != "" { - if strings.Contains(err.Error(), test.errStr) { - t.Logf("found expected error (%v), skipping further checks", err) - return + if test.errStr != nil { + // check if any of the expected errors are contained in the error message + for _, errStr := range test.errStr { + if strings.Contains(err.Error(), errStr) { + t.Logf("found expected error (%v)", err) + return + } } t.Fatalf("expected error (%v) not returned by archiver, got (%v)", test.errStr, err) From 37851827c56a1c70eaee64cdd07608fc8f6a4e65 Mon Sep 17 00:00:00 2001 From: gregoster <47227368+gregoster@users.noreply.github.com> Date: Fri, 5 Sep 2025 13:09:27 -0600 Subject: [PATCH 49/51] EOPNOTSUPP can be returned if the filesystem does not support xattrs (#5344) --------- Co-authored-by: Greg Oster --- changelog/unreleased/issue-5344 | 7 +++++++ internal/fs/node_xattr.go | 5 ++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 changelog/unreleased/issue-5344 diff --git a/changelog/unreleased/issue-5344 b/changelog/unreleased/issue-5344 new file mode 100644 index 000000000..38119d0ec --- /dev/null +++ b/changelog/unreleased/issue-5344 @@ -0,0 +1,7 @@ +Bugfix: Ignore EOPNOTSUPP as an error for xattr + +Restic 0.18.0 added xattr support for NetBSD 10+, but not all NetBSD +filesystems support xattrs. Other BSD systems can likewise return +EOPNOTSUPP, so restic now simply ignores EOPNOTSUPP errors for xattrs. + +https://github.com/restic/restic/issues/5344 diff --git a/internal/fs/node_xattr.go b/internal/fs/node_xattr.go index 2a2b5c0fb..f1119fe51 100644 --- a/internal/fs/node_xattr.go +++ b/internal/fs/node_xattr.go @@ -53,9 +53,8 @@ func handleXattrErr(err error) error { case *xattr.Error: // On Linux, xattr calls on files in an SMB/CIFS mount can return - // ENOATTR instead of ENOTSUP. - switch e.Err { - case syscall.ENOTSUP, xattr.ENOATTR: + // ENOATTR instead of ENOTSUP. BSD can return EOPNOTSUPP. + if e.Err == syscall.ENOTSUP || e.Err == syscall.EOPNOTSUPP || e.Err == xattr.ENOATTR { return nil } return errors.WithStack(e) From 06cc6017b838444ca3df8035176b47cfa51993d2 Mon Sep 17 00:00:00 2001 From: greatroar <61184462+greatroar@users.noreply.github.com> Date: Thu, 4 Sep 2025 11:23:05 +0200 Subject: [PATCH 50/51] internal/restic: Fix panic in ParseDuration Fixes #5485. Includes test case by @MichaelEischer. --- internal/restic/duration.go | 3 +-- internal/restic/duration_test.go | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/restic/duration.go b/internal/restic/duration.go index 831971fe0..6ab4c3c79 100644 --- a/internal/restic/duration.go +++ b/internal/restic/duration.go @@ -4,7 +4,6 @@ import ( "fmt" "strconv" "strings" - "unicode" "github.com/restic/restic/internal/errors" ) @@ -52,7 +51,7 @@ func nextNumber(input string) (num int, rest string, err error) { } for i, s := range input { - if !unicode.IsNumber(s) { + if s < '0' || s > '9' { rest = input[i:] break } diff --git a/internal/restic/duration_test.go b/internal/restic/duration_test.go index f03aa5553..c5f0390db 100644 --- a/internal/restic/duration_test.go +++ b/internal/restic/duration_test.go @@ -37,6 +37,9 @@ func TestNextNumber(t *testing.T) { { input: "5d ", num: 5, rest: "d ", }, + { + input: "5", num: 5, rest: "", + }, } for _, test := range tests { @@ -78,6 +81,7 @@ func TestParseDuration(t *testing.T) { {input: "2w", err: true}, {input: "1y4m3w1d", err: true}, {input: "s", err: true}, + {input: "\xdf\x80", err: true}, // NKO DIGIT ZERO; we want ASCII digits } for _, test := range tests { From 4998fd68a7ef56d29219f4df40b525ee048d420b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 01:57:28 +0000 Subject: [PATCH 51/51] build(deps): bump docker/login-action from 3.4.0 to 3.5.0 Bumps [docker/login-action](https://github.com/docker/login-action) from 3.4.0 to 3.5.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/74a5d142397b4f367a81961eba4e8cd7edddf772...184bdaa0721073962dff0199f1fb9940f07167d1) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 2b4c71121..e4c264fba 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v5 - name: Log in to the Container registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 + uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }}