Compare commits

..

616 Commits

Author SHA1 Message Date
Alexander Neumann
277c8f5029 Add version for 0.17.0 2024-07-26 11:30:37 +02:00
Alexander Neumann
65748fcd6b Update manpages and auto-completion 2024-07-26 11:30:37 +02:00
Alexander Neumann
905da91e61 Generate CHANGELOG.md for 0.17.0 2024-07-26 11:29:39 +02:00
Alexander Neumann
ad09d21aaf Prepare changelog for 0.17.0 2024-07-26 11:28:55 +02:00
Michael Eischer
aa69b15f3e Merge pull request #4936 from restic/828-fix-changelog
doc: Remove unrelated PR URL from changelog entry
2024-07-25 16:48:31 +00:00
Leo R. Lundgren
5a8c915443 doc: Remove unrelated PR URL from changelog entry 2024-07-25 14:27:43 +02:00
Michael Eischer
2be8793de2 Merge pull request #4933 from MichaelEischer/backup-source
docs: Replace all uses of target in relation to backup
2024-07-24 21:08:39 +02:00
Michael Eischer
fe2d1dfd84 Merge pull request #4932 from restic/polish-changelogs
doc: Polish unreleased changelogs
2024-07-24 18:47:03 +00:00
Michael Eischer
636bf2915e minor tweaks 2024-07-24 20:40:15 +02:00
Michael Eischer
729e009485 replace all uses of target in relation to backup 2024-07-24 19:40:53 +02:00
Michael Eischer
0ddff92323 Merge pull request #4930 from MichaelEischer/update-xattr-lib
update xattr library to 0.4.10
2024-07-24 19:06:56 +02:00
Michael Eischer
4d6cd8f069 Merge pull request #4931 from restic/doc-vss-options
doc: Clarify VSS extended options
2024-07-23 20:54:38 +00:00
Leo R. Lundgren
77ec8ae091 doc: Polish unreleased changelogs 2024-07-23 00:51:57 +02:00
Leo R. Lundgren
c54d5a8eca doc: Clarify VSS extended options 2024-07-23 00:37:56 +02:00
Michael Eischer
948c6f1da3 update xattr library to 0.4.10 2024-07-22 22:16:26 +02:00
Michael Eischer
fa5ff0873a Merge pull request #4925 from MichaelEischer/fix-restore-truncation
restore: Fix truncation of uptodate files
2024-07-21 12:28:12 +02:00
Michael Eischer
b5d0586b26 Merge pull request #4926 from MichaelEischer/restore-size-only-files
restorer: only show size in text output for files
2024-07-21 12:06:15 +02:00
Michael Eischer
0dcac90bea restorer: don't track already uptodate blobs 2024-07-21 12:03:56 +02:00
Michael Eischer
10efa77103 restorer: add test for file truncation case 2024-07-21 12:03:56 +02:00
Michael Eischer
6f8e17a463 restorer: minor code cleanups 2024-07-21 12:03:56 +02:00
Michael Eischer
5d6ce59a8d restorer: also truncate files if their content is already uptodate
Files for which no blobs have to be restored, still have to be truncated
to the correct size. Take a file with content "foobar" that should be
replaced by restore with content "foo". The first three bytes are
already uptodate, such that no data has to be written. As file
truncation normally happens when writing data, a special case is
necessary.

This no blobs written special case is unified with the empty file
special case.
2024-07-21 12:03:56 +02:00
Michael Eischer
59c880fce3 restorer: only show size in text output for files 2024-07-20 12:46:28 +02:00
Michael Eischer
4f4598a1e3 Merge pull request #4905 from alex-kattathra-johnson/issue-4902
Update snapshot summary on rewrite
2024-07-16 18:06:15 +00:00
Alex Johnson
3bf2927006 Update snapshot summary on rewrite
Signed-off-by: Alex Johnson <hello@alex-johnson.net>
2024-07-16 12:06:50 -05:00
Michael Eischer
1a45f05e19 Merge pull request #4921 from MichaelEischer/restorer-bugs
restore: fix cancelation and partial updates of large files
2024-07-14 11:38:58 +02:00
Michael Eischer
dcfffd7779 restore: extend overwrite test for small files 2024-07-14 11:30:41 +02:00
Michael Eischer
44e3610b32 restore: progress bar total on windows 2024-07-14 11:21:11 +02:00
Michael Eischer
4a9536b829 amend restore overwrite changelog 2024-07-14 11:21:11 +02:00
Michael Eischer
98cfb2c4c8 restore: test progress reporting for partially up to date files 2024-07-14 11:21:11 +02:00
Michael Eischer
26aa65e0d4 restore: add regression test for corrupt in-place restore of large file 2024-07-14 11:21:11 +02:00
Michael Eischer
2833b2f699 restore: fix progress bar for partially up to date files 2024-07-14 11:21:11 +02:00
Michael Eischer
c77b2d5ca2 restore: avoid long cancelation delay for frequently used blobs 2024-07-14 11:21:11 +02:00
Michael Eischer
f64191da9c restore: improve reporting of cancelation errors 2024-07-14 11:21:08 +02:00
Michael Eischer
2976a666c3 Merge pull request #4920 from MichaelEischer/fix-ls-ncdu-toplevel
ls: fix handling of toplevel directories in ncdu output
2024-07-14 11:09:57 +02:00
Michael Eischer
bdf24dc8f9 ls: extend test sample with a second toplevel file 2024-07-13 10:22:01 +02:00
Michael Eischer
5671dfb481 ls: fix ncdu output for file with timestamp before 1970 2024-07-13 10:21:02 +02:00
Michael Eischer
ff9238ebf1 ls: use / as top-level dir name in ncdu output 2024-07-12 23:46:50 +02:00
Michael Eischer
2971a769da restore: fix corrupt restore of partially up to date files 2024-07-12 22:27:00 +02:00
Michael Eischer
40e5163114 restore: properly cancel file verification 2024-07-12 22:26:22 +02:00
Michael Eischer
31887ea9aa restore: fix hang on command cancelation 2024-07-12 22:24:35 +02:00
Michael Eischer
9f66065237 ls: fix handling of toplevel directories in ncdu output 2024-07-12 21:49:35 +02:00
Michael Eischer
375c572c4f Merge pull request #4884 from MichaelEischer/lock-and-not-exist-error-codes
Return different exit code if repo is locked or does not exist
2024-07-12 21:05:52 +02:00
Michael Eischer
6010c98b3f Merge pull request #4918 from MichaelEischer/restore-dont-delete-target-if-file
restore: do not delete target if it is a file
2024-07-12 21:05:04 +02:00
Michael Eischer
36cc62075c add exit code changelog 2024-07-10 22:13:37 +02:00
Michael Eischer
54ca27a6f2 doc: update init check with exit code 10 2024-07-10 22:13:37 +02:00
Michael Eischer
1328cdd002 Merge pull request #4917 from MichaelEischer/dry-run-speed-up-hint
restore: document how to speed up dry-run
2024-07-10 20:12:39 +00:00
Michael Eischer
8731667156 restore: do not delete target if it is a file
This is implicitly achieved by creating the target directory as the
first step, which will fail if a file already exist in its place.
2024-07-10 22:08:49 +02:00
Michael Eischer
294c8524ed doc: document exit codes 2024-07-10 21:47:24 +02:00
Michael Eischer
94fdca08c4 return exit code 10 if repository does not exist 2024-07-10 21:46:26 +02:00
Michael Eischer
d76a78aa99 return exit code 11 if the repository could not be locked 2024-07-10 21:37:32 +02:00
Michael Eischer
3b7228c8c1 explicitly document exit code 1 on error 2024-07-10 21:35:46 +02:00
Michael Eischer
f560152627 restore: document how to speed up dry-run 2024-07-10 21:34:10 +02:00
Michael Eischer
36a2857df6 Merge pull request #4916 from restic/dependabot/go_modules/google.golang.org/grpc-1.64.1
build(deps): bump google.golang.org/grpc from 1.64.0 to 1.64.1
2024-07-10 20:28:11 +02:00
Michael Eischer
5e1d0ffd99 Merge pull request #4911 from MichaelEischer/fix-filtered-ls-ncdu
ls: Fix --ncdu output with path filters and fix disk size
2024-07-10 20:27:42 +02:00
dependabot[bot]
8c7a2f1792 build(deps): bump google.golang.org/grpc from 1.64.0 to 1.64.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.64.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.64.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-10 18:23:27 +00:00
Michael Eischer
d8dbc71deb Merge pull request #4908 from MichaelEischer/improve-anonymous-s3
S3: Improve anonymous access
2024-07-10 20:19:23 +02:00
Michael Eischer
5067a40bd8 update ncdu changelog 2024-07-10 20:18:53 +02:00
Michael Eischer
79c9fc45a9 ls: fix disk size in --ncdu output
Ncdu expects a size in disk blocks. Round up to the next full block.
Otherwise, small files with size below 255bytes would be rounded down to
0B by ncdu.
2024-07-10 20:18:53 +02:00
Michael Eischer
15419d603d ls: add missing intermediate directories to --ncdu output 2024-07-10 20:18:53 +02:00
Michael Eischer
dc0db4eda4 add s3 anonymous authentication changelog entry 2024-07-10 20:10:27 +02:00
Michael Eischer
f74e70cc36 s3: forbid anonymous authentication unless explicitly requested 2024-07-10 20:10:27 +02:00
Michael Eischer
7cea5402ff Merge pull request #4913 from MichaelEischer/always-show-snapshot-size
snapshots: also show snapshot size in compact view
2024-07-10 20:05:41 +02:00
Michael Eischer
a8fc67d68b Merge pull request #4914 from drdo/minor-correction-design-doc
doc: Update index explanation to match the example
2024-07-09 18:46:47 +00:00
Daniel Oliveira
94c3d3f097 doc: Update index explanation to match the example
In commit 00575ec the example was changed to three data blobs due to the deprecation of mixed pack files
but the following description was not updated to reflect this.
2024-07-09 00:18:09 +01:00
Michael Eischer
f4ecb9d615 Merge pull request #4909 from MichaelEischer/properly-set-dev-version
Fix VERSION file and dev version in binaries
2024-07-08 20:15:20 +02:00
Michael Eischer
c309ffb35b Merge pull request #4912 from MichaelEischer/restore-delete-preserve-root
restore: forbid --target / --delete unless include/exclude is specified
2024-07-08 20:14:44 +02:00
Michael Eischer
f980f5647e snapshots: also show snapshot size in compact view 2024-07-08 20:00:26 +02:00
Michael Eischer
b71a885b92 Merge pull request #4907 from MichaelEischer/bump-dependencies
Bump some dependencies
2024-07-08 19:32:25 +02:00
Michael Eischer
24a7ff45f2 Merge pull request #4904 from MichaelEischer/fix-status-cleanup
ui/termstatus: fix clearing status lines
2024-07-08 19:31:55 +02:00
Michael Eischer
00d9ce7bee fix setting version in build script 2024-07-08 19:30:17 +02:00
Michael Eischer
a0cac7fcd1 helpers/prepare-release: write dev version to VERSION file 2024-07-07 14:04:09 +02:00
Michael Eischer
1856f4d87a restore: forbid --target / --delete unless include/exclude is specified 2024-07-07 13:54:45 +02:00
Michael Eischer
894ec9d05d ls: fix broken folder if --ncdu an file filters are combined 2024-07-07 13:08:41 +02:00
Michael Eischer
4b364940aa s3: use http client with configured timeouts for s3 IAM communication
The default client has no timeouts configured opening network
connections. Thus, if 169.254.169.254 is inaccessible, then the client
would wait for until the operating system gives up, which will take
several minutes.
2024-07-07 11:32:40 +02:00
Michael Eischer
a2a2401a68 s3: prevent repeated credential queries with anonymous authentication 2024-07-07 11:31:04 +02:00
Michael Eischer
be98402ac6 Merge pull request #4906 from joram-berger/patch-1
Add explanation to restic diff symbols
2024-07-06 19:07:08 +00:00
Michael Eischer
10765151d3 doc: fine tune description of diff command 2024-07-06 21:01:58 +02:00
Michael Eischer
f3a3c46153 bump some dependencies 2024-07-06 17:34:28 +02:00
Joram Berger
33de00bba0 Add explanation to restic diff symbols
Explain what the characters for each file in a restic diff output mean.
2024-07-06 16:47:04 +02:00
Michael Eischer
aedead2823 ui/termstatus: fix clearing status lines
To clear the status lines, they should be set to an empty array to
prevent future updates of those lines. Setting the status lines to an
array containing an empty string is wrong as this causes the output to
continuously add that empty status line after each message.
2024-07-06 11:27:35 +02:00
Michael Eischer
8e27a934de Merge pull request #4881 from MichaelEischer/restore-delete-actual
restore: add `--delete` option
2024-07-05 22:52:54 +02:00
Michael Eischer
54316978cd add restore --delete changelog 2024-07-05 22:38:39 +02:00
Michael Eischer
569f111cb1 restore: document --delete option 2024-07-05 22:38:39 +02:00
Michael Eischer
868219aad1 restore: test --dry-run plus --delete 2024-07-05 22:38:39 +02:00
Michael Eischer
aa8e18cf32 restore: add deletions to progress output 2024-07-05 22:38:39 +02:00
Michael Eischer
f4b15fdd96 restore: allow deleting a directory to replace it with a file
When the `--delete` option is specified, recursively delete directories
that should be replaced with a file.
2024-07-05 22:38:39 +02:00
Michael Eischer
168fc09d5f restore: use case insensitive file name comparison on windows 2024-07-05 22:38:39 +02:00
Michael Eischer
013a6156bd restore: remove unused parameter from SelectFilter 2024-07-05 22:38:39 +02:00
Michael Eischer
ac44bdf6dd restore: add --delete option to remove files that are not in snapshot 2024-07-05 22:38:39 +02:00
Michael Eischer
144e2a451f restore: track expected filenames in a folder 2024-07-05 21:03:35 +02:00
Michael Eischer
d762f4ee64 restore: simplfy selectFilter arguments 2024-07-05 21:03:35 +02:00
Michael Eischer
a9a60f77ce restore: optimize memory usage 2024-07-05 21:03:35 +02:00
Michael Eischer
1369658a32 archiver: extract Readdirnames to fs package 2024-07-05 21:03:34 +02:00
Michael Eischer
83fdcf21fe Merge pull request #4839 from MichaelEischer/restore-dry-run
restore: add `--dry-run` and extended progress output
2024-07-05 21:02:13 +02:00
Michael Eischer
a90665028f doc: fix syntax error 2024-07-05 20:41:27 +02:00
Michael Eischer
ae978d60cc restore: pass action enum to restore progress 2024-07-05 20:41:27 +02:00
Michael Eischer
798256ec52 restore: add dry-run docs 2024-07-05 20:41:27 +02:00
Michael Eischer
83351f42e3 restore: add dry-run support 2024-07-05 20:41:27 +02:00
Michael Eischer
c47bf33884 restore: print processed files at maximum verbosity 2024-07-05 20:41:27 +02:00
Michael Eischer
2a7d257036 Merge pull request #4882 from MichaelEischer/improve-check-output
check: improve output if repository is damaged
2024-07-05 20:16:45 +02:00
Michael Eischer
283038056e doc: suggest to follow troubleshooting steps if check reports error 2024-07-05 20:04:25 +02:00
Michael Eischer
fdc7349aa4 check: improve error on damaged index
Always return the `repository contains errors` message if a repository
is damaged and must be repaired. Also provide specific instructions how
to repair the index.
2024-07-05 20:04:25 +02:00
Michael Eischer
a03e00373c update repair packs changelog 2024-07-05 20:04:25 +02:00
Michael Eischer
879ba07a87 check: only show additional files if verbose output is enabled
Additional files are nearly always caused by interrupted backup runs.
This is unproblematic, thus don't pollute the check output with it.
2024-07-05 20:04:25 +02:00
Michael Eischer
6d9dfff1cb check: point users towards the troubleshooting guide if repo has errors 2024-07-05 20:04:25 +02:00
Michael Eischer
c9a4a95848 check: suggest using repair packs to repair truncated pack files
Previously, that help message was only shown for running `check
--read-data`.
2024-07-05 20:04:25 +02:00
Michael Eischer
da338d5aa8 check: tweak wording of repair packs message
By now, the message is also shown for truncated or otherwise damaged pack
files, not just those with corrupted blobs.
2024-07-05 20:04:25 +02:00
Michael Eischer
1671a3fe2e check: hide message about additional files if error in repo
The message says "[...] addition files were found [...]. This is
non-critical [...]". Unless users are highly experienced with restic,
it's hard to correctly interpret what "This" refers to. Thus, just hide
the message if there is a real problem.
2024-07-05 20:04:25 +02:00
Michael Eischer
b1250eead9 check: mark s3legacy layout and legacy indexes are error 2024-07-05 20:04:25 +02:00
Michael Eischer
66a67d568d Merge pull request #4885 from MichaelEischer/clarify-path-option
Clarify semantics of `--path` option and update manual_rest.rst
2024-07-05 19:53:15 +02:00
Michael Eischer
737389ea68 Merge pull request #4896 from MichaelEischer/fix-subfolder-help-text
man: work around broken rendering of <snapshotID>:<subfolder> help text
2024-07-04 22:06:51 +02:00
Michael Eischer
6fadc0131b Merge pull request #4883 from MichaelEischer/fix-check-cache
check: fix cachedir creation when using default location
2024-07-04 22:06:28 +02:00
Michael Eischer
a44e4bdd40 man: work around broken rendering of <snapshotID>:<subfolder> help text 2024-07-03 20:39:59 +02:00
Michael Eischer
639326903c Merge pull request #4893 from szepeviktor/typos
Fix typos
2024-07-03 18:09:40 +00:00
Viktor Szépe
ac00229386 Fix typos 2024-07-03 20:02:06 +02:00
Michael Eischer
278ec55d3f Merge pull request #4894 from eltociear/patch-1
docs: update 045_working_with_repos.rst
2024-07-03 17:26:39 +00:00
Ikko Eltociear Ashimine
a60643de9c docs: update 045_working_with_repos.rst
colums -> columns
2024-07-03 14:31:11 +09:00
Michael Eischer
a72b418319 Merge pull request #4889 from restic/dependabot/go_modules/github.com/spf13/cobra-1.8.1
build(deps): bump github.com/spf13/cobra from 1.8.0 to 1.8.1
2024-07-01 21:02:47 +00:00
Michael Eischer
9e8d7c3ad4 Merge pull request #4887 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/azidentity-1.7.0
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.6.0 to 1.7.0
2024-07-01 21:00:58 +00:00
dependabot[bot]
f02cb8eb62 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.6.0 to 1.7.0.
- [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.7.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 20:50:05 +00:00
Michael Eischer
7a21924d72 Merge pull request #4891 from restic/dependabot/go_modules/golang.org/x/oauth2-0.21.0
build(deps): bump golang.org/x/oauth2 from 0.20.0 to 0.21.0
2024-07-01 20:49:49 +00:00
Michael Eischer
cef24bdcf4 Merge pull request #4890 from restic/dependabot/go_modules/github.com/klauspost/compress-1.17.9
build(deps): bump github.com/klauspost/compress from 1.17.8 to 1.17.9
2024-07-01 20:45:57 +00:00
Michael Eischer
97969e515d Merge pull request #4886 from restic/dependabot/github_actions/docker/build-push-action-6
build(deps): bump docker/build-push-action from 5 to 6
2024-07-01 20:39:44 +00:00
Michael Eischer
74ef20b406 Merge pull request #4888 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/azcore-1.12.0
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.11.1 to 1.12.0
2024-07-01 20:36:04 +00:00
Michael Eischer
c3ad56474d Merge branch 'patch-release' 2024-07-01 21:49:39 +02:00
Alexander Neumann
5820dccaef Set development version for 0.16.5 2024-07-01 21:25:34 +02:00
Alexander Neumann
fe9f142b52 Add version for 0.16.5 2024-07-01 21:25:34 +02:00
Alexander Neumann
6ae760751a Generate CHANGELOG.md for 0.16.5 2024-07-01 21:25:33 +02:00
Alexander Neumann
2fa1b42706 Prepare changelog for 0.16.5 2024-07-01 21:25:33 +02:00
dependabot[bot]
e939c9fd6c build(deps): bump golang.org/x/oauth2 from 0.20.0 to 0.21.0
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.20.0 to 0.21.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.20.0...v0.21.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 01:41:05 +00:00
dependabot[bot]
59b5eacd0f build(deps): bump github.com/klauspost/compress from 1.17.8 to 1.17.9
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.8 to 1.17.9.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml)
- [Commits](https://github.com/klauspost/compress/compare/v1.17.8...v1.17.9)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 01:40:59 +00:00
dependabot[bot]
3de98f11f0 build(deps): bump github.com/spf13/cobra from 1.8.0 to 1.8.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 01:40:50 +00:00
dependabot[bot]
6171389803 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore
Bumps [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) from 1.11.1 to 1.12.0.
- [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.11.1...sdk/azcore/v1.12.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azcore
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 01:40:44 +00:00
dependabot[bot]
bda7aba97d build(deps): bump docker/build-push-action from 5 to 6
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 01:15:18 +00:00
Michael Eischer
aa33af3e75 update command help docs 2024-06-30 20:34:36 +02:00
Michael Eischer
ed904dfac0 clarify that all paths specified using --path option must match 2024-06-30 20:32:36 +02:00
Michael Eischer
ce0cbc7a36 check: fix cachedir creation when using default location 2024-06-30 12:04:57 +02:00
Michael Eischer
132965fd5c Merge pull request #4864 from MichaelEischer/restore-delete
restore: improve file type mismatch handling
2024-06-26 21:27:57 +02:00
Michael Eischer
9817126341 Merge pull request #4863 from MichaelEischer/safer-repo-init2
repository: prevent initialization if a snapshot exists
2024-06-26 21:11:11 +02:00
Michael Eischer
ca04a88e65 Merge pull request #4879 from restic/backport-azure-cli-option
Backport azure cli option
2024-06-26 21:07:16 +02:00
Michael Eischer
12e858b7af azure: deduplicate cli and default credentials case 2024-06-26 20:59:51 +02:00
Maik Riechert
834f08fe2d Azure: add option to force use of CLI credential 2024-06-26 20:59:51 +02:00
Michael Eischer
814ef4901f Merge pull request #4878 from restic/patch-deps-bump
Bump dependencies
2024-06-26 20:58:29 +02:00
Michael Eischer
84bc9432de update release verification script for latest docker 2024-06-26 20:49:23 +02:00
Michael Eischer
e9d711422a bump azure, golang and gcs dependencies 2024-06-26 20:49:23 +02:00
Michael Eischer
e37c11979a Merge pull request #4866 from MichaelEischer/fix-ea-windows
Fix xattr backup on windows
2024-06-26 20:46:24 +02:00
Michael Eischer
c01b655229 backup: fix reading xattrs on Windows for root disks as regular user
Unprivileged users cannot open the root disks with write permissions for
xattrs. Thus, only request read permissions for reading the xattrs.
2024-06-26 20:13:50 +02:00
Michael Eischer
20a6c526e5 restic: also fix file path when reading windows xattrs 2024-06-14 22:40:25 +02:00
Michael Eischer
b80aa7b1cc repository: prevent initialization if a snapshot exists 2024-06-14 20:37:01 +02:00
Michael Eischer
deca7d08ac restorer: cleanup unexpected xattrs on windows 2024-06-14 20:17:06 +02:00
Michael Eischer
9572b7224f restorer: windows test fixes 2024-06-13 23:20:09 +02:00
Michael Eischer
ca41c8fd11 restore: use fs function wrappers
This ensures proper path handling on Windows.
2024-06-13 22:40:37 +02:00
Michael Eischer
3d73ae9988 update restore changelog 2024-06-13 22:32:53 +02:00
Michael Eischer
4d6042fe95 restore: remove unexpected xattrs from files 2024-06-13 22:21:00 +02:00
Michael Eischer
ebbd4e26d7 restorer: allow directory to replace existing file 2024-06-13 21:57:48 +02:00
Michael Eischer
ac729db3ce restorer: fix overwriting of special file types
An attempt to replace an existing file with a hardlink previously ended
with a missing file.

Remove an existing file before trying to restore a special node. This
generalizes the existing behavior for symlinks to all special node
types.
2024-06-13 21:56:18 +02:00
Michael Eischer
c7902b7724 restorer: cleanup overwrite tests 2024-06-13 21:55:33 +02:00
Michael Eischer
c598a751c2 restore: fine-grained sparse support for windows 2024-06-13 21:55:33 +02:00
Michael Eischer
d265ec64f2 restore: correctly handle existing hardlinks
With hardlinks there's no efficient way to detect which files are linked
with each other. Thus, just start from scratch when restore has to
modify a hardlinked file.
2024-06-13 21:55:33 +02:00
Michael Eischer
f19b69af25 restore: allow overwrite to replace empty directories and symlinks
With an already existing file tree an old directory or symlink may exist
in a place where restore wants to create a new file. Thus, check for
unexpected file types and clean up if necessary.
2024-06-13 21:55:33 +02:00
Michael Eischer
267cd62ae4 Merge pull request #4838 from MichaelEischer/restore-skip-unchanged
restore: skip unchanged files and add `--overwrite if-changed` option
2024-06-13 21:26:04 +02:00
Michael Eischer
d890bfff7c doc: suggest backup before in-place restore 2024-06-13 21:17:30 +02:00
Michael Eischer
f1c76a8286 restore: fix corrupted sparse files 2024-06-13 21:17:30 +02:00
Michael Eischer
1eccd6504b restore: test restore only changed parts functionality 2024-06-13 21:17:30 +02:00
Michael Eischer
3ec28ff853 update restore --overwrite documentation 2024-06-13 21:17:30 +02:00
Michael Eischer
5c3709e17a restore: add --overwrite=if-changed to skip files if their mtime&size matches
--overwrite=always still checks the file content
2024-06-13 21:17:30 +02:00
Michael Eischer
a66658b4c9 restore: only restore changed file parts
For files that should be overwritten, first check whether their content
matches the snapshot and only restore diverging parts.
2024-06-13 21:17:30 +02:00
Michael Eischer
63ea017e67 Merge pull request #4861 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/azidentity-1.6.0
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.5.2 to 1.6.0
2024-06-13 17:50:10 +00:00
Michael Eischer
62e0e5e8d8 restore: cleanup options handling 2024-06-12 22:53:53 +02:00
Michael Eischer
8733cd21b9 restore: fix file encryption on windows
The assumption that a file is not readonly is no longer valid.
2024-06-12 22:53:53 +02:00
Michael Eischer
8aa3ab6ef8 restore: check file type in verify 2024-06-12 22:53:53 +02:00
Michael Eischer
663151db57 Merge pull request #4837 from MichaelEischer/restore-options
Make restore overwrite behavior configurable
2024-06-12 22:52:55 +02:00
Michael Eischer
7f7c995977 fix linter warnings 2024-06-12 22:36:52 +02:00
Michael Eischer
105261e12e add changelog for restore --overwrite 2024-06-12 22:36:52 +02:00
Michael Eischer
e1ec60c2ee document restore --overwrite 2024-06-12 22:36:52 +02:00
Michael Eischer
ba53a2abb5 test overwrite behavior 2024-06-12 22:36:52 +02:00
Michael Eischer
e47e08a688 restorer: separately track skipped files 2024-06-12 22:36:52 +02:00
Michael Eischer
64b7b6b975 restore/ui: refactor for extensibility 2024-06-12 22:36:52 +02:00
Michael Eischer
6a4ae9d6b1 restore: configurable overwrite behavior 2024-06-12 22:36:52 +02:00
Michael Eischer
a23cb3a428 restore: reduce memory usage 2024-06-12 22:36:52 +02:00
Michael Eischer
2b50c2606c restorer: use options struct 2024-06-12 22:36:52 +02:00
Michael Eischer
0fcd89f892 restorer: remove special case for blobs with many occurrences
Loading blobs by now is no longer prone to timeouts when processing
takes a long time.
2024-06-12 22:36:52 +02:00
Michael Eischer
fd2ff464a2 restorer: remove stale comment 2024-06-12 22:36:52 +02:00
Michael Eischer
607daeed4f restore: move nil pointer check into restoreui 2024-06-12 22:36:52 +02:00
Michael Eischer
30320a249a restore: let filerestorer also handle empty files
This get's rid of the corresponding special cases.
2024-06-12 22:36:52 +02:00
Michael Eischer
c166ad7daf restore: factor out file creation helper 2024-06-12 22:36:52 +02:00
dependabot[bot]
1e7bc6dab8 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.5.2 to 1.6.0.
- [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/internal/v1.5.2...sdk/azcore/v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-12 20:09:17 +00:00
Michael Eischer
f834c1f08a Merge pull request #4825 from MichaelEischer/bump-fuse
mount: support fuse-t on macOS
2024-06-12 20:33:05 +02:00
Michael Eischer
058292700c mount: support fuse-t on macOS 2024-06-11 22:52:08 +02:00
Michael Eischer
be05a17e15 Merge pull request #4811 from konidev20/fix-gh-4781-restore-include-and-exclude-file-switches
Restore flags to include from file and exclude from file
2024-06-10 19:36:07 +00:00
Srigovind Nayak
fe412e2553 fix: restore inclusion logic and restore tests
doc: update exclude and include docs
2024-06-10 01:55:39 +05:30
Srigovind Nayak
188684ee9e fix: include and exclude logic, add tests for include file and exclude file 2024-06-09 19:07:23 +05:30
Michael Eischer
fc3841e7cc Merge pull request #4851 from MichaelEischer/fix-utf-16-key
key add/passwd: handle UTF-16 encoding correctly
2024-06-09 11:27:58 +02:00
Michael Eischer
da4512738a Merge pull request #4853 from MichaelEischer/safer-repo-init
init: double check that no repository exists yet
2024-06-09 11:27:45 +02:00
Michael Eischer
7861fc1942 Merge pull request #4856 from MichaelEischer/fix-verify-script
update release verification script for latest docker
2024-06-09 11:27:35 +02:00
Michael Eischer
8440b94159 Merge pull request #4807 from zmanda/windows-extendedattribs
Back up and restore Extended Attributes on Windows NTFS
2024-06-09 09:18:04 +00:00
Michael Eischer
bab760369f repository: double check that there is not repository before init
Apparently, calling `Stat` on the config file can be unreliable for some
backends.
2024-06-09 00:05:32 +02:00
Srigovind Nayak
24a247a0dc test: update test case name 2024-06-08 13:23:35 +05:30
Srigovind Nayak
3a52176121 restore: accumulate results of multiple pattern checks
addressing review comments
2024-06-08 13:23:35 +05:30
Srigovind Nayak
e579dfe72a doc: update documentation for restore command 2024-06-08 13:23:35 +05:30
Srigovind Nayak
2a2c09e666 changelog: update changelog for gh-4781 2024-06-08 13:23:35 +05:30
Srigovind Nayak
1a7574e4b4 test: add tests for include By pattern 2024-06-08 13:23:35 +05:30
Srigovind Nayak
4e449ffaff test: add tests for reading patterns from file 2024-06-08 13:23:35 +05:30
Srigovind Nayak
14d2799b44 fix: move include and exclude pattern validations to top 2024-06-08 13:23:35 +05:30
Srigovind Nayak
fdf2e4ed0e restore: refactor include and exclude
- added includePatternOptions similar to excludePatternOptions
- followed similar approach to backup for selecting files for restore
2024-06-08 13:23:35 +05:30
Srigovind Nayak
7d5dd6db66 fix: add string.Lower for insenstive includes and excludes read from file 2024-06-08 13:23:35 +05:30
Srigovind Nayak
b02117ef0b restore: read includes, insensitive includes, excludes and insensitive excludes from a file
feature for gh-4781
2024-06-08 13:23:35 +05:30
Michael Eischer
78485160fc Merge pull request #4849 from fthoma/table-tcwidth
Use character display width for table padding
2024-06-07 19:53:14 +00:00
Michael Eischer
7cd324fe26 ui/table: avoid duplicate table cell width calculation 2024-06-07 21:45:40 +02:00
Michael Eischer
edd3e214c2 ui/table: fix width calculation of multi-line column headers 2024-06-07 21:44:49 +02:00
Michael Eischer
08c43d2c7e update release verification script for latest docker 2024-06-07 21:00:10 +02:00
Michael Eischer
3f878aa8e7 Merge pull request #4845 from greatroar/errors
Fix error handling bug + clean up error messages
2024-06-07 17:07:07 +00:00
Michael Eischer
112de8526d Merge pull request #4852 from MichaelEischer/master
crypto: cleanup ciphertext verification error
2024-06-07 19:06:08 +02:00
Michael Eischer
0a70bbcea5 Merge pull request #4844 from MichaelEischer/improve-timeout-error
backend: Improve timeout error message
2024-06-07 19:05:39 +02:00
aneesh-n
4f053da06a Fix test case by correcting cleanup order 2024-06-05 23:10:29 -06:00
aneesh-n
2101dfe448 Add missing return to fix failing test 2024-06-05 22:40:21 -06:00
aneesh-n
7a48c9ebd7 Fix review comments 2024-06-05 16:06:57 -06:00
Michael Eischer
b82ecc6425 crypto: cleanup ciphertext verification error 2024-06-05 22:33:20 +02:00
Michael Eischer
c55665be2c key add/passwd: handle UTF-16 encoding correctly
Just use the exact some function for load a password from a file
everywhere.
2024-06-05 22:19:26 +02:00
Michael Eischer
ef85a81e83 Merge pull request #4847 from rawtaz/azure-error-msg
azure: Improve error message in azure.Create()
2024-06-05 20:05:57 +00:00
Florian Thoma
e9de9684f4 Use character display width for table padding
Using len(...) for table cell padding produced wrong results for unicode
chracters leading to misaligned tables. Implementation changed to take
the actual terminal display width into consideration.
2024-06-05 09:33:15 +02:00
Leo R. Lundgren
b2bbbe805f azure: Improve error message in azure.Create() 2024-06-03 23:37:17 +02:00
greatroar
10fdb914df cmd: Return error in readPassword
The returned error was always nil.

Replaced Wrap by WithStack because the function name was stale.
2024-06-02 10:11:27 +02:00
Michael Eischer
660679c2f6 Merge pull request #4835 from MichaelEischer/fix-list-cancel
backend/retry: do not log final error if context was canceled
2024-06-01 19:17:30 +02:00
Michael Eischer
db2398f35b backend: increase request progress timeout to 5 minutes
Apparently, 2 minutes are too short in some cases and can result in
canceled List requests.
2024-06-01 19:01:51 +02:00
Michael Eischer
6bf3d4859f backend: improve error on http request timeout
Now yields a "request timeout" error instead of "context canceled".
2024-06-01 18:52:39 +02:00
greatroar
4a874000b7 gs: Replace some errors.Wrap calls
The first one in Create is already a WithStack error. The rest were
referencing code that hasn't existed for quite some time. Note that
errors from Google SDKs tends to start with "google:" or "googleapi:".

Also, use restic/internal/errors.
2024-06-01 15:11:06 +02:00
Michael Eischer
456ebfb0c7 Merge pull request #4840 from restic/dependabot/go_modules/google.golang.org/api-0.182.0
build(deps): bump google.golang.org/api from 0.181.0 to 0.182.0
2024-06-01 13:06:49 +00:00
Michael Eischer
830e87059a Merge pull request #4842 from restic/dependabot/github_actions/docker/login-action-3.2.0
build(deps): bump docker/login-action from 3.1.0 to 3.2.0
2024-06-01 13:06:46 +00:00
Michael Eischer
a26beb9c1c Merge pull request #4843 from restic/dependabot/github_actions/golangci/golangci-lint-action-6
build(deps): bump golangci/golangci-lint-action from 5 to 6
2024-06-01 13:06:43 +00:00
dependabot[bot]
46b0fac11e build(deps): bump golangci/golangci-lint-action from 5 to 6
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 5 to 6.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-01 01:48:46 +00:00
dependabot[bot]
fced29b479 build(deps): bump docker/login-action from 3.1.0 to 3.2.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](e92390c5fb...0d4c9c5ea7)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-01 01:48:43 +00:00
dependabot[bot]
05d7885a87 build(deps): bump google.golang.org/api from 0.181.0 to 0.182.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.181.0 to 0.182.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.181.0...v0.182.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-01 01:02:01 +00:00
Michael Eischer
38654a3bd7 backend/retry: do not log final error if context was canceled
Calls to `List(ctx, ...)` are usually stopped by canceling the context
once no further entries are required by the caller. Thus, don't log the
final error if the used context was canceled.
2024-05-30 18:48:52 +02:00
Michael Eischer
2280fbfd2e Merge pull request #4810 from konidev20/fix-gh-4768-add-custom-user-agent-for-http-client
Allow custom User-Agent to be specified for outgoing requests
2024-05-30 16:34:52 +00:00
Michael Eischer
7e0ee5974f Merge pull request #4816 from MichaelEischer/skip-if-unchanged
backup: add support for `--skip-if-unchanged`
2024-05-30 15:39:08 +02:00
Srigovind Nayak
de7b418bbe http: allow custom User-Agent for outgoing HTTP requests 2024-05-30 15:38:06 +02:00
Michael Eischer
c103c0830e add changelog for skip-if-unchanged 2024-05-30 15:25:44 +02:00
Michael Eischer
513135b238 doc: slightly modernize backup examples 2024-05-30 15:25:44 +02:00
Michael Eischer
cdd210185d Merge pull request #4823 from MichaelEischer/fix-check-output
Fix mangled check output
2024-05-30 15:17:27 +02:00
Michael Eischer
5649334099 backup: document --skip-if-unchanged 2024-05-30 15:14:32 +02:00
Michael Eischer
6869bdaaa8 backup: implement --skip-if-unchanged 2024-05-30 15:14:31 +02:00
Michael Eischer
13127f3f6b check: remove output mangling workaround 2024-05-30 15:09:27 +02:00
Michael Eischer
939b537c80 check/migrate: convert to use termstatus to prevent mangled output
Errors reported by check would result in corrupted output.
2024-05-30 15:09:27 +02:00
Michael Eischer
7b4f81d964 Merge pull request #4829 from greatroar/termstatus
termstatus: Do formatting in Message, not Terminal
2024-05-30 11:57:44 +00:00
Michael Eischer
a5c7a83470 Merge pull request #4819 from restic/update-dependencies
Update dependencies
2024-05-30 13:55:46 +02:00
Michael Eischer
52b3fee42b Merge pull request #4818 from MichaelEischer/move-code
Move cache / index / hashing / pack packages
2024-05-30 13:54:31 +02:00
Michael Eischer
e95cfff923 Merge pull request #4826 from MichaelEischer/fix-docs-warninigs
doc: fix warnings
2024-05-30 13:53:49 +02:00
Michael Eischer
fe8fbcc5ed Merge pull request #4822 from MichaelEischer/consistent-backup-source-name
backup: refer to backed up data as backup source not target
2024-05-30 13:53:25 +02:00
Michael Eischer
3d4a620089 Merge pull request #4824 from MichaelEischer/fix-cache-race
bloblru: Fix flaky test due to race condition
2024-05-30 13:52:34 +02:00
greatroar
46f04bc5f0 termstatus: Do formatting in Message, not Terminal 2024-05-27 19:05:39 +02:00
Michael Eischer
a651af70d6 doc: fix warings 2024-05-26 14:32:09 +02:00
Michael Eischer
1c6067d93d bloblru: variable name cleanup 2024-05-26 12:42:46 +02:00
Michael Eischer
21ce03cff2 bloblru: move defer outside critical section 2024-05-26 12:38:20 +02:00
Michael Eischer
0ad0b7ca7c bloblru: fix race condition that can compute value multiple times 2024-05-26 12:37:24 +02:00
Michael Eischer
619ce8bfa2 Merge pull request #4820 from MichaelEischer/forget-extend-descritpion
forget: explain oldest snapshot special case in command help
2024-05-26 10:04:43 +00:00
Michael Eischer
107f18849c doc: update help output in manual_rest.rst 2024-05-25 23:16:22 +02:00
Michael Eischer
18990dbed8 backup: refer to backed up data as backup source not target
A backup reads from the source and writes it to the backup target
(repository). The name "target" is kept within the source code as it's
used there excessively.
2024-05-25 23:13:37 +02:00
Michael Eischer
3828313974 Merge pull request #4821 from MichaelEischer/master
update `repair packs` changelog
2024-05-25 17:02:21 +02:00
Michael Eischer
04c181dbd0 update-repair-packs-changelog 2024-05-25 16:42:55 +02:00
Michael Eischer
21528c9f02 Merge pull request #4805 from plant99/mkdirall-cachedir
prepareCheckCache function: Add MkdirAll() to restic-cache directory if it doesn't exist
2024-05-25 14:30:21 +00:00
Shivashis Padhi
0271bb97f8 check: enhance check command to create cache directory if it doesn't exist 2024-05-25 19:15:42 +05:30
Michael Eischer
2c7ebf4c7f forget: explain oldest snapshot special case in command help 2024-05-25 15:10:21 +02:00
Michael Eischer
7ea508e7b8 Merge pull request #4815 from greatroar/termstatus
Termstatus refactoring
2024-05-25 12:08:53 +00:00
Michael Eischer
496e57f956 hashing: move to repository package 2024-05-25 13:13:03 +02:00
Michael Eischer
5e0ea8fcfa pack: move to repository package 2024-05-25 13:13:03 +02:00
Michael Eischer
50ec408302 index: move to repository package 2024-05-25 13:13:03 +02:00
Michael Eischer
58bbb27b4c downgrade minio to keep go 1.19 support 2024-05-25 12:52:08 +02:00
Michael Eischer
c5260373ca update backoff/xxhash libraries 2024-05-25 12:37:14 +02:00
Michael Eischer
b2f7a878cd update backend libraries
minio-go is kept at 7.0.67 as later versions require Go 1.21.
2024-05-25 12:36:16 +02:00
Michael Eischer
f20bf5eeba update golang.org/x packages 2024-05-25 12:35:28 +02:00
Michael Eischer
8e5d7d719c cache: move to backend package 2024-05-24 23:04:06 +02:00
Michael Eischer
80132e71d8 Merge pull request #4808 from MichaelEischer/insecure-no-password
Implement `--insecure-no-password` option.
2024-05-24 22:58:25 +02:00
Michael Eischer
130506250f document insecure-no-password 2024-05-24 22:38:20 +02:00
Michael Eischer
1d2277b4c3 Add --insecure-no-password option
This also includes two derived options `--from-insecure-no-password`
used for commands that require specifying a source repository. And
`--new-insecure-no-password` for the `key add` and `key passwd`
commands.

Specifying `--insecure-no-password` disabled the password prompt and
immediately uses an empty password. Passing a password via CLI option or
environment variable at the same time is an error.
2024-05-24 22:38:20 +02:00
Michael Eischer
d4b0d21199 key add/passwd: deduplicate options setup and remove globals
The current pattern of using a global options variable is problematic.
2024-05-24 22:38:20 +02:00
Michael Eischer
55cb8d174a Merge pull request #4354 from MichaelEischer/associated-data
Reduce prune memory usage
2024-05-24 22:26:22 +02:00
Michael Eischer
436afbff23 add changelog for memory efficient prune 2024-05-24 22:18:14 +02:00
Michael Eischer
3c7b7efdc9 repository: remove prune plan parts once they are no longer necessary 2024-05-24 22:18:14 +02:00
Michael Eischer
462b82a060 index: reduce size of compressed indexes
use the same index size for compressed and uncompressed indexes.
Otherwise, decoding the index of a compressed repository requires
significantly more memory.
2024-05-24 22:18:14 +02:00
Michael Eischer
77873f5a9d repository: let prune control data structure of usedBlobs set 2024-05-24 22:18:14 +02:00
Michael Eischer
2033c02b09 index: replace CountedBlobSet with AssociatedSet 2024-05-24 22:18:14 +02:00
Michael Eischer
93098e9265 prune: hide implementation details of counted blob set 2024-05-24 21:42:56 +02:00
Michael Eischer
ff4775a15f Merge pull request #4812 from MichaelEischer/streaming-index-rewrite
Resumable prune & memory-efficient index rewrite
2024-05-24 21:41:30 +02:00
Michael Eischer
860b595a8b backend: increase watchdog test timeout for deflaking 2024-05-24 21:33:17 +02:00
Michael Eischer
f680a2331d add changelog for streaming index rewrite 2024-05-24 21:33:17 +02:00
Michael Eischer
027cc64737 repository: fix prune heuristic to allow resuming interrupted runs
Pack files created by interrupted prune runs, appear to consist only of
duplicate blobs on the next run. This caused the previous heuristic to
ignore those pack files. Now, a duplicate blob in a specific pack file
is also selected if that pack file only contains duplicate blobs. This
allows prune to select the already rewritten pack files.
2024-05-24 21:33:17 +02:00
Michael Eischer
e52033a8bd index: slightly reduce Rewrite concurrency
The index operations are likely CPU-bounded. Thus, reduce the
concurrency accordingly.
2024-05-24 21:33:17 +02:00
Michael Eischer
57d69aa640 index: cleanup SaveIndex method 2024-05-24 21:33:17 +02:00
Michael Eischer
2ca1c37721 index: additional tests for new index save methods 2024-05-24 21:33:17 +02:00
Michael Eischer
5f7b48e65f index: replace Save() method with Rewrite and SaveFallback
Rewrite implements a streaming rewrite of the index that excludes the
given packs. For this it loads all index files from the repository and
only modifies those that require changes. This will reduce the index
churn when running prune. Rewrite does not require the in-memory index
and thus can drop it to significantly reduce the memory usage.

However, `prune --unsafe-recovery` cannot use this strategy and requires
a separate method to save the whole in-memory index. This is now handled
using SaveFallback.
2024-05-24 21:33:17 +02:00
Michael Eischer
ad98fbf7dd restic: add IDSet.Clone() method 2024-05-24 21:33:17 +02:00
Michael Eischer
72482ce5bd index: misc cleanups 2024-05-24 21:33:17 +02:00
Michael Eischer
68fa0e0305 prune: no longer disable automatic index updates
this allows prune to resume an interrupted prune run.
2024-05-24 21:33:17 +02:00
Michael Eischer
9aa0c90fb2 index: remove supersedes field
Using the field with its current semantics is nearly impossible to get
right. Remove it as it will be replaced anyways in repository format 3.
2024-05-24 21:33:17 +02:00
Michael Eischer
76e6719f2e repository: make CreateIndexFromPacks method private 2024-05-24 21:33:17 +02:00
Michael Eischer
04ad9f0c0c repository: remove Packer and SavePacker from public interface 2024-05-24 21:33:17 +02:00
Michael Eischer
550d1eeac3 repository: remove SaveIndex from interface
The method is now only indirectly accessible via Prune or RepairIndex.
2024-05-24 21:33:17 +02:00
Michael Eischer
fb59e00614 index: rewrite MasterIndex load/save test to be independent of repository 2024-05-24 21:33:17 +02:00
Michael Eischer
447b486c20 index: deduplicate index loading of check and repository 2024-05-24 21:33:17 +02:00
Michael Eischer
6ca12c1b4a archiver: replace most uses of restic.Repository 2024-05-24 21:33:17 +02:00
Michael Eischer
864995271e repository: unwrap BlobHandle parameters of LookupBlob
The method now uses the same parameters as LookupBlobSize.
2024-05-24 21:33:17 +02:00
Michael Eischer
1266a4932f repository: fix parameter order of LookupBlobSize
All methods should use blobType followed by ID.
2024-05-24 21:33:17 +02:00
Michael Eischer
e848ad651a restic: name parameters in restic interface 2024-05-24 21:33:17 +02:00
Michael Eischer
0bb0720348 test cleanups 2024-05-24 21:33:17 +02:00
Michael Eischer
c01bcb1001 archiver: remove unused masterIndex from test 2024-05-24 21:33:17 +02:00
Michael Eischer
0aa5c53842 repository: replace HasBlob with LookupBlobSize 2024-05-24 21:33:17 +02:00
Michael Eischer
8f1e70cd9b repository: remove clearIndex and packSize from public interface 2024-05-24 21:33:17 +02:00
Michael Eischer
4df887406f repository: inline MasterIndex interface into Repository interface 2024-05-24 21:33:17 +02:00
Michael Eischer
3eeb6723cd Merge pull request #4764 from MichaelEischer/safe-keep-tag
Prevent unsafe uses of `forget --keep-tag`
2024-05-24 20:51:20 +02:00
Michael Eischer
3cc6827f09 forget: add feature flag for safe --keep-tags behavior 2024-05-24 20:45:33 +02:00
Michael Eischer
7948912b31 document --unsafe-allow-remove-all option 2024-05-24 20:45:33 +02:00
Michael Eischer
3f46808898 add forget safety net changelogs 2024-05-24 20:45:33 +02:00
Michael Eischer
82ca0030b7 forget: test --unsafe-allow-remove-all and --keep-tags safety check 2024-05-24 20:45:33 +02:00
Michael Eischer
57f9739573 forget: Add --unsafe-allow-remove-all option
To prevent accidentally wiping all snapshots from a repository, that
option can only be used if either a snapshot filter or a keep policy is
specified.

Essentially, the option allows `forget --tag something
--unsafe-allow-remove-all` calls to remove all snapshots with a specific
tag.
2024-05-24 20:45:33 +02:00
Michael Eischer
5b7952e426 forget: return error if no policy was specified 2024-05-24 20:45:33 +02:00
Michael Eischer
c0e1f36830 forget: refuse deleting the last snapshot in a snapshot group
`--keep-tag invalid-tag` was previously able to wipe all snapshots in a
repository. As a user specified a `--keep-*` option this is likely
unintentional. This forbid deleting all snapshot if a `--keep-*` option
was specified to prevent data loss. (Not specifying such an option
currently also causes the command to abort)
2024-05-24 20:45:33 +02:00
Michael Eischer
d106ad6921 restic: regenerate snapshot keep policy golden test files 2024-05-24 20:45:33 +02:00
Michael Eischer
16ef4d515b Merge pull request #4784 from MichaelEischer/rework-backend-retries
Rework backend retries
2024-05-24 20:29:54 +02:00
Michael Eischer
e4a48085ae backend/retry: feature flag new retry behavior 2024-05-24 20:24:02 +02:00
Michael Eischer
723247c8e5 add changelog for longer retries 2024-05-24 20:24:02 +02:00
Michael Eischer
b1266867d2 repository: wait max 1 minutes for lock removal if context is canceled
The toplevel context in restic only canceled if the user interrupts a
restic operation. If the network connection has failed this can require
waiting the full retry duration of 15 minutes which is a bad user
experience for interactive usage. Thus limit the delay to one minute in
this case.
2024-05-24 20:24:02 +02:00
Michael Eischer
98709a4372 retry: reduce total number of retries
Retries in restic try to solve two main problems:
- retry a temporarily failed operation
- tolerate temporary network interruptions

The first problem only requires a few retries, whereas the last one benefits
primarily from spreading the requests over a longer duration.

Increasing the default multiplier and the initial interval works for
both cases. The first few retries only take a few seconds, while later
retries quickly reach the maximum interval of one minute. This ensures
that the total number of retries issued by restic will remain at around
21 retries for a 15 minute period. As the concurrency in restic is
bounded, retries drastically reduce the number of requests sent to a
backend. This helps to prevent overloading the backend.
2024-05-24 20:24:02 +02:00
Michael Eischer
512cd6ef07 retry: ensure that there's always at least one retry
Previously, if an operation failed after 15 minutes, then it would never
be retried. This means that large backend requests are more unreliable
than smaller ones.
2024-05-24 20:24:02 +02:00
Michael Eischer
a60ee9b764 retry: limit retries based on elapsed time not count
Depending on how long an operation takes to fail, the total retry
duration can currently vary between 1.5 and 15 minutes. In particular
for temporarily interrupted network connections, the former timeout is
too short. Thus always use a limit of 15 minutes.
2024-05-24 20:24:02 +02:00
Michael Eischer
a3633cad9e retry: explicitly log failed requests
This simplifies finding the request in the log output that cause an
operation to fail.
2024-05-24 20:24:02 +02:00
Michael Eischer
b9cbf623fa Merge pull request #4814 from MichaelEischer/fix-tmp-docs
doc: fix tmpdir documentation for windows
2024-05-24 18:17:59 +02:00
greatroar
66d03c797e ui, termstatus: Move WrapStdio
Saves some imports. ui still needs to import ui/termstatus from
message.go.
2024-05-21 11:25:16 +02:00
greatroar
0b56214473 ui: Simplify stdio wrapper
The StdioWrapper type is really just a pair of io.WriteClosers, so
remove it in favor of a function that returns two of those. Test
coverage increases because the removed code was not tested.
2024-05-21 11:23:32 +02:00
greatroar
7f439a9c34 ui: Inline lineWriter into StdioWrapper 2024-05-21 11:00:09 +02:00
Michael Eischer
4021e67d97 doc: fix tmpdir documentation for windows 2024-05-20 20:48:29 +02:00
Michael Eischer
8898f61717 Merge pull request #4809 from MichaelEischer/update-changelog
add retries for corrupted blobs to changelog
2024-05-18 23:04:13 +02:00
Michael Eischer
5f23baabcc add retries for corrupted blobs to changelog 2024-05-18 23:03:24 +02:00
Michael Eischer
9c5bac6f25 Merge pull request #4799 from letmaik/letmaik/azure-force-cli-credential
Azure: add option to force use of CLI credential
2024-05-18 20:22:15 +00:00
Michael Eischer
c56ecec9aa azure: deduplicate cli and default credentials case 2024-05-18 22:15:54 +02:00
Maik Riechert
355f520936 Azure: add option to force use of CLI credential 2024-05-18 22:15:54 +02:00
Michael Eischer
1dfe1b8732 Merge pull request #4802 from MichaelEischer/backend-cleanups
Repository: Remove Backend() method
2024-05-18 22:02:45 +02:00
Michael Eischer
223aa22cb0 replace some uses of restic.Repository with finegrained interfaces 2024-05-18 21:42:51 +02:00
Michael Eischer
291c9677de restic/repository: remove Backend() method 2024-05-18 21:42:51 +02:00
Michael Eischer
673496b091 repository: clean cache between CheckPack retries
The cache cleanup pattern is also used in ListPack etc.
2024-05-18 21:42:51 +02:00
Michael Eischer
3d2410ed50 Replace some repo.RemoveUnpacked usages
These will eventually be blocked as they do not delete Snapshots.
2024-05-18 21:42:51 +02:00
Michael Eischer
d2c26e33f3 repository: remove further usages of repo.Backend() 2024-05-18 21:42:51 +02:00
Michael Eischer
8a425c2f0a remove usages of repo.Backend() from tests 2024-05-18 21:42:51 +02:00
Michael Eischer
aa4647f773 repository: unexport PackBlobIterator 2024-05-18 21:42:51 +02:00
Michael Eischer
94e863885c check: move verification of individual pack file to repository 2024-05-18 21:42:50 +02:00
Michael Eischer
e40943a75d restic: remove backend usage from lock test 2024-05-18 21:38:31 +02:00
Michael Eischer
67e2ba0d40 repository: Lock requires *repository.Repository
This allows the Lock function to access the backend, even once the
Backend method is removed from the interface.
2024-05-18 21:38:31 +02:00
Michael Eischer
d8b184b3d3 repository: convert test helper to return *repository.Repository 2024-05-18 21:38:31 +02:00
Michael Eischer
a1ca5e15c4 migrations: add temporary hack for s3_layout
The migration will be removed after the next restic release anyways.
Thus, there's no need for a clean implementation.
2024-05-18 21:38:31 +02:00
Michael Eischer
34d90aecf9 migrations: move logic of upgrade_repo_v2 to repository package
The migration modifies repository internals and thus should live within
the repository package.
2024-05-18 21:38:31 +02:00
Michael Eischer
ab9077bc13 replace usages of backend.Remove() with repository.RemoveUnpacked()
RemoveUnpacked will eventually block removal of all filetypes other than
snapshots. However, getting there requires a major refactor to provide
some components with privileged access.
2024-05-18 21:38:31 +02:00
Michael Eischer
8274f5b101 prune: remove Backend.IsNotExist()
Only handling one specific error is not particularly useful.
2024-05-18 21:38:31 +02:00
Michael Eischer
9795198189 debug: remove Backend.Stat() usage 2024-05-18 21:38:31 +02:00
Michael Eischer
0c1ba6d95d backend: remove unused Location method 2024-05-18 21:38:31 +02:00
Michael Eischer
eb6c653f89 Merge pull request #4800 from MichaelEischer/cleanup-load
Retry loading of corrupted data from backend / cache
2024-05-18 21:34:54 +02:00
Michael Eischer
74d90653e0 check: use ReadFull to load pack header in checkPack
This ensures that the pack header is actually read completely.
Previously, for a truncated file it was possible to only read a part of
the header, as backend.Load(...) is not guaranteed to return as many
bytes as requested by the length parameter.
2024-05-18 21:28:54 +02:00
Michael Eischer
8f8d872a68 fix compatibility with go 1.19 2024-05-18 21:28:54 +02:00
Michael Eischer
ff0744b3af check: test checkPack retries 2024-05-18 21:28:54 +02:00
Michael Eischer
987c3b250c repository: test retries of ListPack 2024-05-18 21:28:54 +02:00
Michael Eischer
bf16096771 repository: test LoadBlob retries 2024-05-18 21:28:54 +02:00
Michael Eischer
4f45668b7c repository: rework and extend LoadRaw tests 2024-05-18 21:28:54 +02:00
Michael Eischer
ac805d6838 cache: cleanup debug logs 2024-05-18 21:28:54 +02:00
Michael Eischer
5214af88e2 cache: test forget behavior 2024-05-18 21:28:54 +02:00
Michael Eischer
3ff063e913 check: verify pack a second time if broken 2024-05-18 21:28:54 +02:00
Michael Eischer
385cee09dc repository: fix caching of tree packs in LoadBlobsFromPack 2024-05-18 21:28:54 +02:00
Michael Eischer
e734746f75 cache: forget cached file at most once
This is inspired by the circuit breaker pattern used for distributed
systems. If too many requests fails, then it is better to immediately
fail new requests for a limited time to give the backend time to
recover.

By only forgetting a file in the cache at most once, we can ensure that
a broken file is only retrieved once again from the backend. If the file
stored there is broken, previously it would be cached and deleted
continuously. Now, it is retrieved only once again, all later requests
just use the cached copy and either succeed or fail immediately.
2024-05-18 21:28:54 +02:00
Michael Eischer
97a307df1a cache: Always use cached file if it exists
A file is always cached whole. Thus, any out of bounds access will also
fail when directed at the backend. To handle case in which the cached
file is broken, then caller must call Cache.Forget(h) for the file in
question.
2024-05-18 21:28:54 +02:00
Michael Eischer
8cce06d915 repair packs: drop experimental warning
This warning should already have been removed once the feature flag was
dropped.
2024-05-18 21:28:54 +02:00
Michael Eischer
433a6aad29 repository: remove redundant blob loading fallback from RepairPacks
LoadBlobsFromPack already implements the same fallback behavior.
2024-05-18 21:28:54 +02:00
Michael Eischer
e401af07b2 check: fix error message formatting 2024-05-18 21:28:54 +02:00
Michael Eischer
7017adb7e9 repository: retry failed ListPack once 2024-05-18 21:28:54 +02:00
Michael Eischer
e33ce7f408 repository: retry failed LoadBlob once 2024-05-18 21:28:54 +02:00
Michael Eischer
2ace242f36 repository: make reloading broken files explicit 2024-05-18 21:28:54 +02:00
Michael Eischer
e9390352a7 cache: code cleanups 2024-05-18 21:26:00 +02:00
Michael Eischer
503c8140b1 repository: unify blob decoding code 2024-05-18 21:26:00 +02:00
Michael Eischer
6563f1d2ca repository: remove redundant debug log 2024-05-18 21:26:00 +02:00
Michael Eischer
021fb49559 repository: Implement repository.LoadUnpacked using LoadRaw
Both functions were using a similar implementation.
2024-05-18 21:26:00 +02:00
Michael Eischer
779c8d3527 debug/repair packs/upgrade repo v2: use repository.LoadRaw
This replaces calling the low-level backend.Load() method.
2024-05-18 21:26:00 +02:00
Michael Eischer
1d6d3656b0 repository: move backend.LoadAll to repository.LoadRaw
LoadRaw also includes improved context cancellation handling similar to the
implementation in repository.LoadUnpacked.

The removed cache backend test will be added again later on.
2024-05-18 21:26:00 +02:00
Michael Eischer
47232bf8b0 backend: move LimitReadCloser to util package
The helper is only intended for usage by backend implementations.
2024-05-18 21:26:00 +02:00
Michael Eischer
dcd151147c Merge pull request #4803 from restic/permanent-retry-failure
Do not retry permanent backend failures
2024-05-18 20:07:06 +02:00
Michael Eischer
53d15bcd1b retry: add circuit breaker to load method
If a file exhausts its retry attempts, then it is likely not accessible
the next time. Thus, immediately fail all load calls for that file to
avoid useless retries.
2024-05-18 19:59:26 +02:00
Michael Eischer
394c8ca3ed rest/rclone/s3/sftp/swift: move short file detection behind feature gate
These backends tend to use a large variety of server implementations.
Some of those implementations might prove problematic with the new
checks.
2024-05-18 19:59:26 +02:00
Michael Eischer
6328b7e1f5 replace "too small" with "too short" in error messages 2024-05-18 19:59:26 +02:00
Michael Eischer
53561474d9 update changelog with persistent backend error handling 2024-05-18 19:59:26 +02:00
Michael Eischer
aeb7eb245c retry: do not retry permanent errors
This is currently gated behind a feature flag as some unexpected
interactions might show up in the wild.
2024-05-18 19:59:26 +02:00
Michael Eischer
bf8cc59889 Use generic backend-error-redesign feature flag instead of http-timeouts
An individual flag for each change of the backend error handling would
be too finegrained. Thus, add a generic flag.
2024-05-18 19:54:52 +02:00
Michael Eischer
4740528a0b backend: add tests for IsPermanentError 2024-05-18 19:54:52 +02:00
Michael Eischer
6a85df7297 backend: add IsPermanentError() method to interface 2024-05-18 19:54:52 +02:00
Michael Eischer
cfc420664a mem: stricter handling of out of bounds requests 2024-05-18 19:54:52 +02:00
Michael Eischer
d40f23e716 azure/b2/gs/s3/swift: adapt cloud backend 2024-05-18 19:54:51 +02:00
Michael Eischer
e793c002ec local: stricter handling of short files 2024-05-18 19:54:21 +02:00
Michael Eischer
b4895ebd76 rest: rework error reporting and report too short files 2024-05-18 19:54:21 +02:00
Michael Eischer
eaa3f81d6b sftp: check for truncated files without an extra backend request 2024-05-18 19:54:21 +02:00
Michael Eischer
c6d74458ee sftp: improve handling of too short files 2024-05-18 19:54:21 +02:00
aneesh-n
43bc304e42 Add unreleased changelog 2024-05-17 14:54:25 -06:00
aneesh-n
9d1b23964d Update comment for licensing 2024-05-17 14:19:05 -06:00
aneesh-n
5cff6e084e Add support for Windows EA in node
Refactor Extended Attribute related functions in node files as windows apis get and set EA in bulk
2024-05-17 14:18:20 -06:00
aneesh-n
d6708505b9 Add helpers for Windows Extended Attributes 2024-05-17 14:15:03 -06:00
Michael Eischer
7ed560a201 Merge pull request #4796 from MichaelEischer/parallel-dump-load
dump: Parallelize loading large files
2024-05-14 22:35:44 +02:00
Michael Eischer
92221c2a6d Merge pull request #4708 from zmanda/windows-securitydesc
Back up and restore SecurityDescriptors on Windows
2024-05-12 14:14:39 +00:00
Michael Eischer
b5fdb1d637 Merge pull request #4782 from MichaelEischer/fix-sftp-performance
Fix sftp upload performance
2024-05-12 15:28:33 +02:00
Michael Eischer
e4f9bce384 Merge pull request #4792 from restic/request-watchdog
backend: enforce that backend HTTP requests make progress
2024-05-09 23:55:30 +02:00
Michael Eischer
3740700ddc add http timeouts to changelog 2024-05-09 23:46:17 +02:00
Michael Eischer
ebd01a4675 backend: add tests for watchdogRoundTripper 2024-05-09 23:46:17 +02:00
Michael Eischer
8778670232 backend: cancel stuck http requests
requests that make no upload or download progress within a timeout are
canceled.
2024-05-09 23:46:17 +02:00
Michael Eischer
0987c731ec backend: configure protocol-level connection health checks
This should detect a connection that is stuck for more than 2 minutes.
2024-05-09 23:46:17 +02:00
aneesh-n
a4fd1b91e5 Fix review comments
Change lowerPrivileges from bool to atomic.Bool.
Add missing cleanup from upstream go-winio.
Add handling for ERROR_NOT_ALL_ASSIGNED warning.
2024-05-06 16:54:08 -06:00
Michael Eischer
e184538ddf dump: add changelog 2024-05-05 12:12:21 +02:00
Michael Eischer
4d55a62ada bloblru: add test for GetOrCompute 2024-05-05 12:00:25 +02:00
Michael Eischer
7cce667f92 fuse: switch to use bloblru.GetOrCompute 2024-05-05 11:38:42 +02:00
Michael Eischer
bd03af2feb dump: add GetOrCompute to bloblru cache 2024-05-05 11:38:42 +02:00
Michael Eischer
45509eafc8 dump: load blobs of a file from repository in parallel 2024-05-05 11:38:42 +02:00
Michael Eischer
24c1822220 Merge pull request #4794 from flow-c/master
Update 060_forget.rst
2024-05-04 08:25:06 +00:00
flow-c
d4477a5a99 Update 060_forget.rst
Replace deprecated `-1` with `unlimited` in calendar-related `--keep-*` options
2024-05-04 09:32:25 +02:00
Michael Eischer
ffe5439149 Merge pull request #4605 from MichaelEischer/better-restorer-error-handling
Rework repository.StreamPacks & better restorer error handling
2024-05-01 16:37:41 +02:00
Michael Eischer
676f0dc60d add changelog 2024-05-01 16:28:57 +02:00
Michael Eischer
1e57057953 Merge pull request #4789 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob-1.3.2
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob from 1.3.1 to 1.3.2
2024-05-01 10:45:47 +00:00
Michael Eischer
1ba0af6993 Merge pull request #4787 from restic/dependabot/go_modules/github.com/klauspost/compress-1.17.8
build(deps): bump github.com/klauspost/compress from 1.17.7 to 1.17.8
2024-05-01 10:44:33 +00:00
Michael Eischer
ffc41ae62a Merge pull request #4786 from restic/dependabot/go_modules/golang.org/x/net-0.24.0
build(deps): bump golang.org/x/net from 0.23.0 to 0.24.0
2024-05-01 10:41:26 +00:00
Michael Eischer
4832c2fbfa Merge pull request #4790 from restic/dependabot/github_actions/golangci/golangci-lint-action-5
build(deps): bump golangci/golangci-lint-action from 4 to 5
2024-05-01 10:37:37 +00:00
dependabot[bot]
30609ae6b2 build(deps): bump golangci/golangci-lint-action from 4 to 5
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4 to 5.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 01:45:43 +00:00
dependabot[bot]
502e5867a5 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.3.1 to 1.3.2.
- [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.3.1...sdk/storage/azblob/v1.3.2)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 01:02:39 +00:00
dependabot[bot]
18a6d6b408 build(deps): bump github.com/klauspost/compress from 1.17.7 to 1.17.8
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.7 to 1.17.8.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml)
- [Commits](https://github.com/klauspost/compress/compare/v1.17.7...v1.17.8)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 01:02:22 +00:00
dependabot[bot]
3bb88e8307 build(deps): bump golang.org/x/net from 0.23.0 to 0.24.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/net/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 01:02:11 +00:00
aneesh-n
672f6cd776 Fix review comments for privileges and security flags 2024-04-29 17:29:51 -06:00
aneesh-n
08c6945d61 Fix review comments 2024-04-29 16:21:38 -06:00
Aneesh N
3f76b902e5 Merge branch 'master' into windows-securitydesc 2024-04-29 14:40:34 -06:00
Michael Eischer
ccac7c7fb3 Merge pull request #3067 from DRON-666/vss-options
Add options to fine tune VSS snapshots
2024-04-29 18:09:47 +00:00
DRON-666
ccd35565ee s/sec./seconds 2024-04-29 01:48:22 +03:00
DRON-666
125dba23c5 Rearange code 2024-04-29 01:27:34 +03:00
DRON-666
7ee889bb0d Use S_FALSE and MaxInt 2024-04-29 01:25:25 +03:00
DRON-666
90b168eb6c isMountPointExcluded to isMountPointIncluded 2024-04-29 01:23:50 +03:00
DRON-666
24330c19a8 Use kebab case in option names 2024-04-29 01:21:33 +03:00
DRON-666
5703e5a652 Fix texts and comments 2024-04-29 01:18:46 +03:00
DRON-666
0a8f9c5d9c vss: Add tests for "provider" option 2024-04-28 22:45:21 +03:00
DRON-666
739d3243d9 vss: Update docs and changelog 2024-04-28 22:45:21 +03:00
DRON-666
bb0f93ef3d vss: Add "provider" option 2024-04-28 22:45:21 +03:00
DRON-666
3bac1f0135 vss: Fix issues reported by linters 2024-04-28 22:45:21 +03:00
DRON-666
88c509e3e9 vss: Change ErrorHandler signature
We don't need `error` here: the only existing implementation
of `ErrorHandler` always call `Backup.Error` and all
implementations of `Backup.Error` always return nil.
2024-04-28 22:44:16 +03:00
DRON-666
9d3d915e2c vss: Add some tests 2024-04-28 22:44:16 +03:00
DRON-666
9182e6bab5 vss: Update docs and changelog 2024-04-28 22:44:16 +03:00
DRON-666
c4f67c0064 vss: Add volume filtering
Add options to exclude all mountpoints and arbitrary volumes from snapshotting.
2024-04-28 22:44:15 +03:00
DRON-666
7470e5356e vss: Add "timeout" option
Changing multiple "callAsyncFunctionAndWait" with fixed timeout
to calculated timeout based on deadline.
2024-04-28 22:44:15 +03:00
DRON-666
78dbc5ec58 vss: Add initial support for extended options 2024-04-28 22:44:15 +03:00
Michael Eischer
a1d682ce0e add changelog for sftp performance fix 2024-04-28 11:58:08 +02:00
Michael Eischer
935327d480 sftp: slightly increase write concurrency
This should increase upload throughput for high latency links a bit.
2024-04-28 11:50:09 +02:00
Michael Eischer
669a669603 sftp: Fix upload performance issue
Since pkg/sftp 1.13.0 files were uploaded sequentially using 32kb chunks
instead of sending 64 chunks in parallel.
2024-04-28 11:48:26 +02:00
Michael Eischer
faffd15d13 Merge pull request #4734 from maouw/enhancement/envvar-for-host
Add support for specifying --host via environment variable
2024-04-24 20:00:15 +00:00
Michael Eischer
347e9d0765 complete RESITC_HOST environment handling & test 2024-04-24 21:52:39 +02:00
Altan Orhon
871ea1eaf3 Add support for specifying --host via environment variable
This commit adds support for specifying the `--host` option via the `RESTIC_HOST` environment variable. This is done by extending option processing in `cmd_backup.go` and for `restic.SnapshotFilter` in `find.go`.
2024-04-24 21:49:42 +02:00
Michael Eischer
a7b5e09902 Merge pull request #4753 from MichaelEischer/remove-cleanup-handlers
Replace cleanup handlers with context based command cancelation
2024-04-24 21:34:19 +02:00
Michael Eischer
3f9d50865d Merge pull request #4776 from MichaelEischer/cleanup-backend-open
unify backend open and create
2024-04-24 21:24:27 +02:00
Michael Eischer
5f263752d7 init: also apply limiter for non-HTTP backend 2024-04-24 20:42:30 +02:00
Michael Eischer
484dbb1cf4 get rid of a few global variables 2024-04-22 22:39:33 +02:00
Michael Eischer
940a3159b5 let index.Each() and pack.Size() return error on canceled context
This forces a caller to actually check that the function did complete.
2024-04-22 22:39:32 +02:00
Michael Eischer
31624aeffd Improve command shutdown on context cancellation 2024-04-22 22:31:38 +02:00
Michael Eischer
910927670f mount: fix exit code on cancellation 2024-04-22 22:27:19 +02:00
Michael Eischer
6f2a4dea21 remove global shutdown hook 2024-04-22 22:27:19 +02:00
Michael Eischer
699ef5e9de debug: replace cleanup handler usage in profiling setup 2024-04-22 22:27:19 +02:00
Michael Eischer
eb710a28e8 use standalone shutdown hook for readPasswordTerminal
move terminal restoration into readPasswordTerminal
2024-04-22 22:27:19 +02:00
Michael Eischer
86c7909f41 mount: use standalone shutdown hook via goroutine 2024-04-22 22:27:19 +02:00
Michael Eischer
93135dc705 lock: drop cleanup handler 2024-04-22 22:27:19 +02:00
Michael Eischer
21a7cb405c check: replace cleanup handler 2024-04-22 22:27:19 +02:00
Michael Eischer
b15d867414 Merge pull request #4763 from MichaelEischer/refactor-prune
Refactor repair index / prune into the repository package
2024-04-22 22:24:53 +02:00
Michael Eischer
2e6c43c695 Merge pull request #4761 from MichaelEischer/fix-cache-race
cache: ignore ErrNotExist during cleanup of old files
2024-04-22 21:46:06 +02:00
Michael Eischer
f7632de3d6 Merge pull request #4772 from MichaelEischer/better-error-on-too-large-blob
repository: Better error message if blob is larger than 4GB
2024-04-22 21:45:06 +02:00
Michael Eischer
20d8eed400 repository: streamPack: separate requests for gap larger than 1MB
With most cloud providers, traffic is much more expensive than API
calls. Thus slightly bias streamPack towards a bit more API calls in
exchange for slightly less traffic.
2024-04-22 21:21:23 +02:00
Michael Eischer
cf700d8794 repository: streamPack: reuse zstd decoder 2024-04-22 21:21:23 +02:00
Michael Eischer
666a0b0bdb repository: streamPack: replace streaming with chunked download
Due to the interface of streamPack, we cannot guarantee that operations
progress fast enough that the underlying connections remains open. This
introduces partial failures which massively complicate the error
handling.

Switch to a simpler approach that retrieves the pack in chunks of 32MB.
If a blob is larger than this limit, then it is downloaded separately.

To avoid multiple copies in memory, an auxiliary interface
`discardReader` is introduced that allows directly accessing the
downloaded byte slices, while still supporting the streaming used by the
`check` command.
2024-04-22 21:21:23 +02:00
Michael Eischer
621012dac0 repository: Add blob loading fallback to LoadBlobsFromPack
Try to retrieve individual blobs via LoadBlob if streaming did not work.
2024-04-21 21:35:55 +02:00
Michael Eischer
6c6dceade3 global: unify backend open and create 2024-04-19 22:26:14 +02:00
Michael Eischer
10355c3fb6 repository: Better error message if blob is larger than 4GB 2024-04-19 22:00:35 +02:00
Michael Eischer
228b35f074 Merge pull request #4769 from will-ca/patch-1
Tiny wording clarification in `restic-stats.1`.
2024-04-18 19:00:39 +00:00
will-ca
6aced61c72 Tiny docs wording clarification. 2024-04-18 07:29:55 +00:00
Michael Eischer
4d22412e0c Merge pull request #4766 from coderwander/master
Fix struct names
2024-04-18 06:18:19 +00:00
coderwander
a82ed71de7 Fix struct names
Signed-off-by: coderwander <770732124@qq.com>
2024-04-18 10:02:09 +08:00
Michael Eischer
2173c69280 Merge pull request #4770 from testwill/close_files
fix: close files
2024-04-17 16:50:20 +00:00
Michael Eischer
001bb71676 repair packs: Properly close backup files 2024-04-17 18:32:30 +02:00
Michael Eischer
c9191ea72c forget: cleanup verbose output on snapshot deletion error 2024-04-14 14:17:40 +02:00
Michael Eischer
09587e6c08 repository: duplicate a few blobs in prune tests 2024-04-14 13:57:19 +02:00
Michael Eischer
defd7ae729 prune/repair index: reset in-memory index after command
The current in-memory index becomes stale after prune or repair index
have run. Thus, just drop the in-memory index altogether once these
commands have finished.
2024-04-14 13:46:24 +02:00
Michael Eischer
038586dc9d repository: add minimal test for prune 2024-04-14 13:45:17 +02:00
Michael Eischer
d8622c86eb prune: clean up internal interface 2024-04-14 13:45:15 +02:00
Michael Eischer
8d507c1372 repository: add basic test for RepairIndex 2024-04-14 13:45:15 +02:00
Michael Eischer
310db03c0e repair index: improve log output if index cannot be deleted
The operation will always fail with an error if an index cannot be
deleted. Thus, this change is purely cosmetic.
2024-04-14 13:45:13 +02:00
Michael Eischer
7d1b9cde34 repository: use normal Init method in tests 2024-04-14 13:45:11 +02:00
Michael Eischer
b25fc2c89d repository: remove redundant flushes from tests 2024-04-14 13:45:10 +02:00
Michael Eischer
c65459cd8a repository: speed up tests 2024-04-14 13:45:10 +02:00
Michael Eischer
eda9f7beb4 ui/progress: add helper to print messages during tests 2024-04-14 13:45:08 +02:00
Michael Eischer
35277b7797 backend/mem: cleanup not found error message 2024-04-14 13:45:06 +02:00
Michael Eischer
7ba5e95a82 check: allow tests to only verify pack&index integrity 2024-04-14 13:45:04 +02:00
Michael Eischer
4c9a10ca37 repair packs: deduplicate index rebuild 2024-04-14 13:45:02 +02:00
Michael Eischer
85e4021619 prune: move additional option checks to repository 2024-04-14 13:44:58 +02:00
Michael Eischer
55d56db31b Merge pull request #4743 from MichaelEischer/deprecate-s3legacy-layout
Deprecate s3legacy layout
2024-04-11 22:09:34 +02:00
Michael Eischer
fc3b548625 prune: move logic into repository package 2024-04-10 21:30:52 +02:00
Michael Eischer
df9d4b455d prune: prepare for moving code to repository package 2024-04-10 21:30:52 +02:00
Michael Eischer
866ddf5698 repair index: refactor code into repository package 2024-04-10 21:30:52 +02:00
Michael Eischer
32a234b67e prune/forget/repair index: convert output to use progress.Printer 2024-04-10 21:30:52 +02:00
Michael Eischer
739d11c2eb forget: replace usage of DeleteFilesChecked
This simplifies refactoring prune into the repository package.
2024-04-10 21:30:52 +02:00
Michael Eischer
591b421c4a Deprecate s3legacy layout 2024-04-10 21:27:56 +02:00
Michael Eischer
8efc3a8b7d Merge pull request #4668 from MichaelEischer/backup-xattr-parent-enoperm
backup: Ignore xattr.list permission error for parent directories
2024-04-10 21:25:28 +02:00
Michael Eischer
bf054c09d2 backup: Ignore xattr.list permission error for parent directories
On FreeBSD, limited users may not be able to even list xattrs for the
parent directories above the snapshot source paths. As this can cause
the backup to fail, just ignore those errors.
2024-04-10 20:46:15 +02:00
Michael Eischer
0747cf5319 cache: ignore ErrNotExist during cleanup of old files
Two restic processes running concurrently can try to remove the same
files from the cache. This could cause one process to fail with an error
if the other one has already remove a file that the current process also
tries to delete.
2024-04-10 19:25:51 +02:00
Michael Eischer
6091029fd6 Merge pull request #4756 from mgeisler/patch-1
doc: fix typo in 047_tuning_backup_parameters.rst
2024-04-07 19:24:09 +00:00
Martin Geisler
09d2183351 doc: fix typo in 047_tuning_backup_parameters.rst 2024-04-07 18:05:53 +02:00
Michael Eischer
a4b7ebecfc Merge pull request #4750 from restic/dependabot/go_modules/cloud.google.com/go/storage-1.40.0
build(deps): bump cloud.google.com/go/storage from 1.39.0 to 1.40.0
2024-04-03 20:10:41 +00:00
dependabot[bot]
ba136b31b8 build(deps): bump cloud.google.com/go/storage from 1.39.0 to 1.40.0
Bumps [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) from 1.39.0 to 1.40.0.
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.39.0...spanner/v1.40.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/storage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-03 20:03:22 +00:00
Michael Eischer
f328111a6e Merge pull request #4751 from restic/dependabot/go_modules/golang.org/x/net-0.23.0
build(deps): bump golang.org/x/net from 0.21.0 to 0.23.0
2024-04-03 19:52:29 +00:00
Michael Eischer
9fb017e67a Merge pull request #4745 from MichaelEischer/full-id-key-list
key list: include full key id in JSON output
2024-04-03 21:50:02 +02:00
Michael Eischer
49f98f25fc Merge pull request #4742 from MichaelEischer/consistent-rtest-import
Use consistent alias for interal/test package
2024-04-03 21:47:32 +02:00
dependabot[bot]
96c602a6de build(deps): bump golang.org/x/net from 0.21.0 to 0.23.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.21.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-03 19:41:38 +00:00
Michael Eischer
1d0a20dd58 Merge pull request #4748 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/azcore-1.10.0
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.9.2 to 1.10.0
2024-04-03 19:34:47 +00:00
Michael Eischer
6cca1d5705 Merge pull request #4655 from ae-govau/unixsocket
Enhancement: option to send HTTP over unix socket
2024-04-03 19:29:21 +00:00
dependabot[bot]
f8a72ac2a3 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore
Bumps [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) from 1.9.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/release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.9.2...sdk/azcore/v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azcore
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 02:32:19 +00:00
Michael Eischer
5145c8f9c0 key list: include full key id in JSON output 2024-03-31 12:25:20 +02:00
Michael Eischer
831fc4413d Merge pull request #4737 from stephan0307/3117
json output forget command: added id's in snapshots within reasons object
2024-03-29 13:11:24 +00:00
Stephan Paul
df07814ec2 forget json output: added id's in snapshots within reasons object
In order to evaluate the keep reasons for snapshots, there should be also the id's
to compare it with snapshots within the keep object. (See also Issue #3117)

In order to avoid output parameters also changed function addJSONSnapshots to asJSONSnapshots
2024-03-29 11:30:00 +01:00
Michael Eischer
ec2b79834a use consistent alias for interal/test package 2024-03-29 00:24:03 +01:00
Michael Eischer
510f6f06b0 Merge pull request #4709 from MichaelEischer/refactor-locking
Refactor locking into repository package
2024-03-28 23:53:09 +01:00
Michael Eischer
07eb6c315b add changelog for locking refactor 2024-03-28 23:46:58 +01:00
Michael Eischer
5e98f1e2eb repository: fix test setup race conditions 2024-03-28 23:17:02 +01:00
Michael Eischer
8155dbe711 correctly lock repository in integration tests 2024-03-28 23:17:02 +01:00
Michael Eischer
d18726cd70 ls: add missing read lock
As `ls` reads data from the repository, it must acquire a read lock
unless `--no-lock` was specified. The old behavior is equivalent to `ls
--no-lock`.
2024-03-28 23:17:02 +01:00
Michael Eischer
dc441c57a7 repository: unify repository initialization in tests
Tests should use a helper from internal/repository/testing.go to
construct a Repository object.
2024-03-28 23:17:02 +01:00
Michael Eischer
3ba1fa3cee repository: remove a few global variables 2024-03-28 23:17:02 +01:00
Michael Eischer
044e8bf821 repository: parallelize lock tests 2024-03-28 23:17:02 +01:00
Michael Eischer
e8df50fa3c repository: remove global list of locks 2024-03-28 22:46:33 +01:00
Michael Eischer
cbb5f89252 lock: move code to repository package 2024-03-28 22:46:33 +01:00
Michael Eischer
118a69a84b lock: replace lockRepo(Exclusive) with openWith(Read/Write/Exclusive)Lock
The new functions much better convey the intent behind the lock
request. This allows cleanly integrating noLock (for read) and dryRun
(write/exclusive) handling.

There are only minor changes to existing behavior with two exceptions:
- `tag` no longer accepts the `--no-lock` flag. As it replaces files in
  the repository, this always requires an exclusive lock.
- `debug examine` now returns an error if both `--extract-pack` and
  `--no-lock` are given.
2024-03-28 22:46:33 +01:00
Michael Eischer
7f9ad1c3db Merge pull request #4705 from MichaelEischer/snapshot-statistics
Store snapshot statistics & print snapshot size
2024-03-28 22:41:45 +01:00
Michael Eischer
71b6284155 Merge pull request #4006 from MichaelEischer/deviceID-only-for-hardlinks
archiver: only store deviceID for hardlinks
2024-03-28 22:33:28 +01:00
Michael Eischer
cf81f8ced6 stats: only check for hardlinks for files with more than one link 2024-03-28 21:29:27 +01:00
Michael Eischer
21cf38fe96 add changelog for deviceID only for hardlinks 2024-03-28 19:32:50 +01:00
Michael Eischer
d705741571 backup: test that deviceID is only stored for hardlinks 2024-03-28 19:32:50 +01:00
Michael Eischer
a9b3d86c4f features: remove example feature 2024-03-28 19:12:07 +01:00
Michael Eischer
a26d6ffa72 archiver: move deviceID handling behind feature flag 2024-03-28 19:12:07 +01:00
Michael Eischer
2ba21fe72b archiver: only store deviceID for hardlinks
The deviceID can change e.g. when backing up from filesystem snapshot.
It is only used for hardlink detection. Thus there it is not necessary
to store it for everything else.
2024-03-28 19:12:07 +01:00
Michael Eischer
870904d3ae Merge pull request #4731 from facutuesca/powershell-completion-doc
doc: Add instructions to configure PowerShell completions
2024-03-28 17:46:55 +00:00
Facundo Tuesca
15555c9898 doc: Use consistent case for PROFILE env variable in PowerShell 2024-03-28 18:35:18 +01:00
Michael Eischer
63a2350c9e Merge pull request #4741 from MichaelEischer/ci-upgrade-golangci-lint
CI: Update golangci-lint to version 1.57.1
2024-03-28 18:27:05 +01:00
Michael Eischer
8876e3025b Merge pull request #4724 from MichaelEischer/disable-old-index
Deprecated legacy index format
2024-03-28 18:24:47 +01:00
Michael Eischer
4f4979f4e8 Merge pull request #4740 from MichaelEischer/ci-upgrade-docker-actions
CI: update docker actions
2024-03-28 18:16:38 +01:00
Michael Eischer
1497525e15 CI: Update golangci-lint to version 1.57.1 2024-03-28 18:15:50 +01:00
Michael Eischer
a8face3a25 Merge pull request #4739 from MichaelEischer/ci-allow-annotations
CI: Allow golangci-lint to annotate PRs
2024-03-28 18:02:16 +01:00
Michael Eischer
aee6d311f1 CI: update docker actions 2024-03-28 18:01:48 +01:00
Michael Eischer
6ac7519188 add changelog for rest unix socket support 2024-03-28 17:41:41 +01:00
Michael Eischer
add37fcd9f CI: uses rest-server from master branch until unix sockets are released 2024-03-28 17:41:41 +01:00
Adam Eijdenberg
6e775d3787 Enhancement: option to send HTTP over unix socket
add tests for unix socket connection

switch HTTP rest-server test to use any free port

allow rest-server test graceful shutdown opportunity
2024-03-28 17:41:41 +01:00
Michael Eischer
5c4a4b4a30 CI: Allow golangci-lint to annotate PRs 2024-03-28 17:09:59 +01:00
Michael Eischer
d1d773cfcd Merge pull request #4727 from avoidalone/master
fix some typos
2024-03-17 18:52:40 +00:00
Facundo Tuesca
521713fc94 doc: Add instructions to configure PowerShell completions 2024-03-16 18:54:27 +01:00
avoidalone
ac948fccda fix some typos
Signed-off-by: avoidalone <wuguangdong@outlook.com>
2024-03-11 14:35:12 +08:00
rawtaz
9284f7413a Merge pull request #4725 from leoheitmannruiz/master
Minor README.md cleanups
2024-03-10 12:24:07 +00:00
rawtaz
1287b977b4 Merge pull request #4726 from leoheitmannruiz/patch-1
Capitalize Homebrew and minor edit in wording
2024-03-10 12:23:48 +00:00
Leo Heitmann Ruiz
00f762373f Capitalize Homebrew 2024-03-10 00:20:26 +01:00
Leo Heitmann Ruiz
9f3e1462c0 Minor README.md cleanups 2024-03-09 23:56:16 +01:00
Michael Eischer
69ca12d2eb check: treat legacy index format as errors 2024-03-09 18:36:33 +01:00
Michael Eischer
98a6817d01 add changelog for legacy index deprecation 2024-03-09 18:35:00 +01:00
Michael Eischer
f8852f0eb6 repair index: fix deletion of legacy indexes 2024-03-09 18:21:22 +01:00
Michael Eischer
1a8bf358f1 index: deprecate legacy index format 2024-03-09 18:21:14 +01:00
Michael Eischer
396a61a992 Merge pull request #4666 from MichaelEischer/feature-flags
Implement feature flags
2024-03-09 17:36:29 +01:00
Michael Eischer
a9b64cd7ad features: print warning for stable/depreacted feature flags 2024-03-09 17:29:52 +01:00
Michael Eischer
fe68d2cafb add feature flag documentation 2024-03-09 17:29:52 +01:00
Michael Eischer
70839155f2 features: add tests 2024-03-09 17:29:52 +01:00
Michael Eischer
1c77c51a03 features: initialize based on RESTIC_FEATURES environment variable 2024-03-09 17:29:52 +01:00
Michael Eischer
5974a79497 features: add basic feature flag implementation 2024-03-09 17:29:52 +01:00
Michael Eischer
0589da60b3 Merge pull request #4717 from restic/dependabot/go_modules/cloud.google.com/go/storage-1.39.0
build(deps): bump cloud.google.com/go/storage from 1.37.0 to 1.39.0
2024-03-07 14:10:24 +00:00
dependabot[bot]
608116817b build(deps): bump cloud.google.com/go/storage from 1.37.0 to 1.39.0
Bumps [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) from 1.37.0 to 1.39.0.
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.37.0...spanner/v1.39.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/storage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-07 13:59:23 +00:00
Michael Eischer
f742da8b2f Merge pull request #4722 from konidev20/upgrade-docker-golang-base-image-to-1-22
docker: update the base image to golang:1.22-alpine
2024-03-07 13:44:48 +00:00
Michael Eischer
af1684743f Merge pull request #4716 from restic/dependabot/go_modules/github.com/klauspost/compress-1.17.7
build(deps): bump github.com/klauspost/compress from 1.17.6 to 1.17.7
2024-03-07 13:41:46 +00:00
Michael Eischer
5b9de4d8b7 Merge pull request #4715 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob-1.3.1
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob from 1.2.1 to 1.3.1
2024-03-07 13:40:44 +00:00
Michael Eischer
fceef67abe Merge pull request #4718 from restic/dependabot/go_modules/github.com/spf13/cobra-1.8.0
build(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0
2024-03-07 13:37:17 +00:00
Michael Eischer
8506cae710 Merge pull request #4714 from restic/dependabot/github_actions/golangci/golangci-lint-action-4
build(deps): bump golangci/golangci-lint-action from 3 to 4
2024-03-07 13:34:21 +00:00
Michael Eischer
87d47ef189 Merge pull request #4713 from restic/dependabot/github_actions/docker/login-action-5139682d94efc37792e6b54386b5b470a68a4737
build(deps): bump docker/login-action from 3d58c274f17dffee475a5520cbe67f0a882c4dbb to 5139682d94efc37792e6b54386b5b470a68a4737
2024-03-07 13:33:49 +00:00
Michael Eischer
55abf25ea8 Merge pull request #4719 from restic/dependabot/go_modules/golang.org/x/oauth2-0.17.0
build(deps): bump golang.org/x/oauth2 from 0.16.0 to 0.17.0
2024-03-07 13:32:36 +00:00
Srigovind Nayak
b48b1fa2c9 docker: update the base image to golang:1.22-alpine 2024-03-03 16:18:13 +05:30
dependabot[bot]
8e7f29ae28 build(deps): bump golang.org/x/oauth2 from 0.16.0 to 0.17.0
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 01:25:47 +00:00
dependabot[bot]
79e8ddac3f build(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 01:25:41 +00:00
dependabot[bot]
b5a9b5d0bc build(deps): bump github.com/klauspost/compress from 1.17.6 to 1.17.7
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.6 to 1.17.7.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml)
- [Commits](https://github.com/klauspost/compress/compare/v1.17.6...v1.17.7)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 01:25:00 +00:00
dependabot[bot]
f185c80cf0 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.2.1 to 1.3.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/azidentity/v1.2.1...sdk/azcore/v1.3.1)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 01:24:46 +00:00
dependabot[bot]
70c8aaa303 build(deps): bump golangci/golangci-lint-action from 3 to 4
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3 to 4.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 01:17:27 +00:00
dependabot[bot]
e1a588b75c build(deps): bump docker/login-action
Bumps [docker/login-action](https://github.com/docker/login-action) from 3d58c274f17dffee475a5520cbe67f0a882c4dbb to 5139682d94efc37792e6b54386b5b470a68a4737.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](3d58c274f1...5139682d94)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 01:17:20 +00:00
Michael Eischer
e71660cd1e backup: rename data_added_in_repo statistic to data_added_packed 2024-02-25 20:40:52 +01:00
Aneesh Nireshwalia
062d408987 Clean up SecurityDescriptor helper 2024-02-24 14:23:04 -07:00
Aneesh Nireshwalia
5764300022 Add changelog and fix lint error 2024-02-24 13:47:49 -07:00
Aneesh Nireshwalia
c0a1b9ada5 Update docs for security descriptors 2024-02-24 13:28:18 -07:00
Aneesh Nireshwalia
90916f53de Add test cases for security descriptors 2024-02-24 13:27:01 -07:00
Aneesh Nireshwalia
70cf8e3788 Add support for backup/restore of security descriptors 2024-02-24 13:25:28 -07:00
Aneesh Nireshwalia
e3e59fef24 Fix CombineErrors and fillExtendedAttr error handling 2024-02-24 13:22:34 -07:00
Aneesh Nireshwalia
09ce1b4e58 Create helper for SecurityDescriptor related functions 2024-02-24 13:16:25 -07:00
Michael Eischer
6a13e451b1 document snapshot statistics 2024-02-23 22:32:04 +01:00
Michael Eischer
a8f5684f68 archiver: test statistics in snapshot 2024-02-23 22:05:15 +01:00
Michael Eischer
681395955e archiver: test backup summary calculation 2024-02-23 21:46:39 +01:00
Michael Eischer
b6520038fd snapshots: Print snapshot size stored in snapshots 2024-02-23 20:27:13 +01:00
Michael Eischer
38f91d3b5e backup: store statistics in snapshot 2024-02-23 20:27:13 +01:00
Michael Eischer
86897314d5 backup: expose data_added_in_repo in JSON output
The value describes how much data was added after compression.
Previously, it was only available in the text output.
2024-02-23 20:27:13 +01:00
Michael Eischer
a59f654fa6 archiver: refactor summary collection from ui into the archiver 2024-02-23 20:27:13 +01:00
Michael Eischer
8b1a85711f archiver: unexport save/saveDir/saveTree methods 2024-02-23 20:24:21 +01:00
Michael Eischer
b953dc8f58 Merge pull request #4611 from zmanda/windows-metadata-support
Back up and restore windows metadata like created ts, file attribs like hidden, readonly, encrypted with a common extensible mechanism
2024-02-23 18:16:09 +00:00
Aneesh Nireshwalia
e8211cb64a Add changelog and update docs for windows attr 2024-02-22 17:59:56 -07:00
Aneesh Nireshwalia
4bbd25a37f Add tests for generic attribute changes 2024-02-22 17:55:50 -07:00
Aneesh Nireshwalia
d4be734c73 Handle readonly empty files in windows 2024-02-22 17:54:43 -07:00
Aneesh Nireshwalia
eeb1aa5388 Add ability to report warnings to terminal
Report warnings to terminal when unrecognized generic attributes are found in the repository.
2024-02-22 17:52:26 -07:00
Aneesh Nireshwalia
0962917974 Support windows metadata using generic attribs
Add new generic_attributes attribute in Node.
Use the generic attributes to add support for creation time and file attributes like hidden, readonly, encrypted in windows. Handle permission errors for readonly files in windows.
Handle backup and restore of encrypted attributes using windows system calls.
2024-02-22 17:31:20 -07:00
Aneesh Nireshwalia
62a8a599f1 Add optional messages for Equals helper 2024-02-22 16:58:12 -07:00
Aneesh Nireshwalia
94de87d4b7 Add CombineErrors helper function 2024-02-22 16:57:00 -07:00
Michael Eischer
c6311c1e32 Merge pull request #4703 from ferringb/master
Catch SIGTERM, run cleanup
2024-02-22 21:06:29 +00:00
Michael Eischer
0a65a0f94f update comment 2024-02-22 22:00:42 +01:00
Brian Harring
b41107dcaf Add changelog for SIGTERM bugfix.
Signed-off-by: Brian Harring <ferringb@gmail.com>
2024-02-19 11:31:48 +01:00
Brian Harring
30e979d252 Catch SIGTERM, run cleanup
The previous code only ran cleanup (lock release for example) on SIGINT.  For
anyone running restic in a container, the signal is going to be SIGTERM which
means containerized execution would leave locks behind.

While this could be addressed via interposing dumb-init to translate the signal,
a `kill` invocation is going to default to SIGTERM, so the same problem exists
for non container users.

Signed-off-by: Brian Harring <ferringb@gmail.com>
2024-02-19 11:12:15 +01:00
Michael Eischer
cfbeb2cde5 Merge pull request #4701 from MichaelEischer/better-streampack-errors
repository: Improve StreamPack error messages
2024-02-18 16:57:56 +01:00
Michael Eischer
80754dbf0c Merge pull request #4664 from MichaelEischer/ls-unified-json-output
ls: include standard `message_type` field in output
2024-02-18 15:47:41 +00:00
Michael Eischer
4c3218ef9f repository: include packID in StreamPack for decrypt/decompress errors 2024-02-17 19:38:01 +01:00
Michael Eischer
18b0bbbf42 repository: use fmt.Errorf in StreamPacks 2024-02-17 19:37:32 +01:00
Michael Eischer
5dca8a70d5 ls: include standard message_type field in output 2024-01-27 15:48:24 +01:00
423 changed files with 18873 additions and 9349 deletions

View File

@@ -25,7 +25,7 @@ jobs:
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@3d58c274f17dffee475a5520cbe67f0a882c4dbb
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -33,7 +33,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
@@ -45,7 +45,7 @@ jobs:
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226
uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20
- name: Ensure consistent binaries
run: |
@@ -55,7 +55,7 @@ jobs:
if: github.ref != 'refs/heads/master'
- name: Build and push Docker image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1
with:
push: true
context: .

View File

@@ -74,7 +74,7 @@ jobs:
- name: Get programs (Linux/macOS)
run: |
echo "build Go tools"
go install github.com/restic/rest-server/cmd/rest-server@latest
go install github.com/restic/rest-server/cmd/rest-server@master
echo "install minio server"
mkdir $HOME/bin
@@ -106,7 +106,7 @@ jobs:
$ProgressPreference = 'SilentlyContinue'
echo "build Go tools"
go install github.com/restic/rest-server/...
go install github.com/restic/rest-server/cmd/rest-server@master
echo "install minio server"
mkdir $Env:USERPROFILE/bin
@@ -247,6 +247,10 @@ jobs:
lint:
name: lint
runs-on: ubuntu-latest
permissions:
contents: read
# allow annotating code in the PR
checks: write
steps:
- name: Set up Go ${{ env.latest_go }}
uses: actions/setup-go@v5
@@ -257,10 +261,10 @@ jobs:
uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v6
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.56.1
version: v1.57.1
args: --verbose --timeout 5m
# only run golangci-lint for pull requests, otherwise ALL hints get
@@ -298,7 +302,7 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base name for tags
images: |
@@ -321,7 +325,7 @@ jobs:
- name: Build and push
id: docker_build
uses: docker/build-push-action@v4
uses: docker/build-push-action@v6
with:
push: false
context: .

View File

@@ -38,6 +38,8 @@ linters:
# ensure that http response bodies are closed
- bodyclose
- importas
issues:
# don't use the default exclude rules, this hides (among others) ignored
# errors from Close() calls
@@ -58,4 +60,10 @@ issues:
exclude-rules:
# revive: ignore unused parameters in tests
- path: (_test\.go|testing\.go|backend/.*/tests\.go)
text: "unused-parameter:"
text: "unused-parameter:"
linters-settings:
importas:
alias:
- pkg: github.com/restic/restic/internal/test
alias: rtest

View File

@@ -1,5 +1,7 @@
# Table of Contents
* [Changelog for 0.17.0](#changelog-for-restic-0170-2024-07-26)
* [Changelog for 0.16.5](#changelog-for-restic-0165-2024-07-01)
* [Changelog for 0.16.4](#changelog-for-restic-0164-2024-02-04)
* [Changelog for 0.16.3](#changelog-for-restic-0163-2024-01-14)
* [Changelog for 0.16.2](#changelog-for-restic-0162-2023-10-29)
@@ -33,6 +35,738 @@
* [Changelog for 0.6.0](#changelog-for-restic-060-2017-05-29)
# Changelog for restic 0.17.0 (2024-07-26)
The following sections list the changes in restic 0.17.0 relevant to
restic users. The changes are ordered by importance.
## Summary
* Fix #3600: Handle unreadable xattrs in folders above `backup` source
* Fix #4209: Fix slow SFTP upload performance
* Fix #4503: Correct hardlink handling in `stats` command
* Fix #4568: Prevent `forget --keep-tags <invalid>` from deleting all snapshots
* Fix #4615: Make `find` not sometimes ignore directories
* Fix #4656: Properly report ID of newly added keys
* Fix #4703: Shutdown cleanly when receiving SIGTERM
* Fix #4709: Correct `--no-lock` handling of `ls` and `tag` commands
* Fix #4760: Fix possible error on concurrent cache cleanup
* Fix #4850: Handle UTF-16 password files in `key` command correctly
* Fix #4902: Update snapshot summary on `rewrite`
* Chg #956: Return exit code 10 and 11 for non-existing and locked repository
* Chg #4540: Require at least ARMv6 for ARM binaries
* Chg #4602: Deprecate legacy index format and `s3legacy` repository layout
* Chg #4627: Redesign backend error handling to improve reliability
* Chg #4707: Disable S3 anonymous authentication by default
* Chg #4744: Include full key ID in JSON output of `key list`
* Enh #662: Optionally skip snapshot creation if nothing changed
* Enh #693: Include snapshot size in `snapshots` output
* Enh #805: Add bitrot detection to `diff` command
* Enh #828: Improve features of the `repair packs` command
* Enh #1786: Support repositories with empty password
* Enh #2348: Add `--delete` option to `restore` command
* Enh #3067: Add extended options to configure Windows Shadow Copy Service
* Enh #3406: Improve `dump` performance for large files
* Enh #3806: Optimize and make `prune` command resumable
* Enh #4006: (alpha) Store deviceID only for hardlinks
* Enh #4048: Add support for FUSE-T with `mount` on macOS
* Enh #4251: Support reading backup from a command's standard output
* Enh #4287: Support connection to rest-server using unix socket
* Enh #4354: Significantly reduce `prune` memory usage
* Enh #4437: Make `check` command create non-existent cache directory
* Enh #4472: Support AWS Assume Role for S3 backend
* Enh #4547: Add `--json` option to `version` command
* Enh #4549: Add `--ncdu` option to `ls` command
* Enh #4573: Support rewriting host and time metadata in snapshots
* Enh #4583: Ignore `s3.storage-class` archive tiers for metadata
* Enh #4590: Speed up `mount` command's error detection
* Enh #4601: Add support for feature flags
* Enh #4611: Back up more file metadata on Windows
* Enh #4664: Make `ls` use `message_type` field in JSON output
* Enh #4676: Make `key` command's actions separate sub-commands
* Enh #4678: Add `--target` option to the `dump` command
* Enh #4708: Back up and restore SecurityDescriptors on Windows
* Enh #4733: Allow specifying `--host` via environment variable
* Enh #4737: Include snapshot ID in `reason` field of `forget` JSON output
* Enh #4764: Support forgetting all snapshots
* Enh #4768: Allow specifying custom User-Agent for outgoing requests
* Enh #4781: Add `restore` options to read include/exclude patterns from files
* Enh #4807: Support Extended Attributes on Windows NTFS
* Enh #4817: Make overwrite behavior of `restore` customizable
* Enh #4839: Add dry-run support to `restore` command
## Details
* Bugfix #3600: Handle unreadable xattrs in folders above `backup` source
When backup sources are specified using absolute paths, `backup` also includes
information about the parent folders of the backup sources in the snapshot.
If the extended attributes for some of these folders could not be read due to
missing permissions, this caused the backup to fail. This has now been fixed.
https://github.com/restic/restic/issues/3600
https://github.com/restic/restic/pull/4668
https://forum.restic.net/t/parent-directories-above-the-snapshot-source-path-fatal-error-permission-denied/7216
* Bugfix #4209: Fix slow SFTP upload performance
Since restic 0.12.1, the upload speed of the sftp backend to a remote server has
regressed significantly. This has now been fixed.
https://github.com/restic/restic/issues/4209
https://github.com/restic/restic/pull/4782
* Bugfix #4503: Correct hardlink handling in `stats` command
If files on different devices had the same inode ID, the `stats` command did not
correctly calculate the snapshot size. This has now been fixed.
https://github.com/restic/restic/pull/4503
https://github.com/restic/restic/pull/4006
https://forum.restic.net/t/possible-bug-in-stats/6461/8
* Bugfix #4568: Prevent `forget --keep-tags <invalid>` from deleting all snapshots
Running `forget --keep-tags <invalid>`, where `<invalid>` is a tag that does not
exist in the repository, would remove all snapshots. This is especially
problematic if the tag name contains a typo.
The `forget` command now fails with an error if all snapshots in a snapshot
group would be deleted. This prevents the above example from deleting all
snapshots.
It is possible to temporarily disable the new check by setting the environment
variable `RESTIC_FEATURES=safe-forget-keep-tags=false`. Note that this feature
flag will be removed in the next minor restic version.
https://github.com/restic/restic/pull/4568
https://github.com/restic/restic/pull/4764
* Bugfix #4615: Make `find` not sometimes ignore directories
In some cases, the `find` command ignored empty or moved directories. This has
now been fixed.
https://github.com/restic/restic/pull/4615
* Bugfix #4656: Properly report ID of newly added keys
`restic key add` now reports the ID of the newly added key. This simplifies
selecting a specific key using the `--key-hint key` option.
https://github.com/restic/restic/issues/4656
https://github.com/restic/restic/pull/4657
* Bugfix #4703: Shutdown cleanly when receiving SIGTERM
Previously, when restic received the SIGTERM signal it would terminate
immediately, skipping cleanup and potentially causing issues like stale locks
being left behind. This primarily effected containerized restic invocations that
use SIGTERM, but could also be triggered via a simple `killall restic`.
This has now been fixed, such that restic shuts down cleanly when receiving the
SIGTERM signal.
https://github.com/restic/restic/pull/4703
* Bugfix #4709: Correct `--no-lock` handling of `ls` and `tag` commands
The `ls` command never locked the repository. This has now been fixed, with the
old behavior still being supported using `ls --no-lock`. The latter invocation
also works with older restic versions.
The `tag` command erroneously accepted the `--no-lock` command. This command now
always requires an exclusive lock.
https://github.com/restic/restic/pull/4709
* Bugfix #4760: Fix possible error on concurrent cache cleanup
If multiple restic processes concurrently cleaned up no longer existing files
from the cache, this could cause some of the processes to fail with an `no such
file or directory` error. This has now been fixed.
https://github.com/restic/restic/issues/4760
https://github.com/restic/restic/pull/4761
* Bugfix #4850: Handle UTF-16 password files in `key` command correctly
Previously, `key add` and `key passwd` did not properly decode UTF-16 encoded
passwords read from a password file. This has now been fixed to correctly match
the encoding when opening a repository.
https://github.com/restic/restic/issues/4850
https://github.com/restic/restic/pull/4851
* Bugfix #4902: Update snapshot summary on `rewrite`
Restic previously did not recalculate the total number of files and bytes
processed when files were excluded from a snapshot by the `rewrite` command.
This has now been fixed.
https://github.com/restic/restic/issues/4902
https://github.com/restic/restic/pull/4905
* Change #956: Return exit code 10 and 11 for non-existing and locked repository
If a repository does not exist or cannot be locked, restic previously always
returned exit code 1. This made it difficult to distinguish these cases from
other errors.
Restic now returns exit code 10 if the repository does not exist, and exit code
11 if the repository could be not locked due to a conflicting lock.
https://github.com/restic/restic/issues/956
https://github.com/restic/restic/pull/4884
* Change #4540: Require at least ARMv6 for ARM binaries
The official release binaries of restic now require at least ARMv6 support for
ARM platforms.
https://github.com/restic/restic/issues/4540
https://github.com/restic/restic/pull/4542
* Change #4602: Deprecate legacy index format and `s3legacy` repository layout
Support for the legacy index format used by restic before version 0.2.0 has been
deprecated and will be removed in the next minor restic version. You can use
`restic repair index` to update the index to the current format.
It is possible to temporarily reenable support for the legacy index format by
setting the environment variable `RESTIC_FEATURES=deprecate-legacy-index=false`.
Note that this feature flag will be removed in the next minor restic version.
Support for the `s3legacy` repository layout used for the S3 backend before
restic 0.7.0 has been deprecated and will be removed in the next minor restic
version. You can migrate your S3 repository to the current layout using
`RESTIC_FEATURES=deprecate-s3-legacy-layout=false restic migrate s3_layout`.
It is possible to temporarily reenable support for the `s3legacy` layout by
setting the environment variable
`RESTIC_FEATURES=deprecate-s3-legacy-layout=false`. Note that this feature flag
will be removed in the next minor restic version.
https://github.com/restic/restic/issues/4602
https://github.com/restic/restic/pull/4724
https://github.com/restic/restic/pull/4743
* Change #4627: Redesign backend error handling to improve reliability
Restic now downloads pack files in large chunks instead of using a streaming
download. This prevents failures due to interrupted streams. The `restore`
command now also retries downloading individual blobs that could not be
retrieved.
HTTP requests that are stuck for more than two minutes while uploading or
downloading are now forcibly interrupted. This ensures that stuck requests are
retried after a short timeout.
Attempts to access a missing or truncated file will no longer be retried. This
avoids unnecessary retries in those cases. All other backend requests are
retried for up to 15 minutes. This ensures that temporarily interrupted network
connections can be tolerated.
If a download yields a corrupt file or blob, then the download will be retried
once.
Most parts of the new backend error handling can temporarily be disabled by
setting the environment variable `RESTIC_FEATURES=backend-error-redesign=false`.
Note that this feature flag will be removed in the next minor restic version.
https://github.com/restic/restic/issues/4627
https://github.com/restic/restic/issues/4193
https://github.com/restic/restic/issues/4515
https://github.com/restic/restic/issues/1523
https://github.com/restic/restic/pull/4605
https://github.com/restic/restic/pull/4792
https://github.com/restic/restic/pull/4520
https://github.com/restic/restic/pull/4800
https://github.com/restic/restic/pull/4784
https://github.com/restic/restic/pull/4844
* Change #4707: Disable S3 anonymous authentication by default
When using the S3 backend with anonymous authentication, it continuously tried
to retrieve new authentication credentials, causing bad performance.
Now, to use anonymous authentication, it is necessary to pass the extended
option `-o s3.unsafe-anonymous-auth=true` to restic.
It is possible to temporarily revert to the old behavior by setting the
environment variable `RESTIC_FEATURES=explicit-s3-anonymous-auth=false`. Note
that this feature flag will be removed in the next minor restic version.
https://github.com/restic/restic/issues/4707
https://github.com/restic/restic/pull/4908
* Change #4744: Include full key ID in JSON output of `key list`
The JSON output of the `key list` command has changed to include the full key ID
instead of just a shortened version of the ID, as the latter can be ambiguous in
some rare cases. To derive the short ID, please truncate the full ID down to
eight characters.
https://github.com/restic/restic/issues/4744
https://github.com/restic/restic/pull/4745
* Enhancement #662: Optionally skip snapshot creation if nothing changed
The `backup` command always created a snapshot even if nothing in the backup set
changed compared to the parent snapshot.
Restic now supports the `--skip-if-unchanged` option for the `backup` command,
which omits creating a snapshot if the new snapshot's content would be identical
to that of the parent snapshot.
https://github.com/restic/restic/issues/662
https://github.com/restic/restic/pull/4816
* Enhancement #693: Include snapshot size in `snapshots` output
The `snapshots` command now prints the size for snapshots created using this or
a future restic version. To achieve this, the `backup` command now stores the
backup summary statistics in the snapshot.
The text output of the `snapshots` command only shows the snapshot size. The
other statistics are only included in the JSON output. To inspect these
statistics use `restic snapshots --json` or `restic cat snapshot <snapshotID>`.
https://github.com/restic/restic/issues/693
https://github.com/restic/restic/pull/4705
https://github.com/restic/restic/pull/4913
* Enhancement #805: Add bitrot detection to `diff` command
The output of the `diff` command now includes the modifier `?` for files to
indicate bitrot in backed up files. The `?` will appear whenever there is a
difference in content while the metadata is exactly the same.
Since files with unchanged metadata are normally not read again when creating a
backup, the detection is only effective when the right-hand side of the diff has
been created with `backup --force`.
https://github.com/restic/restic/issues/805
https://github.com/restic/restic/pull/4526
* Enhancement #828: Improve features of the `repair packs` command
The `repair packs` command has been improved to also be able to process
truncated pack files. The `check` and `check --read-data` command will provide
instructions on using the command if necessary to repair a repository. See the
guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html for
further instructions.
https://github.com/restic/restic/issues/828
https://github.com/restic/restic/pull/4644
https://github.com/restic/restic/pull/4882
* Enhancement #1786: Support repositories with empty password
Restic previously required a password to create or operate on repositories.
Using the new option `--insecure-no-password` it is now possible to disable this
requirement. Restic will not prompt for a password when using this option.
For security reasons, the option must always be specified when operating on
repositories with an empty password, and specifying `--insecure-no-password`
while also passing a password to restic via a CLI option or environment variable
results in an error.
The `init` and `copy` commands add the related `--from-insecure-no-password`
option, which applies to the source repository. The `key add` and `key passwd`
commands add the `--new-insecure-no-password` option to add or set an empty
password.
https://github.com/restic/restic/issues/1786
https://github.com/restic/restic/issues/4326
https://github.com/restic/restic/pull/4698
https://github.com/restic/restic/pull/4808
* Enhancement #2348: Add `--delete` option to `restore` command
The `restore` command now supports a `--delete` option that allows removing
files and directories from the target directory that do not exist in the
snapshot. This option also allows files in the snapshot to replace non-empty
directories having the same name.
To check that only expected files are deleted, add the `--dry-run --verbose=2`
options.
https://github.com/restic/restic/issues/2348
https://github.com/restic/restic/pull/4881
* Enhancement #3067: Add extended options to configure Windows Shadow Copy Service
Previous, restic always used a 120 seconds timeout and unconditionally created
VSS snapshots for all volume mount points on disk. This behavior can now be
fine-tuned by the following new extended options (available only on Windows):
- `-o vss.timeout`: Time that VSS can spend creating snapshot before timing out
(default: 120s) - `-o vss.exclude-all-mount-points`: Exclude mountpoints from
snapshotting on all volumes (default: false) - `-o vss.exclude-volumes`:
Semicolon separated list of volumes to exclude from snapshotting - `-o
vss.provider`: VSS provider identifier which will be used for snapshotting
For example, change VSS timeout to five minutes and disable snapshotting of
mount points on all volumes:
Restic backup --use-fs-snapshot -o vss.timeout=5m -o
vss.exclude-all-mount-points=true
Exclude drive `d:`, mount point `c:\mnt` and a specific volume from
snapshotting:
Restic backup --use-fs-snapshot -o
vss.exclude-volumes="d:\;c:\mnt\;\\?\Volume{e2e0315d-9066-4f97-8343-eb5659b35762}"
Uses 'Microsoft Software Shadow Copy provider 1.0' instead of the default
provider:
Restic backup --use-fs-snapshot -o
vss.provider={b5946137-7b9f-4925-af80-51abd60b20d5}
https://github.com/restic/restic/pull/3067
* Enhancement #3406: Improve `dump` performance for large files
The `dump` command now retrieves the data chunks for a file in parallel. This
improves the download performance by up to as many times as the configured
number of parallel backend connections.
https://github.com/restic/restic/issues/3406
https://github.com/restic/restic/pull/4796
* Enhancement #3806: Optimize and make `prune` command resumable
Previously, if the `prune` command was interrupted, a later `prune` run would
start repacking pack files from the start, as `prune` did not update the index
while repacking.
The `prune` command now supports resuming interrupted prune runs. The update of
the repository index has also been optimized to use less memory and only rewrite
parts of the index that have changed.
https://github.com/restic/restic/issues/3806
https://github.com/restic/restic/pull/4812
* Enhancement #4006: (alpha) Store deviceID only for hardlinks
Set `RESTIC_FEATURES=device-id-for-hardlinks` to enable this alpha feature. The
feature flag will be removed after repository format version 3 becomes available
or be replaced with a different solution.
When creating backups from a filesystem snapshot, for example created using
BTRFS subvolumes, the deviceID of the filesystem changes compared to previous
snapshots. This prevented restic from deduplicating the directory metadata of a
snapshot.
When this alpha feature is enabled, the deviceID is only stored for hardlinks,
which significantly reduces the metadata duplication for most backups.
https://github.com/restic/restic/pull/4006
* Enhancement #4048: Add support for FUSE-T with `mount` on macOS
The restic `mount` command now supports creating FUSE mounts using FUSE-T on
macOS.
https://github.com/restic/restic/issues/4048
https://github.com/restic/restic/pull/4825
* Enhancement #4251: Support reading backup from a command's standard output
The `backup` command now supports the `--stdin-from-command` option. When using
this option, the arguments to `backup` are interpreted as a command instead of
paths to back up. `backup` then executes the given command and stores the
standard output from it in the backup, similar to the what the `--stdin` option
does. This also enables restic to verify that the command completes with exit
code zero. A non-zero exit code causes the backup to fail.
Note that the `--stdin` option does not have to be specified at the same time,
and that the `--stdin-filename` option also applies to `--stdin-from-command`.
Example: `restic backup --stdin-from-command --stdin-filename dump.sql mysqldump
[...]`
https://github.com/restic/restic/issues/4251
https://github.com/restic/restic/pull/4410
* Enhancement #4287: Support connection to rest-server using unix socket
Restic now supports using a unix socket to connect to a rest-server version
0.13.0 or later. This allows running restic as follows:
```
rest-server --listen unix:/tmp/rest.socket --data /path/to/data &
restic -r rest:http+unix:///tmp/rest.socket:/my_backup_repo/ [...]
```
https://github.com/restic/restic/issues/4287
https://github.com/restic/restic/pull/4655
* Enhancement #4354: Significantly reduce `prune` memory usage
The `prune` command has been optimized to use up to 60% less memory. The memory
usage should now be roughly similar to creating a backup.
https://github.com/restic/restic/pull/4354
https://github.com/restic/restic/pull/4812
* Enhancement #4437: Make `check` command create non-existent cache directory
Previously, if a custom cache directory was specified for the `check` command,
but the directory did not exist, `check` continued with the cache disabled.
The `check` command now attempts to create the cache directory before
initializing the cache.
https://github.com/restic/restic/issues/4437
https://github.com/restic/restic/pull/4805
https://github.com/restic/restic/pull/4883
* Enhancement #4472: Support AWS Assume Role for S3 backend
Previously only credentials discovered via the Minio discovery methods were used
to authenticate.
However, there are many circumstances where the discovered credentials have
lower permissions and need to assume a specific role. This is now possible using
the following new environment variables:
- RESTIC_AWS_ASSUME_ROLE_ARN - RESTIC_AWS_ASSUME_ROLE_SESSION_NAME -
RESTIC_AWS_ASSUME_ROLE_EXTERNAL_ID - RESTIC_AWS_ASSUME_ROLE_REGION (defaults to
us-east-1) - RESTIC_AWS_ASSUME_ROLE_POLICY - RESTIC_AWS_ASSUME_ROLE_STS_ENDPOINT
https://github.com/restic/restic/issues/4472
https://github.com/restic/restic/pull/4474
* Enhancement #4547: Add `--json` option to `version` command
Restic now supports outputting restic version along with the Go version, OS and
architecture used to build restic in JSON format using `version --json`.
https://github.com/restic/restic/issues/4547
https://github.com/restic/restic/pull/4553
* Enhancement #4549: Add `--ncdu` option to `ls` command
NCDU (NCurses Disk Usage) is a tool to analyse disk usage of directories. It has
an option to save a directory tree and analyse it later.
The `ls` command now supports outputting snapshot information in the NCDU format
using the `--ncdu` option. Example usage: `restic ls latest --ncdu | ncdu -f -`
https://github.com/restic/restic/issues/4549
https://github.com/restic/restic/pull/4550
https://github.com/restic/restic/pull/4911
* Enhancement #4573: Support rewriting host and time metadata in snapshots
The `rewrite` command now supports rewriting the host and/or time metadata of a
snapshot using the new `--new-host` and `--new-time` options.
https://github.com/restic/restic/pull/4573
* Enhancement #4583: Ignore `s3.storage-class` archive tiers for metadata
Restic used to store all files on S3 using the specified `s3.storage-class`.
Now, restic will only use non-archive storage tiers for metadata, to avoid
problems when accessing a repository. To restore any data, it is still necessary
to manually warm up the required data beforehand.
NOTE: There is no official cold storage support in restic, use this option at
your own risk.
https://github.com/restic/restic/issues/4583
https://github.com/restic/restic/pull/4584
* Enhancement #4590: Speed up `mount` command's error detection
The `mount` command now checks for the existence of the mountpoint before
opening the repository, leading to quicker error detection.
https://github.com/restic/restic/pull/4590
* Enhancement #4601: Add support for feature flags
Restic now supports feature flags that can be used to enable and disable
experimental features. The flags can be set using the environment variable
`RESTIC_FEATURES`. To get a list of currently supported feature flags, use the
`features` command.
https://github.com/restic/restic/issues/4601
https://github.com/restic/restic/pull/4666
* Enhancement #4611: Back up more file metadata on Windows
Previously, restic did not back up all common Windows-specific metadata.
Restic now stores file creation time and file attributes like the hidden,
read-only and encrypted flags when backing up files and folders on Windows.
https://github.com/restic/restic/pull/4611
* Enhancement #4664: Make `ls` use `message_type` field in JSON output
The `ls` command was the only restic command that used the `struct_type` field
in its JSON output format to specify the message type.
The JSON output of the `ls` command now also includes the `message_type` field,
which is consistent with other commands. The `struct_type` field is still
included, but now deprecated.
https://github.com/restic/restic/pull/4664
* Enhancement #4676: Make `key` command's actions separate sub-commands
Each of the `add`, `list`, `remove` and `passwd` actions provided by the `key`
command is now a separate sub-command and have its own documentation which can
be invoked using `restic key <add|list|remove|passwd> --help`.
https://github.com/restic/restic/issues/4676
https://github.com/restic/restic/pull/4685
* Enhancement #4678: Add `--target` option to the `dump` command
Restic `dump` always printed to the standard output. It now supports specifying
a `--target` file to write its output to.
https://github.com/restic/restic/issues/4678
https://github.com/restic/restic/pull/4682
https://github.com/restic/restic/pull/4692
* Enhancement #4708: Back up and restore SecurityDescriptors on Windows
Restic now backs up and restores SecurityDescriptors for files and folders on
Windows which includes owner, group, discretionary access control list (DACL)
and system access control list (SACL).
This requires the user to be a member of backup operators or the application
must be run as admin. If that is not the case, only the current user's owner,
group and DACL will be backed up, and during restore only the DACL of the backed
up file will be restored, with the current user's owner and group being set on
the restored file.
https://github.com/restic/restic/pull/4708
* Enhancement #4733: Allow specifying `--host` via environment variable
Restic commands that operate on snapshots, such as `restic backup` and `restic
snapshots`, support the `--host` option to specify the hostname for grouping
snapshots.
Such commands now also support specifying the hostname via the environment
variable `RESTIC_HOST`. Note that `--host` still takes precedence over the
environment variable.
https://github.com/restic/restic/issues/4733
https://github.com/restic/restic/pull/4734
* Enhancement #4737: Include snapshot ID in `reason` field of `forget` JSON output
The JSON output of the `forget` command now includes `id` and `short_id` of
snapshots in the `reason` field.
https://github.com/restic/restic/pull/4737
* Enhancement #4764: Support forgetting all snapshots
The `forget` command now supports the `--unsafe-allow-remove-all` option, which
removes all snapshots in the repository.
This option must always be combined with a snapshot filter (by host, path or
tag). For example, the command `forget --tag example --unsafe-allow-remove-all`
removes all snapshots with the tag "example".
https://github.com/restic/restic/pull/4764
* Enhancement #4768: Allow specifying custom User-Agent for outgoing requests
Restic now supports setting a custom `User-Agent` for outgoing HTTP requests
using the global option `--http-user-agent` or the `RESTIC_HTTP_USER_AGENT`
environment variable.
https://github.com/restic/restic/issues/4768
https://github.com/restic/restic/pull/4810
* Enhancement #4781: Add `restore` options to read include/exclude patterns from files
Restic now supports reading include and exclude patterns from files using the
`--include-file`, `--exclude-file`, `--iinclude-file` and `--iexclude-file`
options of the `restore` command.
https://github.com/restic/restic/issues/4781
https://github.com/restic/restic/pull/4811
* Enhancement #4807: Support Extended Attributes on Windows NTFS
Restic now backs up and restores Extended Attributes for files and folders on
Windows NTFS.
https://github.com/restic/restic/pull/4807
* Enhancement #4817: Make overwrite behavior of `restore` customizable
The `restore` command now supports an `--overwrite` option to configure whether
already existing files are overwritten. The overwrite behavior can be configured
using the following option values:
- `--overwrite always` (default): Always overwrites already existing files. The
`restore` command will verify the existing file content and only restore
mismatching parts to minimize downloads. Updates the metadata of all files. -
`--overwrite if-changed`: Like `always`, but speeds up the file content check by
assuming that files with matching size and modification time (mtime) are already
up to date. In case of a mismatch, the full file content is verified like with
`always`. Updates the metadata of all files. - `--overwrite if-newer`: Like
`always`, but only overwrites existing files when the file in the snapshot has a
newer modification time (mtime) than the existing file. - `--overwrite never`:
Never overwrites existing files.
https://github.com/restic/restic/issues/4817
https://github.com/restic/restic/issues/200
https://github.com/restic/restic/issues/407
https://github.com/restic/restic/issues/2662
https://github.com/restic/restic/pull/4837
https://github.com/restic/restic/pull/4838
https://github.com/restic/restic/pull/4864
https://github.com/restic/restic/pull/4921
* Enhancement #4839: Add dry-run support to `restore` command
The `restore` command now supports the `--dry-run` option to perform a dry run.
Pass the `--verbose=2` option to see which files would remain unchanged, and
which would be updated or freshly restored.
https://github.com/restic/restic/pull/4839
# Changelog for restic 0.16.5 (2024-07-01)
The following sections list the changes in restic 0.16.5 relevant to
restic users. The changes are ordered by importance.
## Summary
* Enh #4799: Add option to force use of Azure CLI credential
* Enh #4873: Update dependencies
## Details
* Enhancement #4799: Add option to force use of Azure CLI credential
A new environment variable `AZURE_FORCE_CLI_CREDENTIAL=true` allows forcing the
use of Azure CLI credential, ignoring other credentials like managed identity.
https://github.com/restic/restic/pull/4799
* Enhancement #4873: Update dependencies
A few potentially vulnerable dependencies were updated.
https://github.com/restic/restic/issues/4873
https://github.com/restic/restic/pull/4878
# Changelog for restic 0.16.4 (2024-02-04)
The following sections list the changes in restic 0.16.4 relevant to
restic users. The changes are ordered by importance.
@@ -596,7 +1330,7 @@ restic users. The changes are ordered by importance.
* Enhancement #3941: Support `--group-by` for backup parent selection
Previously, the `backup` command by default selected the parent snapshot based
on the hostname and the backup targets. When the backup path list changed, the
on the hostname and the backup paths. When the backup path list changed, the
`backup` command was unable to determine a suitable parent snapshot and had to
read all files again.
@@ -2490,7 +3224,7 @@ restic users. The changes are ordered by importance.
* Fix #3151: Don't create invalid snapshots when `backup` is interrupted
* Fix #3152: Do not hang until foregrounded when completed in background
* Fix #3166: Improve error handling in the `restore` command
* Fix #3232: Correct statistics for overlapping targets
* Fix #3232: Correct statistics for overlapping backup sources
* Fix #3249: Improve error handling in `gs` backend
* Chg #3095: Deleting files on Google Drive now moves them to the trash
* Enh #909: Back up mountpoints as empty directories
@@ -2657,10 +3391,10 @@ restic users. The changes are ordered by importance.
https://github.com/restic/restic/issues/3166
https://github.com/restic/restic/pull/3207
* Bugfix #3232: Correct statistics for overlapping targets
* Bugfix #3232: Correct statistics for overlapping backup sources
A user reported that restic's statistics and progress information during backup
was not correctly calculated when the backup targets (files/dirs to save)
was not correctly calculated when the backup sources (files/dirs to save)
overlap. For example, consider a directory `foo` which contains (among others) a
file `foo/bar`. When `restic backup foo foo/bar` was run, restic counted the
size of the file `foo/bar` twice, so the completeness percentage as well as the
@@ -2925,7 +3659,7 @@ restic users. The changes are ordered by importance.
* Enhancement #3106: Parallelize scan of snapshot content in `copy` and `prune`
The `copy` and `prune` commands used to traverse the directories of snapshots
one by one to find used data. This snapshot traversal is now parallized which
one by one to find used data. This snapshot traversal is now parallelized which
can speed up this step several times.
In addition the `check` command now reports how many snapshots have already been
@@ -3024,11 +3758,10 @@ restic users. The changes are ordered by importance.
* Bugfix #1756: Mark repository files as read-only when using the local backend
Files stored in a local repository were marked as writeable on the filesystem
for non-Windows systems, which did not prevent accidental file modifications
outside of restic. In addition, the local backend did not work with certain
filesystems and network mounts which do not permit modifications of file
permissions.
Files stored in a local repository were marked as writable on the filesystem for
non-Windows systems, which did not prevent accidental file modifications outside
of restic. In addition, the local backend did not work with certain filesystems
and network mounts which do not permit modifications of file permissions.
Restic now marks files stored in a local repository as read-only on the
filesystem on non-Windows systems. The error handling is improved to support
@@ -3122,7 +3855,7 @@ restic users. The changes are ordered by importance.
was unable to backup those files before. This update enables backing up these
files.
This needs to be enabled explicitely using the --use-fs-snapshot option of the
This needs to be enabled explicitly using the --use-fs-snapshot option of the
backup command.
https://github.com/restic/restic/issues/340
@@ -3332,8 +4065,8 @@ restic users. The changes are ordered by importance.
* Bugfix #2668: Don't abort the stats command when data blobs are missing
Runing the stats command in the blobs-per-file mode on a repository with missing
data blobs previously resulted in a crash.
Running the stats command in the blobs-per-file mode on a repository with
missing data blobs previously resulted in a crash.
https://github.com/restic/restic/pull/2668
@@ -3488,7 +4221,7 @@ restic users. The changes are ordered by importance.
NOTE: This new implementation does not guarantee order in which blobs are
written to the target files and, for example, the last blob of a file can be
written to the file before any of the preceeding file blobs. It is therefore
written to the file before any of the preceding file blobs. It is therefore
possible to have gaps in the data written to the target files if restore fails
or interrupted by the user.
@@ -3722,7 +4455,7 @@ restic users. The changes are ordered by importance.
will be disabled if the --ignore-inode flag was given.
If this change causes problems for you, please open an issue, and we can look in
to adding a seperate flag to disable just the ctime check.
to adding a separate flag to disable just the ctime check.
https://github.com/restic/restic/issues/2179
https://github.com/restic/restic/pull/2212
@@ -4096,7 +4829,7 @@ restic users. The changes are ordered by importance.
* Enhancement #1876: Display reason why forget keeps snapshots
We've added a column to the list of snapshots `forget` keeps which details the
reasons to keep a particuliar snapshot. This makes debugging policies for forget
reasons to keep a particular snapshot. This makes debugging policies for forget
much easier. Please remember to always try things out with `--dry-run`!
https://github.com/restic/restic/pull/1876
@@ -4409,7 +5142,7 @@ restic users. The changes are ordered by importance.
* Enh #1665: Improve cache handling for `restic check`
* Enh #1709: Improve messages `restic check` prints
* Enh #1721: Add `cache` command to list cache dirs
* Enh #1735: Allow keeping a time range of snaphots
* Enh #1735: Allow keeping a time range of snapshots
* Enh #1758: Allow saving OneDrive folders in Windows
* Enh #1782: Use default AWS credentials chain for S3 backend
@@ -4615,7 +5348,7 @@ restic users. The changes are ordered by importance.
https://github.com/restic/restic/issues/1721
https://github.com/restic/restic/pull/1749
* Enhancement #1735: Allow keeping a time range of snaphots
* Enhancement #1735: Allow keeping a time range of snapshots
We've added the `--keep-within` option to the `forget` command. It instructs
restic to keep all snapshots within the given duration since the newest
@@ -4717,7 +5450,7 @@ restic users. The changes are ordered by importance.
already exists.
This is not accurate, the file could have been created between the HTTP request
testing for it, and when writing starts, so we've relaxed this requeriment,
testing for it, and when writing starts, so we've relaxed this requirement,
which saves one additional HTTP request per newly added file.
https://github.com/restic/restic/pull/1623
@@ -4737,7 +5470,7 @@ restic users. The changes are ordered by importance.
## Summary
* Fix #1506: Limit bandwith at the http.RoundTripper for HTTP based backends
* Fix #1506: Limit bandwidth at the http.RoundTripper for HTTP based backends
* Fix #1512: Restore directory permissions as the last step
* Fix #1528: Correctly create missing subdirs in data/
* Fix #1589: Complete intermediate index upload
@@ -4757,7 +5490,7 @@ restic users. The changes are ordered by importance.
## Details
* Bugfix #1506: Limit bandwith at the http.RoundTripper for HTTP based backends
* Bugfix #1506: Limit bandwidth at the http.RoundTripper for HTTP based backends
https://github.com/restic/restic/issues/1506
https://github.com/restic/restic/pull/1511
@@ -4814,7 +5547,7 @@ restic users. The changes are ordered by importance.
* Bugfix #1595: Backup: Remove bandwidth display
This commit removes the bandwidth displayed during backup process. It is
misleading and seldomly correct, because it's neither the "read bandwidth" (only
misleading and seldom correct, because it's neither the "read bandwidth" (only
for the very first backup) nor the "upload bandwidth". Many users are confused
about (and rightly so), c.f. #1581, #1033, #1591
@@ -5087,7 +5820,7 @@ restic users. The changes are ordered by importance.
We've added a local cache for metadata so that restic doesn't need to load all
metadata (snapshots, indexes, ...) from the repo each time it starts. By default
the cache is active, but there's a new global option `--no-cache` that can be
used to disable the cache. By deafult, the cache a standard cache folder for the
used to disable the cache. By default, the cache a standard cache folder for the
OS, which can be overridden with `--cache-dir`. The cache will automatically
populate, indexes and snapshots are saved as they are loaded. Cache directories
for repos that haven't been used recently can automatically be removed by restic
@@ -5174,7 +5907,7 @@ restic users. The changes are ordered by importance.
* Enhancement #1319: Make `check` print `no errors found` explicitly
The `check` command now explicetly prints `No errors were found` when no errors
The `check` command now explicitly prints `No errors were found` when no errors
could be found.
https://github.com/restic/restic/issues/1303

View File

@@ -10,8 +10,7 @@ For detailed usage and installation instructions check out the [documentation](h
You can ask questions in our [Discourse forum](https://forum.restic.net).
Quick start
-----------
## Quick start
Once you've [installed](https://restic.readthedocs.io/en/latest/020_installation.html) restic, start
off with creating a repository for your backups:
@@ -59,7 +58,7 @@ Therefore, restic supports the following backends for storing backups natively:
Restic is a program that does backups right and was designed with the
following principles in mind:
- **Easy:** Doing backups should be a frictionless process, otherwise
- **Easy**: Doing backups should be a frictionless process, otherwise
you might be tempted to skip it. Restic should be easy to configure
and use, so that, in the event of a data loss, you can just restore
it. Likewise, restoring data should not be complicated.
@@ -92,20 +91,17 @@ reproduce a byte identical version from the source code for that
release. Instructions on how to do that are contained in the
[builder repository](https://github.com/restic/builder).
News
----
## News
You can follow the restic project on Mastodon [@resticbackup](https://fosstodon.org/@restic) or by subscribing to
You can follow the restic project on Mastodon [@resticbackup](https://fosstodon.org/@restic) or subscribe to
the [project blog](https://restic.net/blog/).
License
-------
## License
Restic is licensed under [BSD 2-Clause License](https://opensource.org/licenses/BSD-2-Clause). You can find the
complete text in [``LICENSE``](LICENSE).
complete text in [`LICENSE`](LICENSE).
Sponsorship
-----------
## Sponsorship
Backend integration tests for Google Cloud Storage and Microsoft Azure Blob
Storage are sponsored by [AppsCode](https://appscode.com)!

View File

@@ -1 +1 @@
0.16.4
0.17.0

View File

@@ -10,7 +10,7 @@ https://github.com/restic/restic/issues/2244
NOTE: This new implementation does not guarantee order in which blobs
are written to the target files and, for example, the last blob of a
file can be written to the file before any of the preceeding file blobs.
file can be written to the file before any of the preceding file blobs.
It is therefore possible to have gaps in the data written to the target
files if restore fails or interrupted by the user.

View File

@@ -1,7 +1,7 @@
Bugfix: Correct statistics for overlapping targets
Bugfix: Correct statistics for overlapping backup sources
A user reported that restic's statistics and progress information during backup
was not correctly calculated when the backup targets (files/dirs to save)
was not correctly calculated when the backup sources (files/dirs to save)
overlap. For example, consider a directory `foo` which contains (among others)
a file `foo/bar`. When `restic backup foo foo/bar` was run, restic counted the
size of the file `foo/bar` twice, so the completeness percentage as well as the

View File

@@ -1,7 +1,7 @@
Enhancement: Support `--group-by` for backup parent selection
Previously, the `backup` command by default selected the parent snapshot based
on the hostname and the backup targets. When the backup path list changed, the
on the hostname and the backup paths. When the backup path list changed, the
`backup` command was unable to determine a suitable parent snapshot and had to
read all files again.

View File

@@ -0,0 +1,6 @@
Enhancement: Update dependencies
A few potentially vulnerable dependencies were updated.
https://github.com/restic/restic/issues/4873
https://github.com/restic/restic/pull/4878

View File

@@ -0,0 +1,5 @@
Enhancement: Add option to force use of Azure CLI credential
A new environment variable `AZURE_FORCE_CLI_CREDENTIAL=true` allows forcing the use of Azure CLI credential, ignoring other credentials like managed identity.
https://github.com/restic/restic/pull/4799

View File

@@ -0,0 +1,20 @@
Enhancement: Support repositories with empty password
Restic previously required a password to create or operate on repositories.
Using the new option `--insecure-no-password` it is now possible to disable
this requirement. Restic will not prompt for a password when using this option.
For security reasons, the option must always be specified when operating on
repositories with an empty password, and specifying `--insecure-no-password`
while also passing a password to restic via a CLI option or environment
variable results in an error.
The `init` and `copy` commands add the related `--from-insecure-no-password`
option, which applies to the source repository. The `key add` and `key passwd`
commands add the `--new-insecure-no-password` option to add or set an empty
password.
https://github.com/restic/restic/issues/1786
https://github.com/restic/restic/issues/4326
https://github.com/restic/restic/pull/4698
https://github.com/restic/restic/pull/4808

View File

@@ -0,0 +1,12 @@
Enhancement: Add `--delete` option to `restore` command
The `restore` command now supports a `--delete` option that allows removing
files and directories from the target directory that do not exist in the
snapshot. This option also allows files in the snapshot to replace non-empty
directories having the same name.
To check that only expected files are deleted, add the `--dry-run --verbose=2`
options.
https://github.com/restic/restic/issues/2348
https://github.com/restic/restic/pull/4881

View File

@@ -0,0 +1,11 @@
Bugfix: Handle unreadable xattrs in folders above `backup` source
When backup sources are specified using absolute paths, `backup` also includes
information about the parent folders of the backup sources in the snapshot.
If the extended attributes for some of these folders could not be read due to
missing permissions, this caused the backup to fail. This has now been fixed.
https://github.com/restic/restic/issues/3600
https://github.com/restic/restic/pull/4668
https://forum.restic.net/t/parent-directories-above-the-snapshot-source-path-fatal-error-permission-denied/7216

View File

@@ -0,0 +1,12 @@
Enhancement: Optimize and make `prune` command resumable
Previously, if the `prune` command was interrupted, a later `prune` run would
start repacking pack files from the start, as `prune` did not update the index
while repacking.
The `prune` command now supports resuming interrupted prune runs. The update
of the repository index has also been optimized to use less memory and only
rewrite parts of the index that have changed.
https://github.com/restic/restic/issues/3806
https://github.com/restic/restic/pull/4812

View File

@@ -0,0 +1,6 @@
Enhancement: Add support for FUSE-T with `mount` on macOS
The restic `mount` command now supports creating FUSE mounts using FUSE-T on macOS.
https://github.com/restic/restic/issues/4048
https://github.com/restic/restic/pull/4825

View File

@@ -0,0 +1,7 @@
Bugfix: Fix slow SFTP upload performance
Since restic 0.12.1, the upload speed of the sftp backend to a remote server
has regressed significantly. This has now been fixed.
https://github.com/restic/restic/issues/4209
https://github.com/restic/restic/pull/4782

View File

@@ -1,4 +1,4 @@
Enhancement: Support reading backup from a commands's standard output
Enhancement: Support reading backup from a command's standard output
The `backup` command now supports the `--stdin-from-command` option. When using
this option, the arguments to `backup` are interpreted as a command instead of

View File

@@ -0,0 +1,12 @@
Enhancement: Support connection to rest-server using unix socket
Restic now supports using a unix socket to connect to a rest-server
version 0.13.0 or later. This allows running restic as follows:
```
rest-server --listen unix:/tmp/rest.socket --data /path/to/data &
restic -r rest:http+unix:///tmp/rest.socket:/my_backup_repo/ [...]
```
https://github.com/restic/restic/issues/4287
https://github.com/restic/restic/pull/4655

View File

@@ -0,0 +1,11 @@
Enhancement: Make `check` command create non-existent cache directory
Previously, if a custom cache directory was specified for the `check` command,
but the directory did not exist, `check` continued with the cache disabled.
The `check` command now attempts to create the cache directory before
initializing the cache.
https://github.com/restic/restic/issues/4437
https://github.com/restic/restic/pull/4805
https://github.com/restic/restic/pull/4883

View File

@@ -1,11 +1,11 @@
Enhancement: Allow AWS Assume Role to be used for S3 backend
Enhancement: Support AWS Assume Role for S3 backend
Previously only credentials discovered via the Minio discovery methods
were used to authenticate.
However, there are many circumstances where the discovered credentials have
lower permissions and need to assume a specific role. This is now possible
using the following new environment variables.
using the following new environment variables:
- RESTIC_AWS_ASSUME_ROLE_ARN
- RESTIC_AWS_ASSUME_ROLE_SESSION_NAME

View File

@@ -1,6 +1,7 @@
Change: Require at least ARMv6 for ARM binaries
The official release binaries of restic now require at least ARMv6 support for ARM platforms.
The official release binaries of restic now require
at least ARMv6 support for ARM platforms.
https://github.com/restic/restic/issues/4540
https://github.com/restic/restic/pull/4542

View File

@@ -0,0 +1,7 @@
Enhancement: Add `--json` option to `version` command
Restic now supports outputting restic version along with the Go version, OS
and architecture used to build restic in JSON format using `version --json`.
https://github.com/restic/restic/issues/4547
https://github.com/restic/restic/pull/4553

View File

@@ -0,0 +1,11 @@
Enhancement: Add `--ncdu` option to `ls` command
NCDU (NCurses Disk Usage) is a tool to analyse disk usage of directories. It has
an option to save a directory tree and analyse it later.
The `ls` command now supports outputting snapshot information in the NCDU format
using the `--ncdu` option. Example usage: `restic ls latest --ncdu | ncdu -f -`
https://github.com/restic/restic/issues/4549
https://github.com/restic/restic/pull/4550
https://github.com/restic/restic/pull/4911

View File

@@ -0,0 +1,16 @@
Bugfix: Prevent `forget --keep-tags <invalid>` from deleting all snapshots
Running `forget --keep-tags <invalid>`, where `<invalid>` is a tag that does
not exist in the repository, would remove all snapshots. This is especially
problematic if the tag name contains a typo.
The `forget` command now fails with an error if all snapshots in a snapshot
group would be deleted. This prevents the above example from deleting all
snapshots.
It is possible to temporarily disable the new check by setting the environment
variable `RESTIC_FEATURES=safe-forget-keep-tags=false`. Note that this feature
flag will be removed in the next minor restic version.
https://github.com/restic/restic/pull/4568
https://github.com/restic/restic/pull/4764

View File

@@ -0,0 +1,13 @@
Enhancement: Ignore `s3.storage-class` archive tiers for metadata
Restic used to store all files on S3 using the specified `s3.storage-class`.
Now, restic will only use non-archive storage tiers for metadata, to avoid
problems when accessing a repository. To restore any data, it is still
necessary to manually warm up the required data beforehand.
NOTE: There is no official cold storage support in restic, use this option at
your own risk.
https://github.com/restic/restic/issues/4583
https://github.com/restic/restic/pull/4584

View File

@@ -0,0 +1,9 @@
Enhancement: Add support for feature flags
Restic now supports feature flags that can be used to enable and disable
experimental features. The flags can be set using the environment variable
`RESTIC_FEATURES`. To get a list of currently supported feature flags, use
the `features` command.
https://github.com/restic/restic/issues/4601
https://github.com/restic/restic/pull/4666

View File

@@ -0,0 +1,22 @@
Change: Deprecate legacy index format and `s3legacy` repository layout
Support for the legacy index format used by restic before version 0.2.0 has
been deprecated and will be removed in the next minor restic version. You can
use `restic repair index` to update the index to the current format.
It is possible to temporarily reenable support for the legacy index format by
setting the environment variable `RESTIC_FEATURES=deprecate-legacy-index=false`.
Note that this feature flag will be removed in the next minor restic version.
Support for the `s3legacy` repository layout used for the S3 backend before
restic 0.7.0 has been deprecated and will be removed in the next minor restic
version. You can migrate your S3 repository to the current layout using
`RESTIC_FEATURES=deprecate-s3-legacy-layout=false restic migrate s3_layout`.
It is possible to temporarily reenable support for the `s3legacy` layout by
setting the environment variable `RESTIC_FEATURES=deprecate-s3-legacy-layout=false`.
Note that this feature flag will be removed in the next minor restic version.
https://github.com/restic/restic/issues/4602
https://github.com/restic/restic/pull/4724
https://github.com/restic/restic/pull/4743

View File

@@ -0,0 +1,33 @@
Change: Redesign backend error handling to improve reliability
Restic now downloads pack files in large chunks instead of using a streaming
download. This prevents failures due to interrupted streams. The `restore`
command now also retries downloading individual blobs that could not be
retrieved.
HTTP requests that are stuck for more than two minutes while uploading or
downloading are now forcibly interrupted. This ensures that stuck requests are
retried after a short timeout.
Attempts to access a missing or truncated file will no longer be retried. This
avoids unnecessary retries in those cases. All other backend requests are
retried for up to 15 minutes. This ensures that temporarily interrupted network
connections can be tolerated.
If a download yields a corrupt file or blob, then the download will be retried
once.
Most parts of the new backend error handling can temporarily be disabled by
setting the environment variable `RESTIC_FEATURES=backend-error-redesign=false`.
Note that this feature flag will be removed in the next minor restic version.
https://github.com/restic/restic/issues/4627
https://github.com/restic/restic/issues/4193
https://github.com/restic/restic/pull/4605
https://github.com/restic/restic/pull/4792
https://github.com/restic/restic/issues/4515
https://github.com/restic/restic/issues/1523
https://github.com/restic/restic/pull/4520
https://github.com/restic/restic/pull/4800
https://github.com/restic/restic/pull/4784
https://github.com/restic/restic/pull/4844

View File

@@ -1,6 +1,6 @@
Bugfix: Properly report the ID of newly added keys
Bugfix: Properly report ID of newly added keys
`restic key add` now reports the ID of a newly added key. This simplifies
`restic key add` now reports the ID of the newly added key. This simplifies
selecting a specific key using the `--key-hint key` option.
https://github.com/restic/restic/issues/4656

View File

@@ -0,0 +1,8 @@
Enhancement: Make `key` command's actions separate sub-commands
Each of the `add`, `list`, `remove` and `passwd` actions provided by the `key`
command is now a separate sub-command and have its own documentation which can
be invoked using `restic key <add|list|remove|passwd> --help`.
https://github.com/restic/restic/issues/4676
https://github.com/restic/restic/pull/4685

View File

@@ -0,0 +1,8 @@
Enhancement: Add `--target` option to the `dump` command
Restic `dump` always printed to the standard output. It now supports specifying
a `--target` file to write its output to.
https://github.com/restic/restic/issues/4678
https://github.com/restic/restic/pull/4682
https://github.com/restic/restic/pull/4692

View File

@@ -0,0 +1,14 @@
Change: Disable S3 anonymous authentication by default
When using the S3 backend with anonymous authentication, it continuously
tried to retrieve new authentication credentials, causing bad performance.
Now, to use anonymous authentication, it is necessary to pass the extended
option `-o s3.unsafe-anonymous-auth=true` to restic.
It is possible to temporarily revert to the old behavior by setting the
environment variable `RESTIC_FEATURES=explicit-s3-anonymous-auth=false`. Note
that this feature flag will be removed in the next minor restic version.
https://github.com/restic/restic/issues/4707
https://github.com/restic/restic/pull/4908

View File

@@ -0,0 +1,12 @@
Enhancement: Allow specifying `--host` via environment variable
Restic commands that operate on snapshots, such as `restic backup` and
`restic snapshots`, support the `--host` option to specify the hostname
for grouping snapshots.
Such commands now also support specifying the hostname via the environment
variable `RESTIC_HOST`. Note that `--host` still takes precedence over the
environment variable.
https://github.com/restic/restic/issues/4733
https://github.com/restic/restic/pull/4734

View File

@@ -0,0 +1,9 @@
Change: Include full key ID in JSON output of `key list`
The JSON output of the `key list` command has changed to include the full key
ID instead of just a shortened version of the ID, as the latter can be ambiguous
in some rare cases. To derive the short ID, please truncate the full ID down to
eight characters.
https://github.com/restic/restic/issues/4744
https://github.com/restic/restic/pull/4745

View File

@@ -0,0 +1,8 @@
Bugfix: Fix possible error on concurrent cache cleanup
If multiple restic processes concurrently cleaned up no longer existing files
from the cache, this could cause some of the processes to fail with an `no such
file or directory` error. This has now been fixed.
https://github.com/restic/restic/issues/4760
https://github.com/restic/restic/pull/4761

View File

@@ -0,0 +1,8 @@
Enhancement: Allow specifying custom User-Agent for outgoing requests
Restic now supports setting a custom `User-Agent` for outgoing HTTP requests
using the global option `--http-user-agent` or the `RESTIC_HTTP_USER_AGENT`
environment variable.
https://github.com/restic/restic/issues/4768
https://github.com/restic/restic/pull/4810

View File

@@ -0,0 +1,8 @@
Enhancement: Add `restore` options to read include/exclude patterns from files
Restic now supports reading include and exclude patterns from files using the
`--include-file`, `--exclude-file`, `--iinclude-file` and `--iexclude-file`
options of the `restore` command.
https://github.com/restic/restic/issues/4781
https://github.com/restic/restic/pull/4811

View File

@@ -0,0 +1,26 @@
Enhancement: Make overwrite behavior of `restore` customizable
The `restore` command now supports an `--overwrite` option to configure whether
already existing files are overwritten. The overwrite behavior can be configured
using the following option values:
- `--overwrite always` (default): Always overwrites already existing files.
The `restore` command will verify the existing file content and only restore
mismatching parts to minimize downloads. Updates the metadata of all files.
- `--overwrite if-changed`: Like `always`, but speeds up the file content check
by assuming that files with matching size and modification time (mtime) are
already up to date. In case of a mismatch, the full file content is verified
like with `always`. Updates the metadata of all files.
- `--overwrite if-newer`: Like `always`, but only overwrites existing files
when the file in the snapshot has a newer modification time (mtime) than the
existing file.
- `--overwrite never`: Never overwrites existing files.
https://github.com/restic/restic/issues/4817
https://github.com/restic/restic/issues/200
https://github.com/restic/restic/issues/407
https://github.com/restic/restic/issues/2662
https://github.com/restic/restic/pull/4837
https://github.com/restic/restic/pull/4838
https://github.com/restic/restic/pull/4864
https://github.com/restic/restic/pull/4921

View File

@@ -0,0 +1,8 @@
Bugfix: Handle UTF-16 password files in `key` command correctly
Previously, `key add` and `key passwd` did not properly decode UTF-16
encoded passwords read from a password file. This has now been fixed
to correctly match the encoding when opening a repository.
https://github.com/restic/restic/issues/4850
https://github.com/restic/restic/pull/4851

View File

@@ -0,0 +1,8 @@
Bugfix: Update snapshot summary on `rewrite`
Restic previously did not recalculate the total number of files and bytes
processed when files were excluded from a snapshot by the `rewrite` command.
This has now been fixed.
https://github.com/restic/restic/issues/4902
https://github.com/restic/restic/pull/4905

View File

@@ -0,0 +1,11 @@
Enhancement: Optionally skip snapshot creation if nothing changed
The `backup` command always created a snapshot even if nothing in the
backup set changed compared to the parent snapshot.
Restic now supports the `--skip-if-unchanged` option for the `backup`
command, which omits creating a snapshot if the new snapshot's content
would be identical to that of the parent snapshot.
https://github.com/restic/restic/issues/662
https://github.com/restic/restic/pull/4816

View File

@@ -0,0 +1,13 @@
Enhancement: Include snapshot size in `snapshots` output
The `snapshots` command now prints the size for snapshots created using this
or a future restic version. To achieve this, the `backup` command now stores
the backup summary statistics in the snapshot.
The text output of the `snapshots` command only shows the snapshot size. The
other statistics are only included in the JSON output. To inspect these
statistics use `restic snapshots --json` or `restic cat snapshot <snapshotID>`.
https://github.com/restic/restic/issues/693
https://github.com/restic/restic/pull/4705
https://github.com/restic/restic/pull/4913

View File

@@ -0,0 +1,11 @@
Enhancement: Improve features of the `repair packs` command
The `repair packs` command has been improved to also be able to process
truncated pack files. The `check` and `check --read-data` command will provide
instructions on using the command if necessary to repair a repository. See the
guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html for
further instructions.
https://github.com/restic/restic/issues/828
https://github.com/restic/restic/pull/4644
https://github.com/restic/restic/pull/4882

View File

@@ -0,0 +1,25 @@
Enhancement: Add extended options to configure Windows Shadow Copy Service
Previous, restic always used a 120 seconds timeout and unconditionally created
VSS snapshots for all volume mount points on disk. This behavior can now be
fine-tuned by the following new extended options (available only on Windows):
- `-o vss.timeout`: Time that VSS can spend creating snapshot before timing out (default: 120s)
- `-o vss.exclude-all-mount-points`: Exclude mountpoints from snapshotting on all volumes (default: false)
- `-o vss.exclude-volumes`: Semicolon separated list of volumes to exclude from snapshotting
- `-o vss.provider`: VSS provider identifier which will be used for snapshotting
For example, change VSS timeout to five minutes and disable snapshotting of
mount points on all volumes:
restic backup --use-fs-snapshot -o vss.timeout=5m -o vss.exclude-all-mount-points=true
Exclude drive `d:`, mount point `c:\mnt` and a specific volume from snapshotting:
restic backup --use-fs-snapshot -o vss.exclude-volumes="d:\;c:\mnt\;\\?\Volume{e2e0315d-9066-4f97-8343-eb5659b35762}"
Uses 'Microsoft Software Shadow Copy provider 1.0' instead of the default provider:
restic backup --use-fs-snapshot -o vss.provider={b5946137-7b9f-4925-af80-51abd60b20d5}
https://github.com/restic/restic/pull/3067

View File

@@ -0,0 +1,15 @@
Enhancement: (alpha) Store deviceID only for hardlinks
Set `RESTIC_FEATURES=device-id-for-hardlinks` to enable this alpha feature.
The feature flag will be removed after repository format version 3 becomes
available or be replaced with a different solution.
When creating backups from a filesystem snapshot, for example created using
BTRFS subvolumes, the deviceID of the filesystem changes compared to previous
snapshots. This prevented restic from deduplicating the directory metadata of
a snapshot.
When this alpha feature is enabled, the deviceID is only stored for hardlinks,
which significantly reduces the metadata duplication for most backups.
https://github.com/restic/restic/pull/4006

View File

@@ -0,0 +1,7 @@
Enhancement: Significantly reduce `prune` memory usage
The `prune` command has been optimized to use up to 60% less memory.
The memory usage should now be roughly similar to creating a backup.
https://github.com/restic/restic/pull/4354
https://github.com/restic/restic/pull/4812

View File

@@ -0,0 +1,8 @@
Bugfix: Correct hardlink handling in `stats` command
If files on different devices had the same inode ID, the `stats` command
did not correctly calculate the snapshot size. This has now been fixed.
https://forum.restic.net/t/possible-bug-in-stats/6461/8
https://github.com/restic/restic/pull/4503
https://github.com/restic/restic/pull/4006

View File

@@ -0,0 +1,12 @@
Enhancement: Add bitrot detection to `diff` command
The output of the `diff` command now includes the modifier `?` for files to
indicate bitrot in backed up files. The `?` will appear whenever there is a
difference in content while the metadata is exactly the same.
Since files with unchanged metadata are normally not read again when creating
a backup, the detection is only effective when the right-hand side of the diff
has been created with `backup --force`.
https://github.com/restic/restic/issues/805
https://github.com/restic/restic/pull/4526

View File

@@ -0,0 +1,6 @@
Enhancement: Support rewriting host and time metadata in snapshots
The `rewrite` command now supports rewriting the host and/or time metadata of
a snapshot using the new `--new-host` and `--new-time` options.
https://github.com/restic/restic/pull/4573

View File

@@ -0,0 +1,6 @@
Enhancement: Speed up `mount` command's error detection
The `mount` command now checks for the existence of the mountpoint before
opening the repository, leading to quicker error detection.
https://github.com/restic/restic/pull/4590

View File

@@ -0,0 +1,9 @@
Enhancement: Back up more file metadata on Windows
Previously, restic did not back up all common Windows-specific metadata.
Restic now stores file creation time and file attributes like the hidden,
read-only and encrypted flags when backing up files and folders on Windows.
https://github.com/restic/restic/pull/4611

View File

@@ -1,6 +1,6 @@
Bugfix: `find` ignored directories in some cases
Bugfix: Make `find` not sometimes ignore directories
In some cases, the `find` command ignored empty or moved directories. This has
been fixed.
now been fixed.
https://github.com/restic/restic/pull/4615

View File

@@ -0,0 +1,10 @@
Enhancement: Make `ls` use `message_type` field in JSON output
The `ls` command was the only restic command that used the `struct_type` field
in its JSON output format to specify the message type.
The JSON output of the `ls` command now also includes the `message_type` field,
which is consistent with other commands. The `struct_type` field is still
included, but now deprecated.
https://github.com/restic/restic/pull/4664

View File

@@ -0,0 +1,11 @@
Bugfix: Shutdown cleanly when receiving SIGTERM
Previously, when restic received the SIGTERM signal it would terminate
immediately, skipping cleanup and potentially causing issues like stale locks
being left behind. This primarily effected containerized restic invocations
that use SIGTERM, but could also be triggered via a simple `killall restic`.
This has now been fixed, such that restic shuts down cleanly when receiving
the SIGTERM signal.
https://github.com/restic/restic/pull/4703

View File

@@ -0,0 +1,13 @@
Enhancement: Back up and restore SecurityDescriptors on Windows
Restic now backs up and restores SecurityDescriptors for files and folders on
Windows which includes owner, group, discretionary access control list (DACL)
and system access control list (SACL).
This requires the user to be a member of backup operators or the application
must be run as admin. If that is not the case, only the current user's owner,
group and DACL will be backed up, and during restore only the DACL of the
backed up file will be restored, with the current user's owner and group
being set on the restored file.
https://github.com/restic/restic/pull/4708

View File

@@ -0,0 +1,10 @@
Bugfix: Correct `--no-lock` handling of `ls` and `tag` commands
The `ls` command never locked the repository. This has now been fixed, with the
old behavior still being supported using `ls --no-lock`. The latter invocation
also works with older restic versions.
The `tag` command erroneously accepted the `--no-lock` command. This command
now always requires an exclusive lock.
https://github.com/restic/restic/pull/4709

View File

@@ -0,0 +1,6 @@
Enhancement: Include snapshot ID in `reason` field of `forget` JSON output
The JSON output of the `forget` command now includes `id` and `short_id` of
snapshots in the `reason` field.
https://github.com/restic/restic/pull/4737

View File

@@ -0,0 +1,10 @@
Enhancement: Support forgetting all snapshots
The `forget` command now supports the `--unsafe-allow-remove-all` option, which
removes all snapshots in the repository.
This option must always be combined with a snapshot filter (by host, path or
tag). For example, the command `forget --tag example --unsafe-allow-remove-all`
removes all snapshots with the tag "example".
https://github.com/restic/restic/pull/4764

View File

@@ -0,0 +1,8 @@
Enhancement: Improve `dump` performance for large files
The `dump` command now retrieves the data chunks for a file in
parallel. This improves the download performance by up to as many
times as the configured number of parallel backend connections.
https://github.com/restic/restic/issues/3406
https://github.com/restic/restic/pull/4796

View File

@@ -0,0 +1,6 @@
Enhancement: Support Extended Attributes on Windows NTFS
Restic now backs up and restores Extended Attributes for files
and folders on Windows NTFS.
https://github.com/restic/restic/pull/4807

View File

@@ -0,0 +1,7 @@
Enhancement: Add dry-run support to `restore` command
The `restore` command now supports the `--dry-run` option to perform
a dry run. Pass the `--verbose=2` option to see which files would
remain unchanged, and which would be updated or freshly restored.
https://github.com/restic/restic/pull/4839

View File

@@ -0,0 +1,11 @@
Change: Return exit code 10 and 11 for non-existing and locked repository
If a repository does not exist or cannot be locked, restic previously always
returned exit code 1. This made it difficult to distinguish these cases from
other errors.
Restic now returns exit code 10 if the repository does not exist, and exit code
11 if the repository could be not locked due to a conflicting lock.
https://github.com/restic/restic/issues/956
https://github.com/restic/restic/pull/4884

View File

@@ -1,8 +0,0 @@
Change: Don't retry to load files that don't exist
Restic used to always retry to load files. It now only retries to load
files if they exist.
https://github.com/restic/restic/issues/4515
https://github.com/restic/restic/issues/1523
https://github.com/restic/restic/pull/4520

View File

@@ -1,7 +0,0 @@
Enhancement: Add support for `--json` option to `version` command
Restic now supports outputting restic version and used go version, OS and
architecture via JSON when using the version command.
https://github.com/restic/restic/issues/4547
https://github.com/restic/restic/pull/4553

View File

@@ -1,11 +0,0 @@
Enhancement: Add `--ncdu` option to `ls` command
NCDU (NCurses Disk Usage) is a tool to analyse disk usage of directories.
It has an option to save a directory tree and analyse it later.
The `ls` command now supports the `--ncdu` option which outputs information
about a snapshot in the NCDU format.
You can use it as follows: `restic ls latest --ncdu | ncdu -f -`
https://github.com/restic/restic/issues/4549
https://github.com/restic/restic/pull/4550

View File

@@ -1,12 +0,0 @@
Enhancement: Ignore s3.storage-class for metadata if archive tier is specified
There is no official cold storage support in restic, use this option at your
own risk.
Restic always stored all files on s3 using the specified `s3.storage-class`.
Now, restic will store metadata using a non-archive storage tier to avoid
problems when accessing a repository. To restore any data, it is still
necessary to manually warm up the required data beforehand.
https://github.com/restic/restic/issues/4583
https://github.com/restic/restic/pull/4584

View File

@@ -1,8 +0,0 @@
Enhancement: Move key add, list, remove and passwd as separate sub-commands
Restic now provides usage documentation for the `key` command. Each sub-command;
`add`, `list`, `remove` and `passwd` now have their own sub-command documentation
which can be invoked using `restic key <add|list|remove|passwd> --help`.
https://github.com/restic/restic/issues/4676
https://github.com/restic/restic/pull/4685

View File

@@ -1,8 +0,0 @@
Enhancement: Add --target flag to the dump command
Restic `dump` always printed to the standard output. It now permits to select a
`--target` file to write the output to.
https://github.com/restic/restic/issues/4678
https://github.com/restic/restic/pull/4682
https://github.com/restic/restic/pull/4692

View File

@@ -1,7 +0,0 @@
Bugfix: Correct hardlink handling in `stats` command
If files on different devices had the same inode id, then the `stats` command
did not correctly calculate the snapshot size. This has been fixed.
https://github.com/restic/restic/pull/4503
https://forum.restic.net/t/possible-bug-in-stats/6461/8

View File

@@ -1,11 +0,0 @@
Enhancement: Add bitrot detection to `diff` command
The output of the `diff` command now includes the modifier `?` for files
to indicate bitrot in backed up files. It will appear whenever there is a
difference in content while the metadata is exactly the same. Since files with
unchanged metadata are normally not read again when creating a backup, the
detection is only effective if the right-hand side of the diff has been created
with "backup --force".
https://github.com/restic/restic/issues/805
https://github.com/restic/restic/pull/4526

View File

@@ -1,5 +0,0 @@
Enhancement: Add `--new-host` and `--new-time` options to `rewrite` command
`restic rewrite` now allows rewriting the host and / or time metadata of a snapshot.
https://github.com/restic/restic/pull/4573

View File

@@ -1,7 +0,0 @@
Enhancement: `mount` tests mountpoint existence before opening the repository
The restic `mount` command now checks for the existence of the
mountpoint before opening the repository, leading to quicker error
detection.
https://github.com/restic/restic/pull/4590

View File

@@ -1,10 +0,0 @@
Enhancement: Improve `repair packs` command
The `repair packs` command has been improved to also be able to process
truncated pack files. The `check --read-data` command will provide instructions
on using the command if necessary to repair a repository. See the guide at
https://restic.readthedocs.io/en/stable/077_troubleshooting.html for further
instructions.
https://github.com/restic/restic/pull/4644
https://github.com/restic/restic/pull/4655

View File

@@ -1,89 +1,41 @@
package main
import (
"context"
"os"
"os/signal"
"sync"
"syscall"
"github.com/restic/restic/internal/debug"
)
var cleanupHandlers struct {
sync.Mutex
list []func(code int) (int, error)
done bool
ch chan os.Signal
func createGlobalContext() context.Context {
ctx, cancel := context.WithCancel(context.Background())
ch := make(chan os.Signal, 1)
go cleanupHandler(ch, cancel)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
return ctx
}
func init() {
cleanupHandlers.ch = make(chan os.Signal, 1)
go CleanupHandler(cleanupHandlers.ch)
signal.Notify(cleanupHandlers.ch, syscall.SIGINT)
}
// cleanupHandler handles the SIGINT and SIGTERM signals.
func cleanupHandler(c <-chan os.Signal, cancel context.CancelFunc) {
s := <-c
debug.Log("signal %v received, cleaning up", s)
Warnf("%ssignal %v received, cleaning up\n", clearLine(0), s)
// AddCleanupHandler adds the function f to the list of cleanup handlers so
// that it is executed when all the cleanup handlers are run, e.g. when SIGINT
// is received.
func AddCleanupHandler(f func(code int) (int, error)) {
cleanupHandlers.Lock()
defer cleanupHandlers.Unlock()
// reset the done flag for integration tests
cleanupHandlers.done = false
cleanupHandlers.list = append(cleanupHandlers.list, f)
}
// RunCleanupHandlers runs all registered cleanup handlers
func RunCleanupHandlers(code int) int {
cleanupHandlers.Lock()
defer cleanupHandlers.Unlock()
if cleanupHandlers.done {
return code
if val, _ := os.LookupEnv("RESTIC_DEBUG_STACKTRACE_SIGINT"); val != "" {
_, _ = os.Stderr.WriteString("\n--- STACKTRACE START ---\n\n")
_, _ = os.Stderr.WriteString(debug.DumpStacktrace())
_, _ = os.Stderr.WriteString("\n--- STACKTRACE END ---\n")
}
cleanupHandlers.done = true
for _, f := range cleanupHandlers.list {
var err error
code, err = f(code)
if err != nil {
Warnf("error in cleanup handler: %v\n", err)
}
}
cleanupHandlers.list = nil
return code
cancel()
}
// CleanupHandler handles the SIGINT signals.
func CleanupHandler(c <-chan os.Signal) {
for s := range c {
debug.Log("signal %v received, cleaning up", s)
Warnf("%ssignal %v received, cleaning up\n", clearLine(0), s)
if val, _ := os.LookupEnv("RESTIC_DEBUG_STACKTRACE_SIGINT"); val != "" {
_, _ = os.Stderr.WriteString("\n--- STACKTRACE START ---\n\n")
_, _ = os.Stderr.WriteString(debug.DumpStacktrace())
_, _ = os.Stderr.WriteString("\n--- STACKTRACE END ---\n")
}
code := 0
if s == syscall.SIGINT {
code = 130
} else {
code = 1
}
Exit(code)
}
}
// Exit runs the cleanup handlers and then terminates the process with the
// given exit code.
// Exit terminates the process with the given exit code.
func Exit(code int) {
code = RunCleanupHandlers(code)
debug.Log("exiting with status code %d", code)
os.Exit(code)
}

View File

@@ -41,6 +41,8 @@ EXIT STATUS
Exit status is 0 if the command was successful.
Exit status is 1 if there was a fatal error (no snapshot created).
Exit status is 3 if some source data could not be read (incomplete snapshot created).
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
PreRun: func(_ *cobra.Command, _ []string) {
if backupOptions.Host == "" {
@@ -87,6 +89,7 @@ type BackupOptions struct {
DryRun bool
ReadConcurrency uint
NoScan bool
SkipIfUnchanged bool
}
var backupOptions BackupOptions
@@ -101,7 +104,7 @@ func init() {
f.StringVar(&backupOptions.Parent, "parent", "", "use this parent `snapshot` (default: latest snapshot in the group determined by --group-by and not newer than the timestamp determined by --time)")
backupOptions.GroupBy = restic.SnapshotGroupByOptions{Host: true, Path: true}
f.VarP(&backupOptions.GroupBy, "group-by", "g", "`group` snapshots by host, paths and/or tags, separated by comma (disable grouping with '')")
f.BoolVarP(&backupOptions.Force, "force", "f", false, `force re-reading the target files/directories (overrides the "parent" flag)`)
f.BoolVarP(&backupOptions.Force, "force", "f", false, `force re-reading the source files/directories (overrides the "parent" flag)`)
initExcludePatternOptions(f, &backupOptions.excludePatternOptions)
@@ -114,7 +117,7 @@ func init() {
f.BoolVar(&backupOptions.StdinCommand, "stdin-from-command", false, "interpret arguments as command to execute and store its stdout")
f.Var(&backupOptions.Tags, "tag", "add `tags` for the new snapshot in the format `tag[,tag,...]` (can be specified multiple times)")
f.UintVar(&backupOptions.ReadConcurrency, "read-concurrency", 0, "read `n` files concurrently (default: $RESTIC_READ_CONCURRENCY or 2)")
f.StringVarP(&backupOptions.Host, "host", "H", "", "set the `hostname` for the snapshot manually. To prevent an expensive rescan use the \"parent\" flag")
f.StringVarP(&backupOptions.Host, "host", "H", "", "set the `hostname` for the snapshot manually (default: $RESTIC_HOST). To prevent an expensive rescan use the \"parent\" flag")
f.StringVar(&backupOptions.Host, "hostname", "", "set the `hostname` for the snapshot manually")
err := f.MarkDeprecated("hostname", "use --host")
if err != nil {
@@ -133,10 +136,16 @@ func init() {
if runtime.GOOS == "windows" {
f.BoolVar(&backupOptions.UseFsSnapshot, "use-fs-snapshot", false, "use filesystem snapshot where possible (currently only Windows VSS)")
}
f.BoolVar(&backupOptions.SkipIfUnchanged, "skip-if-unchanged", false, "skip snapshot creation if identical to parent snapshot")
// parse read concurrency from env, on error the default value will be used
readConcurrency, _ := strconv.ParseUint(os.Getenv("RESTIC_READ_CONCURRENCY"), 10, 32)
backupOptions.ReadConcurrency = uint(readConcurrency)
// parse host from env, if not exists or empty the default value will be used
if host := os.Getenv("RESTIC_HOST"); host != "" {
backupOptions.Host = host
}
}
// filterExisting returns a slice of all existing items, or an error if no
@@ -153,7 +162,7 @@ func filterExisting(items []string) (result []string, err error) {
}
if len(result) == 0 {
return nil, errors.Fatal("all target directories/files do not exist")
return nil, errors.Fatal("all source directories/files do not exist")
}
return
@@ -252,7 +261,7 @@ func readFilenamesRaw(r io.Reader) (names []string, err error) {
// Check returns an error when an invalid combination of options was set.
func (opts BackupOptions) Check(gopts GlobalOptions, args []string) error {
if gopts.password == "" {
if gopts.password == "" && !gopts.InsecureNoPassword {
if opts.Stdin {
return errors.Fatal("cannot read both password and data from stdin")
}
@@ -398,7 +407,7 @@ func collectTargets(opts BackupOptions, args []string) (targets []string, err er
// and have the ability to use both files-from and args at the same time.
targets = append(targets, args...)
if len(targets) == 0 && !opts.Stdin {
return nil, errors.Fatal("nothing to backup, please specify target files/dirs")
return nil, errors.Fatal("nothing to backup, please specify source files/dirs")
}
targets, err = filterExisting(targets)
@@ -440,7 +449,16 @@ func findParentSnapshot(ctx context.Context, repo restic.ListerLoaderUnpacked, o
}
func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, term *termstatus.Terminal, args []string) error {
err := opts.Check(gopts, args)
var vsscfg fs.VSSConfig
var err error
if runtime.GOOS == "windows" {
if vsscfg, err = fs.ParseVSSConfig(gopts.extended); err != nil {
return err
}
}
err = opts.Check(gopts, args)
if err != nil {
return err
}
@@ -451,6 +469,7 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
}
timeStamp := time.Now()
backupStart := timeStamp
if opts.TimeStamp != "" {
timeStamp, err = time.ParseInLocation(TimeFormat, opts.TimeStamp, time.Local)
if err != nil {
@@ -462,10 +481,11 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
Verbosef("open repository\n")
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithAppendLock(ctx, gopts, opts.DryRun)
if err != nil {
return err
}
defer unlock()
var progressPrinter backup.ProgressPrinter
if gopts.JSON {
@@ -477,22 +497,6 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
calculateProgressInterval(!gopts.Quiet, gopts.JSON))
defer progressReporter.Done()
if opts.DryRun {
repo.SetDryRun()
}
if !gopts.JSON {
progressPrinter.V("lock repository")
}
if !opts.DryRun {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
// rejectByNameFuncs collect functions that can reject items from the backup based on path only
rejectByNameFuncs, err := collectRejectByNameFuncs(opts, repo)
if err != nil {
@@ -556,8 +560,8 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
return err
}
errorHandler := func(item string, err error) error {
return progressReporter.Error(item, err)
errorHandler := func(item string, err error) {
_ = progressReporter.Error(item, err)
}
messageHandler := func(msg string, args ...interface{}) {
@@ -566,7 +570,7 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
}
}
localVss := fs.NewLocalVss(errorHandler, messageHandler)
localVss := fs.NewLocalVss(errorHandler, messageHandler, vsscfg)
defer localVss.DeleteSnapshots()
targetFS = localVss
}
@@ -638,18 +642,20 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
}
snapshotOpts := archiver.SnapshotOptions{
Excludes: opts.Excludes,
Tags: opts.Tags.Flatten(),
Time: timeStamp,
Hostname: opts.Host,
ParentSnapshot: parentSnapshot,
ProgramVersion: "restic " + version,
Excludes: opts.Excludes,
Tags: opts.Tags.Flatten(),
BackupStart: backupStart,
Time: timeStamp,
Hostname: opts.Host,
ParentSnapshot: parentSnapshot,
ProgramVersion: "restic " + version,
SkipIfUnchanged: opts.SkipIfUnchanged,
}
if !gopts.JSON {
progressPrinter.V("start backup on %v", targets)
}
_, id, err := arch.Snapshot(ctx, targets, snapshotOpts)
_, id, summary, err := arch.Snapshot(ctx, targets, snapshotOpts)
// cleanly shutdown all running goroutines
cancel()
@@ -663,10 +669,7 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
}
// Report finished execution
progressReporter.Finish(id, opts.DryRun)
if !gopts.JSON && !opts.DryRun {
progressPrinter.P("snapshot %s saved\n", id.Str())
}
progressReporter.Finish(id, summary, opts.DryRun)
if !success {
return ErrInvalidSourceData
}

View File

@@ -9,7 +9,6 @@ import (
"runtime"
"testing"
"github.com/restic/restic/internal/backend"
"github.com/restic/restic/internal/fs"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
@@ -250,29 +249,18 @@ func TestBackupTreeLoadError(t *testing.T) {
opts := BackupOptions{}
// Backup a subdirectory first, such that we can remove the tree pack for the subdirectory
testRunBackup(t, env.testdata, []string{"test"}, opts, env.gopts)
r, err := OpenRepository(context.TODO(), env.gopts)
rtest.OK(t, err)
rtest.OK(t, r.LoadIndex(context.TODO(), nil))
treePacks := restic.NewIDSet()
r.Index().Each(context.TODO(), func(pb restic.PackedBlob) {
if pb.Type == restic.TreeBlob {
treePacks.Insert(pb.PackID)
}
})
treePacks := listTreePacks(env.gopts, t)
testRunBackup(t, filepath.Dir(env.testdata), []string{filepath.Base(env.testdata)}, opts, env.gopts)
testRunCheck(t, env.gopts)
// delete the subdirectory pack first
for id := range treePacks {
rtest.OK(t, r.Backend().Remove(context.TODO(), backend.Handle{Type: restic.PackFile, Name: id.String()}))
}
removePacks(env.gopts, t, treePacks)
testRunRebuildIndex(t, env.gopts)
// now the repo is missing the tree blob in the index; check should report this
testRunCheckMustFail(t, env.gopts)
// second backup should report an error but "heal" this situation
err = testRunBackupAssumeFailure(t, filepath.Dir(env.testdata), []string{filepath.Base(env.testdata)}, opts, env.gopts)
err := testRunBackupAssumeFailure(t, filepath.Dir(env.testdata), []string{filepath.Base(env.testdata)}, opts, env.gopts)
rtest.Assert(t, err != nil, "backup should have reported an error for the subdirectory")
testRunCheck(t, env.gopts)
@@ -406,6 +394,7 @@ func TestIncrementalBackup(t *testing.T) {
t.Logf("repository grown by %d bytes", stat3.size-stat2.size)
}
// nolint: staticcheck // false positive nil pointer dereference check
func TestBackupTags(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
@@ -441,6 +430,7 @@ func TestBackupTags(t *testing.T) {
"expected parent to be %v, got %v", parent.ID, newest.Parent)
}
// nolint: staticcheck // false positive nil pointer dereference check
func TestBackupProgramVersion(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
@@ -637,3 +627,32 @@ func TestStdinFromCommandFailNoOutputAndExitCode(t *testing.T) {
testRunCheck(t, env.gopts)
}
func TestBackupEmptyPassword(t *testing.T) {
// basic sanity test that empty passwords work
env, cleanup := withTestEnvironment(t)
defer cleanup()
env.gopts.password = ""
env.gopts.InsecureNoPassword = true
testSetupBackupData(t, env)
testRunBackup(t, filepath.Dir(env.testdata), []string{"testdata"}, BackupOptions{}, env.gopts)
testListSnapshots(t, env.gopts, 1)
testRunCheck(t, env.gopts)
}
func TestBackupSkipIfUnchanged(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
testSetupBackupData(t, env)
opts := BackupOptions{SkipIfUnchanged: true}
for i := 0; i < 3; i++ {
testRunBackup(t, filepath.Dir(env.testdata), []string{"testdata"}, opts, env.gopts)
testListSnapshots(t, env.gopts, 1)
}
testRunCheck(t, env.gopts)
}

View File

@@ -8,7 +8,7 @@ import (
"strings"
"time"
"github.com/restic/restic/internal/cache"
"github.com/restic/restic/internal/backend/cache"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/fs"
"github.com/restic/restic/internal/ui"
@@ -25,7 +25,8 @@ The "cache" command allows listing and cleaning local cache directories.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
`,
DisableAutoGenTag: true,
RunE: func(_ *cobra.Command, args []string) error {

View File

@@ -7,7 +7,6 @@ import (
"github.com/spf13/cobra"
"github.com/restic/restic/internal/backend"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
@@ -22,7 +21,10 @@ The "cat" command is used to print internal objects to stdout.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -64,19 +66,11 @@ func runCat(ctx context.Context, gopts GlobalOptions, args []string) error {
return err
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
if !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
tpe := args[0]
@@ -154,9 +148,9 @@ func runCat(ctx context.Context, gopts GlobalOptions, args []string) error {
return nil
case "pack":
h := backend.Handle{Type: restic.PackFile, Name: id.String()}
buf, err := backend.LoadAll(ctx, nil, repo.Backend(), h)
if err != nil {
buf, err := repo.LoadRaw(ctx, restic.PackFile, id)
// allow returning broken pack files
if buf == nil {
return err
}
@@ -176,8 +170,7 @@ func runCat(ctx context.Context, gopts GlobalOptions, args []string) error {
}
for _, t := range []restic.BlobType{restic.DataBlob, restic.TreeBlob} {
bh := restic.BlobHandle{ID: id, Type: t}
if !repo.Index().Has(bh) {
if _, ok := repo.LookupBlobSize(t, id); !ok {
continue
}

View File

@@ -11,12 +11,15 @@ import (
"github.com/spf13/cobra"
"github.com/restic/restic/internal/cache"
"github.com/restic/restic/internal/backend/cache"
"github.com/restic/restic/internal/checker"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/fs"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
"github.com/restic/restic/internal/ui/termstatus"
)
var cmdCheck = &cobra.Command{
@@ -32,11 +35,16 @@ repository and not use a local cache.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
return runCheck(cmd.Context(), checkOptions, globalOptions, args)
term, cancel := setupTermstatus()
defer cancel()
return runCheck(cmd.Context(), checkOptions, globalOptions, args, term)
},
PreRunE: func(_ *cobra.Command, _ []string) error {
return checkFlags(checkOptions)
@@ -154,7 +162,7 @@ func parsePercentage(s string) (float64, error) {
// - if the user explicitly requested --no-cache, we don't use any cache
// - if the user provides --cache-dir, we use a cache in a temporary sub-directory of the specified directory and the sub-directory is deleted after the check
// - by default, we use a cache in a temporary directory that is deleted after the check
func prepareCheckCache(opts CheckOptions, gopts *GlobalOptions) (cleanup func()) {
func prepareCheckCache(opts CheckOptions, gopts *GlobalOptions, printer progress.Printer) (cleanup func()) {
cleanup = func() {}
if opts.WithCache {
// use the default cache, no setup needed
@@ -171,53 +179,54 @@ func prepareCheckCache(opts CheckOptions, gopts *GlobalOptions) (cleanup func())
cachedir = cache.EnvDir()
}
// use a cache in a temporary directory
if cachedir != "" {
// use a cache in a temporary directory
err := os.MkdirAll(cachedir, 0755)
if err != nil {
Warnf("unable to create cache directory %s, disabling cache: %v\n", cachedir, err)
gopts.NoCache = true
return cleanup
}
}
tempdir, err := os.MkdirTemp(cachedir, "restic-check-cache-")
if err != nil {
// if an error occurs, don't use any cache
Warnf("unable to create temporary directory for cache during check, disabling cache: %v\n", err)
printer.E("unable to create temporary directory for cache during check, disabling cache: %v\n", err)
gopts.NoCache = true
return cleanup
}
gopts.CacheDir = tempdir
Verbosef("using temporary cache in %v\n", tempdir)
printer.P("using temporary cache in %v\n", tempdir)
cleanup = func() {
err := fs.RemoveAll(tempdir)
if err != nil {
Warnf("error removing temporary cache directory: %v\n", err)
printer.E("error removing temporary cache directory: %v\n", err)
}
}
return cleanup
}
func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args []string) error {
func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args []string, term *termstatus.Terminal) error {
if len(args) != 0 {
return errors.Fatal("the check command expects no arguments, only options - please see `restic help check` for usage and flags")
}
cleanup := prepareCheckCache(opts, &gopts)
AddCleanupHandler(func(code int) (int, error) {
cleanup()
return code, nil
})
printer := newTerminalProgressPrinter(gopts.verbosity, term)
repo, err := OpenRepository(ctx, gopts)
cleanup := prepareCheckCache(opts, &gopts, printer)
defer cleanup()
if !gopts.NoLock {
printer.P("create exclusive lock for repository\n")
}
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
if !gopts.NoLock {
Verbosef("create exclusive lock for repository\n")
var lock *restic.Lock
lock, ctx, err = lockRepoExclusive(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
chkr := checker.New(repo, opts.CheckUnused)
err = chkr.LoadSnapshots(ctx)
@@ -225,71 +234,99 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
return err
}
Verbosef("load indexes\n")
bar := newIndexProgress(gopts.Quiet, gopts.JSON)
printer.P("load indexes\n")
bar := newIndexTerminalProgress(gopts.Quiet, gopts.JSON, term)
hints, errs := chkr.LoadIndex(ctx, bar)
if ctx.Err() != nil {
return ctx.Err()
}
errorsFound := false
suggestIndexRebuild := false
suggestLegacyIndexRebuild := false
mixedFound := false
for _, hint := range hints {
switch hint.(type) {
case *checker.ErrDuplicatePacks, *checker.ErrOldIndexFormat:
Printf("%v\n", hint)
case *checker.ErrDuplicatePacks:
term.Print(hint.Error())
suggestIndexRebuild = true
case *checker.ErrOldIndexFormat:
printer.E("error: %v\n", hint)
suggestLegacyIndexRebuild = true
errorsFound = true
case *checker.ErrMixedPack:
Printf("%v\n", hint)
term.Print(hint.Error())
mixedFound = true
default:
Warnf("error: %v\n", hint)
printer.E("error: %v\n", hint)
errorsFound = true
}
}
if suggestIndexRebuild {
Printf("Duplicate packs/old indexes are non-critical, you can run `restic repair index' to correct this.\n")
term.Print("Duplicate packs are non-critical, you can run `restic repair index' to correct this.\n")
}
if suggestLegacyIndexRebuild {
printer.E("error: Found indexes using the legacy format, you must run `restic repair index' to correct this.\n")
}
if mixedFound {
Printf("Mixed packs with tree and data blobs are non-critical, you can run `restic prune` to correct this.\n")
term.Print("Mixed packs with tree and data blobs are non-critical, you can run `restic prune` to correct this.\n")
}
if len(errs) > 0 {
for _, err := range errs {
Warnf("error: %v\n", err)
printer.E("error: %v\n", err)
}
return errors.Fatal("LoadIndex returned errors")
printer.E("\nThe repository index is damaged and must be repaired. You must run `restic repair index' to correct this.\n\n")
return errors.Fatal("repository contains errors")
}
orphanedPacks := 0
errChan := make(chan error)
salvagePacks := restic.NewIDSet()
Verbosef("check all packs\n")
printer.P("check all packs\n")
go chkr.Packs(ctx, errChan)
for err := range errChan {
if checker.IsOrphanedPack(err) {
orphanedPacks++
Verbosef("%v\n", err)
var packErr *checker.PackError
if errors.As(err, &packErr) {
if packErr.Orphaned {
orphanedPacks++
printer.V("%v\n", err)
} else {
if packErr.Truncated {
salvagePacks.Insert(packErr.ID)
}
errorsFound = true
printer.E("%v\n", err)
}
} else if err == checker.ErrLegacyLayout {
Verbosef("repository still uses the S3 legacy layout\nPlease run `restic migrate s3legacy` to correct this.\n")
errorsFound = true
printer.E("error: repository still uses the S3 legacy layout\nYou must run `restic migrate s3legacy` to correct this.\n")
} else {
errorsFound = true
Warnf("%v\n", err)
printer.E("%v\n", err)
}
}
if orphanedPacks > 0 {
Verbosef("%d additional files were found in the repo, which likely contain duplicate data.\nThis is non-critical, you can run `restic prune` to correct this.\n", orphanedPacks)
if orphanedPacks > 0 && !errorsFound {
// hide notice if repository is damaged
printer.P("%d additional files were found in the repo, which likely contain duplicate data.\nThis is non-critical, you can run `restic prune` to correct this.\n", orphanedPacks)
}
if ctx.Err() != nil {
return ctx.Err()
}
Verbosef("check snapshots, trees and blobs\n")
printer.P("check snapshots, trees and blobs\n")
errChan = make(chan error)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
bar := newProgressMax(!gopts.Quiet, 0, "snapshots")
bar := newTerminalProgressMax(!gopts.Quiet, 0, "snapshots", term)
defer bar.Done()
chkr.Structure(ctx, bar, errChan)
}()
@@ -297,16 +334,12 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
for err := range errChan {
errorsFound = true
if e, ok := err.(*checker.TreeError); ok {
var clean string
if stdoutCanUpdateStatus() {
clean = clearLine(0)
}
Warnf(clean+"error for tree %v:\n", e.ID.Str())
printer.E("error for tree %v:\n", e.ID.Str())
for _, treeErr := range e.Errors {
Warnf(" %v\n", treeErr)
printer.E(" %v\n", treeErr)
}
} else {
Warnf("error: %v\n", err)
printer.E("error: %v\n", err)
}
}
@@ -314,10 +347,17 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
// Must happen after `errChan` is read from in the above loop to avoid
// deadlocking in the case of errors.
wg.Wait()
if ctx.Err() != nil {
return ctx.Err()
}
if opts.CheckUnused {
for _, id := range chkr.UnusedBlobs(ctx) {
Verbosef("unused blob %v\n", id)
unused, err := chkr.UnusedBlobs(ctx)
if err != nil {
return err
}
for _, id := range unused {
printer.P("unused blob %v\n", id)
errorsFound = true
}
}
@@ -325,36 +365,24 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
doReadData := func(packs map[restic.ID]int64) {
packCount := uint64(len(packs))
p := newProgressMax(!gopts.Quiet, packCount, "packs")
p := newTerminalProgressMax(!gopts.Quiet, packCount, "packs", term)
errChan := make(chan error)
go chkr.ReadPacks(ctx, packs, p, errChan)
var salvagePacks restic.IDs
for err := range errChan {
errorsFound = true
Warnf("%v\n", err)
if err, ok := err.(*checker.ErrPackData); ok {
salvagePacks = append(salvagePacks, err.PackID)
printer.E("%v\n", err)
if err, ok := err.(*repository.ErrPackData); ok {
salvagePacks.Insert(err.PackID)
}
}
p.Done()
if len(salvagePacks) > 0 {
Warnf("\nThe repository contains pack files with damaged blobs. These blobs must be removed to repair the repository. This can be done using the following commands. Please read the troubleshooting guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html first.\n\n")
var strIDs []string
for _, id := range salvagePacks {
strIDs = append(strIDs, id.String())
}
Warnf("restic repair packs %v\nrestic repair snapshots --forget\n\n", strings.Join(strIDs, " "))
Warnf("Corrupted blobs are either caused by hardware problems or bugs in restic. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting!\n")
}
}
switch {
case opts.ReadData:
Verbosef("read all data\n")
printer.P("read all data\n")
doReadData(selectPacksByBucket(chkr.GetPacks(), 1, 1))
case opts.ReadDataSubset != "":
var packs map[restic.ID]int64
@@ -364,12 +392,12 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
totalBuckets := dataSubset[1]
packs = selectPacksByBucket(chkr.GetPacks(), bucket, totalBuckets)
packCount := uint64(len(packs))
Verbosef("read group #%d of %d data packs (out of total %d packs in %d groups)\n", bucket, packCount, chkr.CountPacks(), totalBuckets)
printer.P("read group #%d of %d data packs (out of total %d packs in %d groups)\n", bucket, packCount, chkr.CountPacks(), totalBuckets)
} else if strings.HasSuffix(opts.ReadDataSubset, "%") {
percentage, err := parsePercentage(opts.ReadDataSubset)
if err == nil {
packs = selectRandomPacksByPercentage(chkr.GetPacks(), percentage)
Verbosef("read %.1f%% of data packs\n", percentage)
printer.P("read %.1f%% of data packs\n", percentage)
}
} else {
repoSize := int64(0)
@@ -385,7 +413,7 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
subsetSize = repoSize
}
packs = selectRandomPacksByFileSize(chkr.GetPacks(), subsetSize, repoSize)
Verbosef("read %d bytes of data packs\n", subsetSize)
printer.P("read %d bytes of data packs\n", subsetSize)
}
if packs == nil {
return errors.Fatal("internal error: failed to select packs to check")
@@ -393,11 +421,27 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
doReadData(packs)
}
if errorsFound {
return errors.Fatal("repository contains errors")
if len(salvagePacks) > 0 {
printer.E("\nThe repository contains damaged pack files. These damaged files must be removed to repair the repository. This can be done using the following commands. Please read the troubleshooting guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html first.\n\n")
var strIDs []string
for id := range salvagePacks {
strIDs = append(strIDs, id.String())
}
printer.E("restic repair packs %v\nrestic repair snapshots --forget\n\n", strings.Join(strIDs, " "))
printer.E("Damaged pack files can be caused by backend problems, hardware problems or bugs in restic. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting!\n")
}
Verbosef("no errors were found\n")
if ctx.Err() != nil {
return ctx.Err()
}
if errorsFound {
if len(salvagePacks) == 0 {
printer.E("\nThe repository is damaged and must be repaired. Please follow the troubleshooting guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html .\n\n")
}
return errors.Fatal("repository contains errors")
}
printer.P("no errors were found\n")
return nil
}

View File

@@ -1,10 +1,12 @@
package main
import (
"bytes"
"context"
"testing"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/termstatus"
)
func testRunCheck(t testing.TB, gopts GlobalOptions) {
@@ -23,12 +25,14 @@ func testRunCheckMustFail(t testing.TB, gopts GlobalOptions) {
}
func testRunCheckOutput(gopts GlobalOptions, checkUnused bool) (string, error) {
buf, err := withCaptureStdout(func() error {
buf := bytes.NewBuffer(nil)
gopts.stdout = buf
err := withTermStatus(gopts, func(ctx context.Context, term *termstatus.Terminal) error {
opts := CheckOptions{
ReadData: true,
CheckUnused: checkUnused,
}
return runCheck(context.TODO(), opts, gopts, nil)
return runCheck(context.TODO(), opts, gopts, nil, term)
})
return buf.String(), err
}

View File

@@ -1,12 +1,17 @@
package main
import (
"io/fs"
"math"
"os"
"reflect"
"strings"
"testing"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func TestParsePercentage(t *testing.T) {
@@ -163,3 +168,79 @@ func TestSelectNoRandomPacksByFileSize(t *testing.T) {
selectedPacks := selectRandomPacksByFileSize(testPacks, 10, 500)
rtest.Assert(t, len(selectedPacks) == 0, "Expected 0 selected packs")
}
func checkIfFileWithSimilarNameExists(files []fs.DirEntry, fileName string) bool {
found := false
for _, file := range files {
if file.IsDir() {
dirName := file.Name()
if strings.Contains(dirName, fileName) {
found = true
}
}
}
return found
}
func TestPrepareCheckCache(t *testing.T) {
// Create a temporary directory for the cache
tmpDirBase := t.TempDir()
testCases := []struct {
opts CheckOptions
withValidCache bool
}{
{CheckOptions{WithCache: true}, true}, // Shouldn't create temp directory
{CheckOptions{WithCache: false}, true}, // Should create temp directory
{CheckOptions{WithCache: false}, false}, // Should create cache directory first, then temp directory
}
for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
if !testCase.withValidCache {
// remove tmpDirBase to simulate non-existing cache directory
err := os.Remove(tmpDirBase)
rtest.OK(t, err)
}
gopts := GlobalOptions{CacheDir: tmpDirBase}
cleanup := prepareCheckCache(testCase.opts, &gopts, &progress.NoopPrinter{})
files, err := os.ReadDir(tmpDirBase)
rtest.OK(t, err)
if !testCase.opts.WithCache {
// If using a temporary cache directory, the cache directory should exist
// listing all directories inside tmpDirBase (cacheDir)
// one directory should be tmpDir created by prepareCheckCache with 'restic-check-cache-' in path
found := checkIfFileWithSimilarNameExists(files, "restic-check-cache-")
if !found {
t.Errorf("Expected temporary directory to exist, but it does not")
}
} else {
// If not using the cache, the temp directory should not exist
rtest.Assert(t, len(files) == 0, "expected cache directory not to exist, but it does: %v", files)
}
// Call the cleanup function to remove the temporary cache directory
cleanup()
// Verify that the cache directory has been removed
files, err = os.ReadDir(tmpDirBase)
rtest.OK(t, err)
rtest.Assert(t, len(files) == 0, "Expected cache directory to be removed, but it still exists: %v", files)
})
}
}
func TestPrepareDefaultCheckCache(t *testing.T) {
gopts := GlobalOptions{CacheDir: ""}
cleanup := prepareCheckCache(CheckOptions{}, &gopts, &progress.NoopPrinter{})
_, err := os.ReadDir(gopts.CacheDir)
rtest.OK(t, err)
// Call the cleanup function to remove the temporary cache directory
cleanup()
// Verify that the cache directory has been removed
_, err = os.ReadDir(gopts.CacheDir)
rtest.Assert(t, errors.Is(err, os.ErrNotExist), "Expected cache directory to be removed, but it still exists")
}

View File

@@ -30,6 +30,14 @@ This means that copied files, which existed in both the source and destination
repository, /may occupy up to twice their space/ in the destination repository.
This can be mitigated by the "--copy-chunker-params" option when initializing a
new destination repository using the "init" command.
EXIT STATUS
===========
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
RunE: func(cmd *cobra.Command, args []string) error {
return runCopy(cmd.Context(), copyOptions, globalOptions, args)
@@ -53,7 +61,7 @@ func init() {
}
func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args []string) error {
secondaryGopts, isFromRepo, err := fillSecondaryGlobalOpts(opts.secondaryRepoOptions, gopts, "destination")
secondaryGopts, isFromRepo, err := fillSecondaryGlobalOpts(ctx, opts.secondaryRepoOptions, gopts, "destination")
if err != nil {
return err
}
@@ -62,30 +70,17 @@ func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args []
gopts, secondaryGopts = secondaryGopts, gopts
}
srcRepo, err := OpenRepository(ctx, gopts)
ctx, srcRepo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
defer unlock()
dstRepo, err := OpenRepository(ctx, secondaryGopts)
if err != nil {
return err
}
if !gopts.NoLock {
var srcLock *restic.Lock
srcLock, ctx, err = lockRepo(ctx, srcRepo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(srcLock)
if err != nil {
return err
}
}
dstLock, ctx, err := lockRepo(ctx, dstRepo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(dstLock)
ctx, dstRepo, unlock, err := openWithAppendLock(ctx, secondaryGopts, false)
if err != nil {
return err
}
defer unlock()
srcSnapshotLister, err := restic.MemorizeList(ctx, srcRepo, restic.SnapshotFile)
if err != nil {
@@ -116,6 +111,9 @@ func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args []
// also consider identical snapshot copies
dstSnapshotByOriginal[*sn.ID()] = append(dstSnapshotByOriginal[*sn.ID()], sn)
}
if ctx.Err() != nil {
return ctx.Err()
}
// remember already processed trees across all snapshots
visitedTrees := restic.NewIDSet()
@@ -160,7 +158,7 @@ func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args []
}
Verbosef("snapshot %s saved\n", newID.Str())
}
return nil
return ctx.Err()
}
func similarSnapshots(sna *restic.Snapshot, snb *restic.Snapshot) bool {
@@ -197,7 +195,7 @@ func copyTree(ctx context.Context, srcRepo restic.Repository, dstRepo restic.Rep
packList := restic.NewIDSet()
enqueue := func(h restic.BlobHandle) {
pb := srcRepo.Index().Lookup(h)
pb := srcRepo.LookupBlob(h.Type, h.ID)
copyBlobs.Insert(h)
for _, p := range pb {
packList.Insert(p.PackID)
@@ -212,7 +210,7 @@ func copyTree(ctx context.Context, srcRepo restic.Repository, dstRepo restic.Rep
// Do we already have this tree blob?
treeHandle := restic.BlobHandle{ID: tree.ID, Type: restic.TreeBlob}
if !dstRepo.Index().Has(treeHandle) {
if _, ok := dstRepo.LookupBlobSize(treeHandle.Type, treeHandle.ID); !ok {
// copy raw tree bytes to avoid problems if the serialization changes
enqueue(treeHandle)
}
@@ -222,7 +220,7 @@ func copyTree(ctx context.Context, srcRepo restic.Repository, dstRepo restic.Rep
// Copy the blobs for this file.
for _, blobID := range entry.Content {
h := restic.BlobHandle{Type: restic.DataBlob, ID: blobID}
if !dstRepo.Index().Has(h) {
if _, ok := dstRepo.LookupBlobSize(h.Type, h.ID); !ok {
enqueue(h)
}
}

View File

@@ -13,10 +13,12 @@ func testRunCopy(t testing.TB, srcGopts GlobalOptions, dstGopts GlobalOptions) {
gopts := srcGopts
gopts.Repo = dstGopts.Repo
gopts.password = dstGopts.password
gopts.InsecureNoPassword = dstGopts.InsecureNoPassword
copyOpts := CopyOptions{
secondaryRepoOptions: secondaryRepoOptions{
Repo: srcGopts.Repo,
password: srcGopts.password,
Repo: srcGopts.Repo,
password: srcGopts.password,
InsecureNoPassword: srcGopts.InsecureNoPassword,
},
}
@@ -134,3 +136,22 @@ func TestCopyUnstableJSON(t *testing.T) {
testRunCheck(t, env2.gopts)
testListSnapshots(t, env2.gopts, 1)
}
func TestCopyToEmptyPassword(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
env2, cleanup2 := withTestEnvironment(t)
defer cleanup2()
env2.gopts.password = ""
env2.gopts.InsecureNoPassword = true
testSetupBackupData(t, env)
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9")}, BackupOptions{}, env.gopts)
testRunInit(t, env2.gopts)
testRunCopy(t, env.gopts, env2.gopts)
testListSnapshots(t, env.gopts, 1)
testListSnapshots(t, env2.gopts, 1)
testRunCheck(t, env2.gopts)
}

View File

@@ -20,12 +20,11 @@ import (
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
"github.com/restic/restic/internal/backend"
"github.com/restic/restic/internal/crypto"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/index"
"github.com/restic/restic/internal/pack"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/repository/index"
"github.com/restic/restic/internal/repository/pack"
"github.com/restic/restic/internal/restic"
)
@@ -44,7 +43,10 @@ is used for debugging purposes only.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -153,19 +155,11 @@ func runDebugDump(ctx context.Context, gopts GlobalOptions, args []string) error
return errors.Fatal("type not specified")
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
if !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
tpe := args[0]
@@ -324,10 +318,11 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
if err != nil {
panic(err)
}
be := repo.Backend()
h := backend.Handle{
Name: packID.String(),
Type: restic.PackFile,
pack, err := repo.LoadRaw(ctx, restic.PackFile, packID)
// allow processing broken pack files
if pack == nil {
return err
}
wg, ctx := errgroup.WithContext(ctx)
@@ -339,19 +334,11 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
wg.Go(func() error {
for _, blob := range list {
Printf(" loading blob %v at %v (length %v)\n", blob.ID, blob.Offset, blob.Length)
buf := make([]byte, blob.Length)
err := be.Load(ctx, h, int(blob.Length), int64(blob.Offset), func(rd io.Reader) error {
n, err := io.ReadFull(rd, buf)
if err != nil {
return fmt.Errorf("read error after %d bytes: %v", n, err)
}
return nil
})
if err != nil {
Warnf("error read: %v\n", err)
if int(blob.Offset+blob.Length) > len(pack) {
Warnf("skipping truncated blob\n")
continue
}
buf := pack[blob.Offset : blob.Offset+blob.Length]
key := repo.Key()
nonce, plaintext := buf[:key.NonceSize()], buf[key.NonceSize():]
@@ -442,10 +429,15 @@ func storePlainBlob(id restic.ID, prefix string, plain []byte) error {
}
func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamineOptions, args []string) error {
repo, err := OpenRepository(ctx, gopts)
if opts.ExtractPack && gopts.NoLock {
return fmt.Errorf("--extract-pack and --no-lock are mutually exclusive")
}
ctx, repo, unlock, err := openWithAppendLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
defer unlock()
ids := make([]restic.ID, 0)
for _, name := range args {
@@ -464,15 +456,6 @@ func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamine
return errors.Fatal("no pack files to examine")
}
if !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
bar := newIndexProgress(gopts.Quiet, gopts.JSON)
err = repo.LoadIndex(ctx, bar)
if err != nil {
@@ -494,20 +477,12 @@ func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamine
func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repository, id restic.ID) error {
Printf("examine %v\n", id)
h := backend.Handle{
Type: restic.PackFile,
Name: id.String(),
}
fi, err := repo.Backend().Stat(ctx, h)
if err != nil {
return err
}
Printf(" file size is %v\n", fi.Size)
buf, err := backend.LoadAll(ctx, nil, repo.Backend(), h)
if err != nil {
buf, err := repo.LoadRaw(ctx, restic.PackFile, id)
// also process damaged pack files
if buf == nil {
return err
}
Printf(" file size is %v\n", len(buf))
gotID := restic.Hash(buf)
if !id.Equal(gotID) {
Printf(" wanted hash %v, got %v\n", id, gotID)
@@ -520,13 +495,13 @@ func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repo
blobsLoaded := false
// examine all data the indexes have for the pack file
for b := range repo.Index().ListPacks(ctx, restic.NewIDSet(id)) {
for b := range repo.ListPacksFromIndex(ctx, restic.NewIDSet(id)) {
blobs := b.Blobs
if len(blobs) == 0 {
continue
}
checkPackSize(blobs, fi.Size)
checkPackSize(blobs, len(buf))
err = loadBlobs(ctx, opts, repo, id, blobs)
if err != nil {
@@ -539,11 +514,11 @@ func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repo
Printf(" ========================================\n")
Printf(" inspect the pack itself\n")
blobs, _, err := repo.ListPack(ctx, id, fi.Size)
blobs, _, err := repo.ListPack(ctx, id, int64(len(buf)))
if err != nil {
return fmt.Errorf("pack %v: %v", id.Str(), err)
}
checkPackSize(blobs, fi.Size)
checkPackSize(blobs, len(buf))
if !blobsLoaded {
return loadBlobs(ctx, opts, repo, id, blobs)
@@ -551,7 +526,7 @@ func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repo
return nil
}
func checkPackSize(blobs []restic.Blob, fileSize int64) {
func checkPackSize(blobs []restic.Blob, fileSize int) {
// track current size and offset
var size, offset uint64

View File

@@ -33,13 +33,16 @@ Metadata comparison will likely not work if a backup was created using the
'--ignore-inode' or '--ignore-ctime' option.
To only compare files in specific subfolders, you can use the
"<snapshotID>:<subfolder>" syntax, where "subfolder" is a path within the
"snapshotID:subfolder" syntax, where "subfolder" is a path within the
snapshot.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -156,7 +159,7 @@ func updateBlobs(repo restic.Loader, blobs restic.BlobSet, stats *DiffStat) {
stats.TreeBlobs++
}
size, found := repo.LookupBlobSize(h.ID, h.Type)
size, found := repo.LookupBlobSize(h.Type, h.ID)
if !found {
Warnf("unable to find blob size for %v\n", h)
continue
@@ -344,19 +347,11 @@ func runDiff(ctx context.Context, opts DiffOptions, gopts GlobalOptions, args []
return errors.Fatalf("specify two snapshot IDs")
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
if !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
// cache snapshots listing
be, err := restic.MemorizeList(ctx, repo, restic.SnapshotFile)

View File

@@ -28,13 +28,16 @@ The special snapshotID "latest" can be used to use the latest snapshot in the
repository.
To include the folder content at the root of the archive, you can use the
"<snapshotID>:<subfolder>" syntax, where "subfolder" is a path within the
"snapshotID:subfolder" syntax, where "subfolder" is a path within the
snapshot.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -131,19 +134,11 @@ func runDump(ctx context.Context, opts DumpOptions, gopts GlobalOptions, args []
splittedPath := splitPath(path.Clean(pathToPrint))
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
if !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
sn, subfolder, err := (&restic.SnapshotFilter{
Hosts: opts.Hosts,

View File

@@ -0,0 +1,59 @@
package main
import (
"fmt"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/feature"
"github.com/restic/restic/internal/ui/table"
"github.com/spf13/cobra"
)
var featuresCmd = &cobra.Command{
Use: "features",
Short: "Print list of feature flags",
Long: `
The "features" command prints a list of supported feature flags.
To pass feature flags to restic, set the RESTIC_FEATURES environment variable
to "featureA=true,featureB=false". Specifying an unknown feature flag is an error.
A feature can either be in alpha, beta, stable or deprecated state.
An _alpha_ feature is disabled by default and may change in arbitrary ways between restic versions or be removed.
A _beta_ feature is enabled by default, but still can change in minor ways or be removed.
A _stable_ feature is always enabled and cannot be disabled. The flag will be removed in a future restic version.
A _deprecated_ feature is always disabled and cannot be enabled. The flag will be removed in a future restic version.
EXIT STATUS
===========
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
`,
Hidden: true,
DisableAutoGenTag: true,
RunE: func(_ *cobra.Command, args []string) error {
if len(args) != 0 {
return errors.Fatal("the feature command expects no arguments")
}
fmt.Printf("All Feature Flags:\n")
flags := feature.Flag.List()
tab := table.New()
tab.AddColumn("Name", "{{ .Name }}")
tab.AddColumn("Type", "{{ .Type }}")
tab.AddColumn("Default", "{{ .Default }}")
tab.AddColumn("Description", "{{ .Description }}")
for _, flag := range flags {
tab.AddRow(flag)
}
return tab.Write(globalOptions.stdout)
},
}
func init() {
cmdRoot.AddCommand(featuresCmd)
}

View File

@@ -33,7 +33,10 @@ restic find --pack 025c1d06
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -126,6 +129,7 @@ func (s *statefulOutput) PrintPatternJSON(path string, node *restic.Node) {
// Make the following attributes disappear
Name byte `json:"name,omitempty"`
ExtendedAttributes byte `json:"extended_attributes,omitempty"`
GenericAttributes byte `json:"generic_attributes,omitempty"`
Device byte `json:"device,omitempty"`
Content byte `json:"content,omitempty"`
Subtree byte `json:"subtree,omitempty"`
@@ -438,7 +442,10 @@ func (f *Finder) packsToBlobs(ctx context.Context, packs []string) error {
if err != errAllPacksFound {
// try to resolve unknown pack ids from the index
packIDs = f.indexPacksToBlobs(ctx, packIDs)
packIDs, err = f.indexPacksToBlobs(ctx, packIDs)
if err != nil {
return err
}
}
if len(packIDs) > 0 {
@@ -455,13 +462,13 @@ func (f *Finder) packsToBlobs(ctx context.Context, packs []string) error {
return nil
}
func (f *Finder) indexPacksToBlobs(ctx context.Context, packIDs map[string]struct{}) map[string]struct{} {
func (f *Finder) indexPacksToBlobs(ctx context.Context, packIDs map[string]struct{}) (map[string]struct{}, error) {
wctx, cancel := context.WithCancel(ctx)
defer cancel()
// remember which packs were found in the index
indexPackIDs := make(map[string]struct{})
f.repo.Index().Each(wctx, func(pb restic.PackedBlob) {
err := f.repo.ListBlobs(wctx, func(pb restic.PackedBlob) {
idStr := pb.PackID.String()
// keep entry in packIDs as Each() returns individual index entries
matchingID := false
@@ -480,6 +487,9 @@ func (f *Finder) indexPacksToBlobs(ctx context.Context, packIDs map[string]struc
indexPackIDs[idStr] = struct{}{}
}
})
if err != nil {
return nil, err
}
for id := range indexPackIDs {
delete(packIDs, id)
@@ -492,19 +502,17 @@ func (f *Finder) indexPacksToBlobs(ctx context.Context, packIDs map[string]struc
}
Warnf("some pack files are missing from the repository, getting their blobs from the repository index: %v\n\n", list)
}
return packIDs
return packIDs, nil
}
func (f *Finder) findObjectPack(id string, t restic.BlobType) {
idx := f.repo.Index()
rid, err := restic.ParseID(id)
if err != nil {
Printf("Note: cannot find pack for object '%s', unable to parse ID: %v\n", id, err)
return
}
blobs := idx.Lookup(restic.BlobHandle{ID: rid, Type: t})
blobs := f.repo.LookupBlob(t, rid)
if len(blobs) == 0 {
Printf("Object %s not found in the index\n", rid.Str())
return
@@ -562,19 +570,11 @@ func runFind(ctx context.Context, opts FindOptions, gopts GlobalOptions, args []
return errors.Fatal("cannot have several ID types")
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
if !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
snapshotLister, err := restic.MemorizeList(ctx, repo, restic.SnapshotFile)
if err != nil {
@@ -615,6 +615,9 @@ func runFind(ctx context.Context, opts FindOptions, gopts GlobalOptions, args []
for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, opts.Snapshots) {
filteredSnapshots = append(filteredSnapshots, sn)
}
if ctx.Err() != nil {
return ctx.Err()
}
sort.Slice(filteredSnapshots, func(i, j int) bool {
return filteredSnapshots[i].Time.Before(filteredSnapshots[j].Time)

View File

@@ -3,11 +3,14 @@ package main
import (
"context"
"encoding/json"
"fmt"
"io"
"strconv"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/feature"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/termstatus"
"github.com/spf13/cobra"
)
@@ -18,6 +21,9 @@ var cmdForget = &cobra.Command{
The "forget" command removes snapshots according to a policy. All snapshots are
first divided into groups according to "--group-by", and after that the policy
specified by the "--keep-*" options is applied to each group individually.
If there are not enough snapshots to keep one for each duration related
"--keep-{within-,}*" option, the oldest snapshot in the group is kept
additionally.
Please note that this command really only deletes the snapshot object in the
repository, which is a reference to data stored there. In order to remove the
@@ -29,11 +35,16 @@ security considerations.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
return runForget(cmd.Context(), forgetOptions, forgetPruneOptions, globalOptions, args)
term, cancel := setupTermstatus()
defer cancel()
return runForget(cmd.Context(), forgetOptions, forgetPruneOptions, globalOptions, term, args)
},
}
@@ -88,6 +99,8 @@ type ForgetOptions struct {
WithinYearly restic.Duration
KeepTags restic.TagLists
UnsafeAllowRemoveAll bool
restic.SnapshotFilter
Compact bool
@@ -117,6 +130,7 @@ func init() {
f.VarP(&forgetOptions.WithinMonthly, "keep-within-monthly", "", "keep monthly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot")
f.VarP(&forgetOptions.WithinYearly, "keep-within-yearly", "", "keep yearly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot")
f.Var(&forgetOptions.KeepTags, "keep-tag", "keep snapshots with this `taglist` (can be specified multiple times)")
f.BoolVar(&forgetOptions.UnsafeAllowRemoveAll, "unsafe-allow-remove-all", false, "allow deleting all snapshots of a snapshot group")
initMultiSnapshotFilter(f, &forgetOptions.SnapshotFilter, false)
f.StringArrayVar(&forgetOptions.Hosts, "hostname", nil, "only consider snapshots with the given `hostname` (can be specified multiple times)")
@@ -152,7 +166,7 @@ func verifyForgetOptions(opts *ForgetOptions) error {
return nil
}
func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOptions, gopts GlobalOptions, args []string) error {
func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOptions, gopts GlobalOptions, term *termstatus.Terminal, args []string) error {
err := verifyForgetOptions(&opts)
if err != nil {
return err
@@ -163,23 +177,21 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
return err
}
repo, err := OpenRepository(ctx, gopts)
if err != nil {
return err
}
if gopts.NoLock && !opts.DryRun {
return errors.Fatal("--no-lock is only applicable in combination with --dry-run for forget command")
}
if !opts.DryRun || !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepoExclusive(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, opts.DryRun && gopts.NoLock)
if err != nil {
return err
}
defer unlock()
verbosity := gopts.verbosity
if gopts.JSON {
verbosity = 0
}
printer := newTerminalProgressPrinter(verbosity, term)
var snapshots restic.Snapshots
removeSnIDs := restic.NewIDSet()
@@ -187,6 +199,9 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
for sn := range FindFilteredSnapshots(ctx, repo, repo, &opts.SnapshotFilter, args) {
snapshots = append(snapshots, sn)
}
if ctx.Err() != nil {
return ctx.Err()
}
var jsonGroups []*ForgetGroup
@@ -217,72 +232,87 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
Tags: opts.KeepTags,
}
if policy.Empty() && len(args) == 0 {
if !gopts.JSON {
Verbosef("no policy was specified, no snapshots will be removed\n")
if policy.Empty() {
if opts.UnsafeAllowRemoveAll {
if opts.SnapshotFilter.Empty() {
return errors.Fatal("--unsafe-allow-remove-all is not allowed unless a snapshot filter option is specified")
}
// UnsafeAllowRemoveAll together with snapshot filter is fine
} else {
return errors.Fatal("no policy was specified, no snapshots will be removed")
}
}
if !policy.Empty() {
if !gopts.JSON {
Verbosef("Applying Policy: %v\n", policy)
}
printer.P("Applying Policy: %v\n", policy)
for k, snapshotGroup := range snapshotGroups {
if gopts.Verbose >= 1 && !gopts.JSON {
err = PrintSnapshotGroupHeader(globalOptions.stdout, k)
if err != nil {
return err
}
}
var key restic.SnapshotGroupKey
if json.Unmarshal([]byte(k), &key) != nil {
for k, snapshotGroup := range snapshotGroups {
if gopts.Verbose >= 1 && !gopts.JSON {
err = PrintSnapshotGroupHeader(globalOptions.stdout, k)
if err != nil {
return err
}
}
var fg ForgetGroup
fg.Tags = key.Tags
fg.Host = key.Hostname
fg.Paths = key.Paths
var key restic.SnapshotGroupKey
if json.Unmarshal([]byte(k), &key) != nil {
return err
}
keep, remove, reasons := restic.ApplyPolicy(snapshotGroup, policy)
var fg ForgetGroup
fg.Tags = key.Tags
fg.Host = key.Hostname
fg.Paths = key.Paths
if len(keep) != 0 && !gopts.Quiet && !gopts.JSON {
Printf("keep %d snapshots:\n", len(keep))
PrintSnapshots(globalOptions.stdout, keep, reasons, opts.Compact)
Printf("\n")
}
addJSONSnapshots(&fg.Keep, keep)
keep, remove, reasons := restic.ApplyPolicy(snapshotGroup, policy)
if len(remove) != 0 && !gopts.Quiet && !gopts.JSON {
Printf("remove %d snapshots:\n", len(remove))
PrintSnapshots(globalOptions.stdout, remove, nil, opts.Compact)
Printf("\n")
}
addJSONSnapshots(&fg.Remove, remove)
if feature.Flag.Enabled(feature.SafeForgetKeepTags) && !policy.Empty() && len(keep) == 0 {
return fmt.Errorf("refusing to delete last snapshot of snapshot group \"%v\"", key.String())
}
if len(keep) != 0 && !gopts.Quiet && !gopts.JSON {
printer.P("keep %d snapshots:\n", len(keep))
PrintSnapshots(globalOptions.stdout, keep, reasons, opts.Compact)
printer.P("\n")
}
fg.Keep = asJSONSnapshots(keep)
fg.Reasons = reasons
if len(remove) != 0 && !gopts.Quiet && !gopts.JSON {
printer.P("remove %d snapshots:\n", len(remove))
PrintSnapshots(globalOptions.stdout, remove, nil, opts.Compact)
printer.P("\n")
}
fg.Remove = asJSONSnapshots(remove)
jsonGroups = append(jsonGroups, &fg)
fg.Reasons = asJSONKeeps(reasons)
for _, sn := range remove {
removeSnIDs.Insert(*sn.ID())
}
jsonGroups = append(jsonGroups, &fg)
for _, sn := range remove {
removeSnIDs.Insert(*sn.ID())
}
}
}
if ctx.Err() != nil {
return ctx.Err()
}
if len(removeSnIDs) > 0 {
if !opts.DryRun {
err := DeleteFilesChecked(ctx, gopts, repo, removeSnIDs, restic.SnapshotFile)
bar := printer.NewCounter("files deleted")
err := restic.ParallelRemove(ctx, repo, removeSnIDs, restic.SnapshotFile, func(id restic.ID, err error) error {
if err != nil {
printer.E("unable to remove %v/%v from the repository\n", restic.SnapshotFile, id)
} else {
printer.VV("removed %v/%v\n", restic.SnapshotFile, id)
}
return nil
}, bar)
bar.Done()
if err != nil {
return err
}
} else {
if !gopts.JSON {
Printf("Would have removed the following snapshots:\n%v\n\n", removeSnIDs)
}
printer.P("Would have removed the following snapshots:\n%v\n\n", removeSnIDs)
}
}
@@ -294,15 +324,13 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
}
if len(removeSnIDs) > 0 && opts.Prune {
if !gopts.JSON {
if opts.DryRun {
Verbosef("%d snapshots would be removed, running prune dry run\n", len(removeSnIDs))
} else {
Verbosef("%d snapshots have been removed, running prune\n", len(removeSnIDs))
}
if opts.DryRun {
printer.P("%d snapshots would be removed, running prune dry run\n", len(removeSnIDs))
} else {
printer.P("%d snapshots have been removed, running prune\n", len(removeSnIDs))
}
pruneOptions.DryRun = opts.DryRun
return runPruneWithRepo(ctx, pruneOptions, gopts, repo, removeSnIDs)
return runPruneWithRepo(ctx, pruneOptions, gopts, repo, removeSnIDs, term)
}
return nil
@@ -310,23 +338,47 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
// ForgetGroup helps to print what is forgotten in JSON.
type ForgetGroup struct {
Tags []string `json:"tags"`
Host string `json:"host"`
Paths []string `json:"paths"`
Keep []Snapshot `json:"keep"`
Remove []Snapshot `json:"remove"`
Reasons []restic.KeepReason `json:"reasons"`
Tags []string `json:"tags"`
Host string `json:"host"`
Paths []string `json:"paths"`
Keep []Snapshot `json:"keep"`
Remove []Snapshot `json:"remove"`
Reasons []KeepReason `json:"reasons"`
}
func addJSONSnapshots(js *[]Snapshot, list restic.Snapshots) {
func asJSONSnapshots(list restic.Snapshots) []Snapshot {
var resultList []Snapshot
for _, sn := range list {
k := Snapshot{
Snapshot: sn,
ID: sn.ID(),
ShortID: sn.ID().Str(),
}
*js = append(*js, k)
resultList = append(resultList, k)
}
return resultList
}
// KeepReason helps to print KeepReasons as JSON with Snapshots with their ID included.
type KeepReason struct {
Snapshot Snapshot `json:"snapshot"`
Matches []string `json:"matches"`
}
func asJSONKeeps(list []restic.KeepReason) []KeepReason {
var resultList []KeepReason
for _, keep := range list {
k := KeepReason{
Snapshot: Snapshot{
Snapshot: keep.Snapshot,
ID: keep.Snapshot.ID(),
ShortID: keep.Snapshot.ID().Str(),
},
Matches: keep.Matches,
}
resultList = append(resultList, k)
}
return resultList
}
func printJSONForget(stdout io.Writer, forgets []*ForgetGroup) error {

View File

@@ -2,15 +2,65 @@ package main
import (
"context"
"path/filepath"
"strings"
"testing"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/termstatus"
)
func testRunForget(t testing.TB, gopts GlobalOptions, args ...string) {
opts := ForgetOptions{}
func testRunForgetMayFail(gopts GlobalOptions, opts ForgetOptions, args ...string) error {
pruneOpts := PruneOptions{
MaxUnused: "5%",
}
rtest.OK(t, runForget(context.TODO(), opts, pruneOpts, gopts, args))
return withTermStatus(gopts, func(ctx context.Context, term *termstatus.Terminal) error {
return runForget(context.TODO(), opts, pruneOpts, gopts, term, args)
})
}
func testRunForget(t testing.TB, gopts GlobalOptions, opts ForgetOptions, args ...string) {
rtest.OK(t, testRunForgetMayFail(gopts, opts, args...))
}
func TestRunForgetSafetyNet(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
testSetupBackupData(t, env)
opts := BackupOptions{
Host: "example",
}
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9")}, opts, env.gopts)
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9")}, opts, env.gopts)
testListSnapshots(t, env.gopts, 2)
// --keep-tags invalid
err := testRunForgetMayFail(env.gopts, ForgetOptions{
KeepTags: restic.TagLists{restic.TagList{"invalid"}},
GroupBy: restic.SnapshotGroupByOptions{Host: true, Path: true},
})
rtest.Assert(t, strings.Contains(err.Error(), `refusing to delete last snapshot of snapshot group "host example, path`), "wrong error message got %v", err)
// disallow `forget --unsafe-allow-remove-all`
err = testRunForgetMayFail(env.gopts, ForgetOptions{
UnsafeAllowRemoveAll: true,
})
rtest.Assert(t, strings.Contains(err.Error(), `--unsafe-allow-remove-all is not allowed unless a snapshot filter option is specified`), "wrong error message got %v", err)
// disallow `forget` without options
err = testRunForgetMayFail(env.gopts, ForgetOptions{})
rtest.Assert(t, strings.Contains(err.Error(), `no policy was specified, no snapshots will be removed`), "wrong error message got %v", err)
// `forget --host example --unsafe-allow-remove-all` should work
testRunForget(t, env.gopts, ForgetOptions{
UnsafeAllowRemoveAll: true,
GroupBy: restic.SnapshotGroupByOptions{Host: true, Path: true},
SnapshotFilter: restic.SnapshotFilter{
Hosts: []string{opts.Host},
},
})
testListSnapshots(t, env.gopts, 0)
}

View File

@@ -18,7 +18,8 @@ and the auto-completion files for bash, fish and zsh).
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
`,
DisableAutoGenTag: true,
RunE: func(_ *cobra.Command, args []string) error {

View File

@@ -23,7 +23,8 @@ The "init" command initializes a new repository.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -80,7 +81,7 @@ func runInit(ctx context.Context, opts InitOptions, gopts GlobalOptions, args []
return err
}
gopts.password, err = ReadPasswordTwice(gopts,
gopts.password, err = ReadPasswordTwice(ctx, gopts,
"enter password for new repository: ",
"enter password again: ")
if err != nil {
@@ -131,7 +132,7 @@ func runInit(ctx context.Context, opts InitOptions, gopts GlobalOptions, args []
func maybeReadChunkerPolynomial(ctx context.Context, opts InitOptions, gopts GlobalOptions) (*chunker.Pol, error) {
if opts.CopyChunkerParameters {
otherGopts, _, err := fillSecondaryGlobalOpts(opts.secondaryRepoOptions, gopts, "secondary")
otherGopts, _, err := fillSecondaryGlobalOpts(ctx, opts.secondaryRepoOptions, gopts, "secondary")
if err != nil {
return nil, err
}

View File

@@ -3,12 +3,11 @@ package main
import (
"context"
"fmt"
"os"
"strings"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/repository"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
var cmdKeyAdd = &cobra.Command{
@@ -20,29 +19,36 @@ The "add" sub-command creates a new key and validates the key. Returns the new k
EXIT STATUS
===========
Exit status is 0 if the command is successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
return runKeyAdd(cmd.Context(), globalOptions, keyAddOpts, args)
},
}
type KeyAddOptions struct {
NewPasswordFile string
Username string
Hostname string
NewPasswordFile string
InsecureNoPassword bool
Username string
Hostname string
}
var keyAddOpts KeyAddOptions
func (opts *KeyAddOptions) Add(flags *pflag.FlagSet) {
flags.StringVarP(&opts.NewPasswordFile, "new-password-file", "", "", "`file` from which to read the new password")
flags.BoolVar(&opts.InsecureNoPassword, "new-insecure-no-password", false, "add an empty password for the repository (insecure)")
flags.StringVarP(&opts.Username, "user", "", "", "the username for new key")
flags.StringVarP(&opts.Hostname, "host", "", "", "the hostname for new key")
}
func init() {
cmdKey.AddCommand(cmdKeyAdd)
flags := cmdKeyAdd.Flags()
flags.StringVarP(&keyAddOpts.NewPasswordFile, "new-password-file", "", "", "`file` from which to read the new password")
flags.StringVarP(&keyAddOpts.Username, "user", "", "", "the username for new key")
flags.StringVarP(&keyAddOpts.Hostname, "host", "", "", "the hostname for new key")
var keyAddOpts KeyAddOptions
keyAddOpts.Add(cmdKeyAdd.Flags())
cmdKeyAdd.RunE = func(cmd *cobra.Command, args []string) error {
return runKeyAdd(cmd.Context(), globalOptions, keyAddOpts, args)
}
}
func runKeyAdd(ctx context.Context, gopts GlobalOptions, opts KeyAddOptions, args []string) error {
@@ -50,22 +56,17 @@ func runKeyAdd(ctx context.Context, gopts GlobalOptions, opts KeyAddOptions, arg
return fmt.Errorf("the key add command expects no arguments, only options - please see `restic help key add` for usage and flags")
}
repo, err := OpenRepository(ctx, gopts)
if err != nil {
return err
}
lock, ctx, err := lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
ctx, repo, unlock, err := openWithAppendLock(ctx, gopts, false)
if err != nil {
return err
}
defer unlock()
return addKey(ctx, repo, gopts, opts)
}
func addKey(ctx context.Context, repo *repository.Repository, gopts GlobalOptions, opts KeyAddOptions) error {
pw, err := getNewPassword(gopts, opts.NewPasswordFile)
pw, err := getNewPassword(ctx, gopts, opts.NewPasswordFile, opts.InsecureNoPassword)
if err != nil {
return err
}
@@ -88,33 +89,41 @@ func addKey(ctx context.Context, repo *repository.Repository, gopts GlobalOption
// testKeyNewPassword is used to set a new password during integration testing.
var testKeyNewPassword string
func getNewPassword(gopts GlobalOptions, newPasswordFile string) (string, error) {
func getNewPassword(ctx context.Context, gopts GlobalOptions, newPasswordFile string, insecureNoPassword bool) (string, error) {
if testKeyNewPassword != "" {
return testKeyNewPassword, nil
}
if insecureNoPassword {
if newPasswordFile != "" {
return "", fmt.Errorf("only either --new-password-file or --new-insecure-no-password may be specified")
}
return "", nil
}
if newPasswordFile != "" {
return loadPasswordFromFile(newPasswordFile)
password, err := loadPasswordFromFile(newPasswordFile)
if err != nil {
return "", err
}
if password == "" {
return "", fmt.Errorf("an empty password is not allowed by default. Pass the flag `--new-insecure-no-password` to restic to disable this check")
}
return password, nil
}
// Since we already have an open repository, temporary remove the password
// to prompt the user for the passwd.
newopts := gopts
newopts.password = ""
// empty passwords are already handled above
newopts.InsecureNoPassword = false
return ReadPasswordTwice(newopts,
return ReadPasswordTwice(ctx, newopts,
"enter new password: ",
"enter password again: ")
}
func loadPasswordFromFile(pwdFile string) (string, error) {
s, err := os.ReadFile(pwdFile)
if os.IsNotExist(err) {
return "", errors.Fatalf("%s does not exist", pwdFile)
}
return strings.TrimSpace(string(s)), errors.Wrap(err, "Readfile")
}
func switchToNewKeyAndRemoveIfBroken(ctx context.Context, repo *repository.Repository, key *repository.Key, pw string) error {
// Verify new key to make sure it really works. A broken key can render the
// whole repository inaccessible

View File

@@ -3,6 +3,8 @@ package main
import (
"bufio"
"context"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
@@ -109,6 +111,43 @@ func TestKeyAddRemove(t *testing.T) {
testRunKeyAddNewKeyUserHost(t, env.gopts)
}
func TestKeyAddInvalid(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
testRunInit(t, env.gopts)
err := runKeyAdd(context.TODO(), env.gopts, KeyAddOptions{
NewPasswordFile: "some-file",
InsecureNoPassword: true,
}, []string{})
rtest.Assert(t, strings.Contains(err.Error(), "only either"), "unexpected error message, got %q", err)
pwfile := filepath.Join(t.TempDir(), "pwfile")
rtest.OK(t, os.WriteFile(pwfile, []byte{}, 0o666))
err = runKeyAdd(context.TODO(), env.gopts, KeyAddOptions{
NewPasswordFile: pwfile,
}, []string{})
rtest.Assert(t, strings.Contains(err.Error(), "an empty password is not allowed by default"), "unexpected error message, got %q", err)
}
func TestKeyAddEmpty(t *testing.T) {
env, cleanup := withTestEnvironment(t)
// must list keys more than once
env.gopts.backendTestHook = nil
defer cleanup()
testRunInit(t, env.gopts)
rtest.OK(t, runKeyAdd(context.TODO(), env.gopts, KeyAddOptions{
InsecureNoPassword: true,
}, []string{}))
env.gopts.password = ""
env.gopts.InsecureNoPassword = true
testRunCheck(t, env.gopts)
}
type emptySaveBackend struct {
backend.Backend
}

View File

@@ -23,7 +23,10 @@ used to access the repository.
EXIT STATUS
===========
Exit status is 0 if the command is successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -40,19 +43,11 @@ func runKeyList(ctx context.Context, gopts GlobalOptions, args []string) error {
return fmt.Errorf("the key list command expects no arguments, only options - please see `restic help key list` for usage and flags")
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
if !gopts.NoLock {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
return listKeys(ctx, repo, gopts)
}
@@ -61,6 +56,7 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions
type keyInfo struct {
Current bool `json:"current"`
ID string `json:"id"`
ShortID string `json:"-"`
UserName string `json:"userName"`
HostName string `json:"hostName"`
Created string `json:"created"`
@@ -78,7 +74,8 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions
key := keyInfo{
Current: id == s.KeyID(),
ID: id.Str(),
ID: id.String(),
ShortID: id.Str(),
UserName: k.Username,
HostName: k.Hostname,
Created: k.Created.Local().Format(TimeFormat),
@@ -99,7 +96,7 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions
}
tab := table.New()
tab.AddColumn(" ID", "{{if .Current}}*{{else}} {{end}}{{ .ID }}")
tab.AddColumn(" ID", "{{if .Current}}*{{else}} {{end}}{{ .ShortID }}")
tab.AddColumn("User", "{{ .UserName }}")
tab.AddColumn("Host", "{{ .HostName }}")
tab.AddColumn("Created", "{{ .Created }}")

View File

@@ -19,27 +19,26 @@ Returns the new key ID.
EXIT STATUS
===========
Exit status is 0 if the command is successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
return runKeyPasswd(cmd.Context(), globalOptions, keyPasswdOpts, args)
},
}
type KeyPasswdOptions struct {
KeyAddOptions
}
var keyPasswdOpts KeyPasswdOptions
func init() {
cmdKey.AddCommand(cmdKeyPasswd)
flags := cmdKeyPasswd.Flags()
flags.StringVarP(&keyPasswdOpts.NewPasswordFile, "new-password-file", "", "", "`file` from which to read the new password")
flags.StringVarP(&keyPasswdOpts.Username, "user", "", "", "the username for new key")
flags.StringVarP(&keyPasswdOpts.Hostname, "host", "", "", "the hostname for new key")
var keyPasswdOpts KeyPasswdOptions
keyPasswdOpts.KeyAddOptions.Add(cmdKeyPasswd.Flags())
cmdKeyPasswd.RunE = func(cmd *cobra.Command, args []string) error {
return runKeyPasswd(cmd.Context(), globalOptions, keyPasswdOpts, args)
}
}
func runKeyPasswd(ctx context.Context, gopts GlobalOptions, opts KeyPasswdOptions, args []string) error {
@@ -47,22 +46,17 @@ func runKeyPasswd(ctx context.Context, gopts GlobalOptions, opts KeyPasswdOption
return fmt.Errorf("the key passwd command expects no arguments, only options - please see `restic help key passwd` for usage and flags")
}
repo, err := OpenRepository(ctx, gopts)
if err != nil {
return err
}
lock, ctx, err := lockRepoExclusive(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, false)
if err != nil {
return err
}
defer unlock()
return changePassword(ctx, repo, gopts, opts)
}
func changePassword(ctx context.Context, repo *repository.Repository, gopts GlobalOptions, opts KeyPasswdOptions) error {
pw, err := getNewPassword(gopts, opts.NewPasswordFile)
pw, err := getNewPassword(ctx, gopts, opts.NewPasswordFile, opts.InsecureNoPassword)
if err != nil {
return err
}

View File

@@ -20,7 +20,10 @@ removing the current key being used to access the repository.
EXIT STATUS
===========
Exit status is 0 if the command is successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -37,20 +40,13 @@ func runKeyRemove(ctx context.Context, gopts GlobalOptions, args []string) error
return fmt.Errorf("key remove expects one argument as the key id")
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, false)
if err != nil {
return err
}
defer unlock()
lock, ctx, err := lockRepoExclusive(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
idPrefix := args[0]
return deleteKey(ctx, repo, idPrefix)
return deleteKey(ctx, repo, args[0])
}
func deleteKey(ctx context.Context, repo *repository.Repository, idPrefix string) error {

View File

@@ -4,7 +4,7 @@ import (
"context"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/index"
"github.com/restic/restic/internal/repository/index"
"github.com/restic/restic/internal/restic"
"github.com/spf13/cobra"
@@ -19,7 +19,10 @@ The "list" command allows listing objects in the repository based on type.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -36,19 +39,11 @@ func runList(ctx context.Context, gopts GlobalOptions, args []string) error {
return errors.Fatal("type not specified")
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock || args[0] == "locks")
if err != nil {
return err
}
if !gopts.NoLock && args[0] != "locks" {
var lock *restic.Lock
lock, ctx, err = lockRepo(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock)
if err != nil {
return err
}
}
defer unlock()
var t restic.FileType
switch args[0] {
@@ -67,10 +62,9 @@ func runList(ctx context.Context, gopts GlobalOptions, args []string) error {
if err != nil {
return err
}
idx.Each(ctx, func(blobs restic.PackedBlob) {
return idx.Each(ctx, func(blobs restic.PackedBlob) {
Printf("%v %v\n", blobs.Type, blobs.ID)
})
return nil
})
default:
return errors.Fatal("invalid type")

View File

@@ -39,7 +39,10 @@ a path separator); paths use the forward slash '/' as separator.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -71,7 +74,7 @@ func init() {
type lsPrinter interface {
Snapshot(sn *restic.Snapshot)
Node(path string, node *restic.Node)
Node(path string, node *restic.Node, isPrefixDirectory bool)
LeaveDir(path string)
Close()
}
@@ -83,16 +86,18 @@ type jsonLsPrinter struct {
func (p *jsonLsPrinter) Snapshot(sn *restic.Snapshot) {
type lsSnapshot struct {
*restic.Snapshot
ID *restic.ID `json:"id"`
ShortID string `json:"short_id"`
StructType string `json:"struct_type"` // "snapshot"
ID *restic.ID `json:"id"`
ShortID string `json:"short_id"`
MessageType string `json:"message_type"` // "snapshot"
StructType string `json:"struct_type"` // "snapshot", deprecated
}
err := p.enc.Encode(lsSnapshot{
Snapshot: sn,
ID: sn.ID(),
ShortID: sn.ID().Str(),
StructType: "snapshot",
Snapshot: sn,
ID: sn.ID(),
ShortID: sn.ID().Str(),
MessageType: "snapshot",
StructType: "snapshot",
})
if err != nil {
Warnf("JSON encode failed: %v\n", err)
@@ -100,7 +105,10 @@ func (p *jsonLsPrinter) Snapshot(sn *restic.Snapshot) {
}
// Print node in our custom JSON format, followed by a newline.
func (p *jsonLsPrinter) Node(path string, node *restic.Node) {
func (p *jsonLsPrinter) Node(path string, node *restic.Node, isPrefixDirectory bool) {
if isPrefixDirectory {
return
}
err := lsNodeJSON(p.enc, path, node)
if err != nil {
Warnf("JSON encode failed: %v\n", err)
@@ -121,7 +129,8 @@ func lsNodeJSON(enc *json.Encoder, path string, node *restic.Node) error {
AccessTime time.Time `json:"atime,omitempty"`
ChangeTime time.Time `json:"ctime,omitempty"`
Inode uint64 `json:"inode,omitempty"`
StructType string `json:"struct_type"` // "node"
MessageType string `json:"message_type"` // "node"
StructType string `json:"struct_type"` // "node", deprecated
size uint64 // Target for Size pointer.
}{
@@ -137,6 +146,7 @@ func lsNodeJSON(enc *json.Encoder, path string, node *restic.Node) error {
AccessTime: node.AccessTime,
ChangeTime: node.ChangeTime,
Inode: node.Inode,
MessageType: "node",
StructType: "node",
}
// Always print size for regular files, even when empty,
@@ -168,7 +178,7 @@ func (p *ncduLsPrinter) Snapshot(sn *restic.Snapshot) {
Warnf("JSON encode failed: %v\n", err)
}
p.depth++
fmt.Fprintf(p.out, "[%d, %d, %s", NcduMajorVer, NcduMinorVer, string(snapshotBytes))
fmt.Fprintf(p.out, "[%d, %d, %s, [{\"name\":\"/\"}", NcduMajorVer, NcduMinorVer, string(snapshotBytes))
}
func lsNcduNode(_ string, node *restic.Node) ([]byte, error) {
@@ -186,10 +196,13 @@ func lsNcduNode(_ string, node *restic.Node) ([]byte, error) {
Mtime int64 `json:"mtime"`
}
const blockSize = 512
outNode := NcduNode{
Name: node.Name,
Asize: node.Size,
Dsize: node.Size,
Name: node.Name,
Asize: node.Size,
// round up to nearest full blocksize
Dsize: (node.Size + blockSize - 1) / blockSize * blockSize,
Dev: node.DeviceID,
Ino: node.Inode,
NLink: node.Links,
@@ -209,11 +222,15 @@ func lsNcduNode(_ string, node *restic.Node) ([]byte, error) {
if node.Mode&os.ModeSticky != 0 {
outNode.Mode |= 0o1000
}
if outNode.Mtime < 0 {
// ncdu does not allow negative times
outNode.Mtime = 0
}
return json.Marshal(outNode)
}
func (p *ncduLsPrinter) Node(path string, node *restic.Node) {
func (p *ncduLsPrinter) Node(path string, node *restic.Node, _ bool) {
out, err := lsNcduNode(path, node)
if err != nil {
Warnf("JSON encode failed: %v\n", err)
@@ -233,7 +250,7 @@ func (p *ncduLsPrinter) LeaveDir(_ string) {
}
func (p *ncduLsPrinter) Close() {
fmt.Fprint(p.out, "\n]\n")
fmt.Fprint(p.out, "\n]\n]\n")
}
type textLsPrinter struct {
@@ -245,8 +262,10 @@ type textLsPrinter struct {
func (p *textLsPrinter) Snapshot(sn *restic.Snapshot) {
Verbosef("%v filtered by %v:\n", sn, p.dirs)
}
func (p *textLsPrinter) Node(path string, node *restic.Node) {
Printf("%s\n", formatNode(path, node, p.ListLong, p.HumanReadable))
func (p *textLsPrinter) Node(path string, node *restic.Node, isPrefixDirectory bool) {
if !isPrefixDirectory {
Printf("%s\n", formatNode(path, node, p.ListLong, p.HumanReadable))
}
}
func (p *textLsPrinter) LeaveDir(_ string) {}
@@ -305,10 +324,11 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
return false
}
repo, err := OpenRepository(ctx, gopts)
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
if err != nil {
return err
}
defer unlock()
snapshotLister, err := restic.MemorizeList(ctx, repo, restic.SnapshotFile)
if err != nil {
@@ -362,9 +382,11 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
return nil
}
printedDir := false
if withinDir(nodepath) {
// if we're within a dir, print the node
printer.Node(nodepath, node)
// if we're within a target path, print the node
printer.Node(nodepath, node, false)
printedDir = true
// if recursive listing is requested, signal the walker that it
// should continue walking recursively
@@ -376,12 +398,20 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
// if there's an upcoming match deeper in the tree (but we're not
// there yet), signal the walker to descend into any subdirs
if approachingMatchingTree(nodepath) {
// print node leading up to the target paths
if !printedDir {
printer.Node(nodepath, node, true)
}
return nil
}
// otherwise, signal the walker to not walk recursively into any
// subdirs
if node.Type == "dir" {
// immediately generate leaveDir if the directory is skipped
if printedDir {
printer.LeaveDir(nodepath)
}
return walker.ErrSkipNode
}
return nil
@@ -391,7 +421,7 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
ProcessNode: processNode,
LeaveDir: func(path string) {
// the root path `/` has no corresponding node and is thus also skipped by processNode
if withinDir(path) && path != "/" {
if path != "/" {
printer.LeaveDir(path)
}
},

Some files were not shown because too many files have changed in this diff Show More