forked from TrueCloudLab/restic
commit
639326903c
22 changed files with 55 additions and 55 deletions
|
@ -1,6 +1,6 @@
|
|||
Enhancement: Support repositories with empty password
|
||||
|
||||
Restic refused to create or operate on repositories with an emtpy password.
|
||||
Restic refused to create or operate on repositories with an empty password.
|
||||
Using the new option `--insecure-no-password` it is now possible to disable
|
||||
this check. Restic will not prompt for a password when using this option.
|
||||
For security reasons, the option must always be specified when operating on
|
||||
|
@ -10,8 +10,8 @@ Specifying `--insecure-no-password` while also passing a password to restic
|
|||
via a CLI option or via environment variable results in an error.
|
||||
|
||||
The `init` and `copy` command also support the option `--from-insecure-no-password`
|
||||
which applies to the source repository. The `key add` and `key passwd` comands
|
||||
include the `--new-insecure-no-password` option to add or set an emtpy password.
|
||||
which applies to the source repository. The `key add` and `key passwd` commands
|
||||
include the `--new-insecure-no-password` option to add or set an empty password.
|
||||
|
||||
https://github.com/restic/restic/issues/1786
|
||||
https://github.com/restic/restic/issues/4326
|
||||
|
|
|
@ -54,7 +54,7 @@ func TestRunForgetSafetyNet(t *testing.T) {
|
|||
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-remmove-all` should work
|
||||
// `forget --host example --unsafe-allow-remove-all` should work
|
||||
testRunForget(t, env.gopts, ForgetOptions{
|
||||
UnsafeAllowRemoveAll: true,
|
||||
GroupBy: restic.SnapshotGroupByOptions{Host: true, Path: true},
|
||||
|
|
|
@ -51,9 +51,9 @@ type PruneOptions struct {
|
|||
MaxRepackSize string
|
||||
MaxRepackBytes uint64
|
||||
|
||||
RepackCachableOnly bool
|
||||
RepackSmall bool
|
||||
RepackUncompressed bool
|
||||
RepackCacheableOnly bool
|
||||
RepackSmall bool
|
||||
RepackUncompressed bool
|
||||
}
|
||||
|
||||
var pruneOptions PruneOptions
|
||||
|
@ -70,7 +70,7 @@ func addPruneOptions(c *cobra.Command, pruneOptions *PruneOptions) {
|
|||
f := c.Flags()
|
||||
f.StringVar(&pruneOptions.MaxUnused, "max-unused", "5%", "tolerate given `limit` of unused data (absolute value in bytes with suffixes k/K, m/M, g/G, t/T, a value in % or the word 'unlimited')")
|
||||
f.StringVar(&pruneOptions.MaxRepackSize, "max-repack-size", "", "maximum `size` to repack (allowed suffixes: k/K, m/M, g/G, t/T)")
|
||||
f.BoolVar(&pruneOptions.RepackCachableOnly, "repack-cacheable-only", false, "only repack packs which are cacheable")
|
||||
f.BoolVar(&pruneOptions.RepackCacheableOnly, "repack-cacheable-only", false, "only repack packs which are cacheable")
|
||||
f.BoolVar(&pruneOptions.RepackSmall, "repack-small", false, "repack pack files below 80% of target pack size")
|
||||
f.BoolVar(&pruneOptions.RepackUncompressed, "repack-uncompressed", false, "repack all uncompressed data")
|
||||
}
|
||||
|
@ -183,9 +183,9 @@ func runPruneWithRepo(ctx context.Context, opts PruneOptions, gopts GlobalOption
|
|||
MaxUnusedBytes: opts.maxUnusedBytes,
|
||||
MaxRepackBytes: opts.MaxRepackBytes,
|
||||
|
||||
RepackCachableOnly: opts.RepackCachableOnly,
|
||||
RepackSmall: opts.RepackSmall,
|
||||
RepackUncompressed: opts.RepackUncompressed,
|
||||
RepackCacheableOnly: opts.RepackCacheableOnly,
|
||||
RepackSmall: opts.RepackSmall,
|
||||
RepackUncompressed: opts.RepackUncompressed,
|
||||
}
|
||||
|
||||
plan, err := repository.PlanPrune(ctx, popts, repo, func(ctx context.Context, repo restic.Repository, usedBlobs restic.FindBlobSet) error {
|
||||
|
|
|
@ -51,8 +51,8 @@ func testPruneVariants(t *testing.T, unsafeNoSpaceRecovery bool) {
|
|||
testPrune(t, opts, checkOpts)
|
||||
})
|
||||
|
||||
t.Run("CachableOnly"+suffix, func(t *testing.T) {
|
||||
opts := PruneOptions{MaxUnused: "5%", RepackCachableOnly: true, unsafeRecovery: unsafeNoSpaceRecovery}
|
||||
t.Run("CacheableOnly"+suffix, func(t *testing.T) {
|
||||
opts := PruneOptions{MaxUnused: "5%", RepackCacheableOnly: true, unsafeRecovery: unsafeNoSpaceRecovery}
|
||||
checkOpts := CheckOptions{ReadData: true}
|
||||
testPrune(t, opts, checkOpts)
|
||||
})
|
||||
|
|
|
@ -81,9 +81,9 @@ func runSnapshots(ctx context.Context, opts SnapshotOptions, gopts GlobalOptions
|
|||
if opts.Last {
|
||||
// This branch should be removed in the same time
|
||||
// that --last.
|
||||
list = FilterLastestSnapshots(list, 1)
|
||||
list = FilterLatestSnapshots(list, 1)
|
||||
} else if opts.Latest > 0 {
|
||||
list = FilterLastestSnapshots(list, opts.Latest)
|
||||
list = FilterLatestSnapshots(list, opts.Latest)
|
||||
}
|
||||
sort.Sort(sort.Reverse(list))
|
||||
snapshotGroups[k] = list
|
||||
|
@ -126,11 +126,11 @@ func newFilterLastSnapshotsKey(sn *restic.Snapshot) filterLastSnapshotsKey {
|
|||
return filterLastSnapshotsKey{sn.Hostname, strings.Join(paths, "|")}
|
||||
}
|
||||
|
||||
// FilterLastestSnapshots filters a list of snapshots to only return
|
||||
// FilterLatestSnapshots filters a list of snapshots to only return
|
||||
// the limit last entries for each hostname and path. If the snapshot
|
||||
// contains multiple paths, they will be joined and treated as one
|
||||
// item.
|
||||
func FilterLastestSnapshots(list restic.Snapshots, limit int) restic.Snapshots {
|
||||
func FilterLatestSnapshots(list restic.Snapshots, limit int) restic.Snapshots {
|
||||
// Sort the snapshots so that the newer ones are listed first
|
||||
sort.SliceStable(list, func(i, j int) bool {
|
||||
return list[i].Time.After(list[j].Time)
|
||||
|
@ -307,7 +307,7 @@ type Snapshot struct {
|
|||
ShortID string `json:"short_id"`
|
||||
}
|
||||
|
||||
// SnapshotGroup helps to print SnaphotGroups as JSON with their GroupReasons included.
|
||||
// SnapshotGroup helps to print SnapshotGroups as JSON with their GroupReasons included.
|
||||
type SnapshotGroup struct {
|
||||
GroupKey restic.SnapshotGroupKey `json:"group_key"`
|
||||
Snapshots []Snapshot `json:"snapshots"`
|
||||
|
|
|
@ -34,12 +34,12 @@ func internalOpenWithLocked(ctx context.Context, gopts GlobalOptions, dryRun boo
|
|||
}
|
||||
|
||||
func openWithReadLock(ctx context.Context, gopts GlobalOptions, noLock bool) (context.Context, *repository.Repository, func(), error) {
|
||||
// TODO enfore read-only operations once the locking code has moved to the repository
|
||||
// TODO enforce read-only operations once the locking code has moved to the repository
|
||||
return internalOpenWithLocked(ctx, gopts, noLock, false)
|
||||
}
|
||||
|
||||
func openWithAppendLock(ctx context.Context, gopts GlobalOptions, dryRun bool) (context.Context, *repository.Repository, func(), error) {
|
||||
// TODO enfore non-exclusive operations once the locking code has moved to the repository
|
||||
// TODO enforce non-exclusive operations once the locking code has moved to the repository
|
||||
return internalOpenWithLocked(ctx, gopts, dryRun, false)
|
||||
}
|
||||
|
||||
|
|
|
@ -873,5 +873,5 @@ with an empty password, use the following command.
|
|||
|
||||
|
||||
The ``init`` and ``copy`` command also support the option ``--from-insecure-no-password``
|
||||
which applies to the source repository. The ``key add`` and ``key passwd`` comands
|
||||
include the ``--new-insecure-no-password`` option to add or set and emtpy password.
|
||||
which applies to the source repository. The ``key add`` and ``key passwd`` commands
|
||||
include the ``--new-insecure-no-password`` option to add or set and empty password.
|
||||
|
|
|
@ -71,7 +71,7 @@ some blobs in the repository, then please ask for help in the forum or our IRC
|
|||
channel. These errors are often caused by hardware problems which **must** be
|
||||
investigated and fixed. Otherwise, the backup will be damaged again and again.
|
||||
|
||||
Similarly, if a repository is repeatedly damaged, please open an `issue on Github
|
||||
Similarly, if a repository is repeatedly damaged, please open an `issue on GitHub
|
||||
<https://github.com/restic/restic/issues/new/choose>`_ as this could indicate a bug
|
||||
somewhere. Please include the check output and additional information that might
|
||||
help locate the problem.
|
||||
|
@ -102,7 +102,7 @@ remove data unexpectedly.
|
|||
Please take the time to understand what the commands described in the following
|
||||
do. If you are unsure, then ask for help in the forum or our IRC channel. Search
|
||||
whether your issue is already known and solved. Please take a look at the
|
||||
`forum`_ and `Github issues <https://github.com/restic/restic/issues>`_.
|
||||
`forum`_ and `GitHub issues <https://github.com/restic/restic/issues>`_.
|
||||
|
||||
|
||||
3. Repair the index
|
||||
|
|
4
internal/backend/cache/backend_test.go
vendored
4
internal/backend/cache/backend_test.go
vendored
|
@ -135,7 +135,7 @@ func TestOutOfBoundsAccess(t *testing.T) {
|
|||
|
||||
// load out of bounds
|
||||
err := wbe.Load(context.TODO(), h, 100, 100, func(rd io.Reader) error {
|
||||
t.Error("cache returned non-existant file section")
|
||||
t.Error("cache returned non-existent file section")
|
||||
return errors.New("broken")
|
||||
})
|
||||
test.Assert(t, strings.Contains(err.Error(), " is too short"), "expected too short error, got %v", err)
|
||||
|
@ -147,7 +147,7 @@ func TestOutOfBoundsAccess(t *testing.T) {
|
|||
|
||||
// start within bounds, but request too large chunk
|
||||
err = wbe.Load(context.TODO(), h, 100, 0, func(rd io.Reader) error {
|
||||
t.Error("cache returned non-existant file section")
|
||||
t.Error("cache returned non-existent file section")
|
||||
return errors.New("broken")
|
||||
})
|
||||
test.Assert(t, strings.Contains(err.Error(), " is too short"), "expected too short error, got %v", err)
|
||||
|
|
|
@ -79,14 +79,14 @@ func TestCacheGetOrCompute(t *testing.T) {
|
|||
return data1, nil
|
||||
})
|
||||
rtest.OK(t, err)
|
||||
rtest.Equals(t, &data1[0], &blob[0], "wrong buffer returend")
|
||||
rtest.Equals(t, &data1[0], &blob[0], "wrong buffer returned")
|
||||
|
||||
// now the buffer should be returned without calling the compute function
|
||||
blob, err = c.GetOrCompute(id1, func() ([]byte, error) {
|
||||
return nil, e
|
||||
})
|
||||
rtest.OK(t, err)
|
||||
rtest.Equals(t, &data1[0], &blob[0], "wrong buffer returend")
|
||||
rtest.Equals(t, &data1[0], &blob[0], "wrong buffer returned")
|
||||
|
||||
// check concurrency
|
||||
wg, _ := errgroup.WithContext(context.TODO())
|
||||
|
|
|
@ -29,7 +29,7 @@ func TempFile(dir, prefix string) (f *os.File, err error) {
|
|||
return f, nil
|
||||
}
|
||||
|
||||
// isNotSuported returns true if the error is caused by an unsupported file system feature.
|
||||
// isNotSupported returns true if the error is caused by an unsupported file system feature.
|
||||
func isNotSupported(err error) bool {
|
||||
if perr, ok := err.(*os.PathError); ok && perr.Err == syscall.ENOTSUP {
|
||||
return true
|
||||
|
|
|
@ -72,7 +72,7 @@ type LocalVss struct {
|
|||
var _ FS = &LocalVss{}
|
||||
|
||||
// parseMountPoints try to convert semicolon separated list of mount points
|
||||
// to map of lowercased volume GUID pathes. Mountpoints already in volume
|
||||
// to map of lowercased volume GUID paths. Mountpoints already in volume
|
||||
// GUID path format will be validated and normalized.
|
||||
func parseMountPoints(list string, msgError ErrorHandler) (volumes map[string]struct{}) {
|
||||
if list == "" {
|
||||
|
|
|
@ -128,7 +128,7 @@ func TestAssociatedSetWithExtendedIndex(t *testing.T) {
|
|||
mi.StorePack(blob2.PackID, []restic.Blob{blob2.Blob})
|
||||
test.OK(t, mi.SaveIndex(context.TODO(), &noopSaver{}))
|
||||
|
||||
// non-existant
|
||||
// non-existent
|
||||
test.Equals(t, false, bs.Has(of))
|
||||
// set
|
||||
bs.Set(of, 5)
|
||||
|
|
|
@ -156,7 +156,7 @@ func TestIndexMapFirstIndex(t *testing.T) {
|
|||
|
||||
for i := 1; i <= 400; i++ {
|
||||
r.Read(id[:])
|
||||
rtest.Equals(t, -1, m.firstIndex(id), "wrong firstIndex for nonexistant id")
|
||||
rtest.Equals(t, -1, m.firstIndex(id), "wrong firstIndex for nonexistent id")
|
||||
|
||||
m.add(id, 0, 0, 0, 0)
|
||||
idx := m.firstIndex(id)
|
||||
|
|
|
@ -25,9 +25,9 @@ type PruneOptions struct {
|
|||
MaxUnusedBytes func(used uint64) (unused uint64) // calculates the number of unused bytes after repacking, according to MaxUnused
|
||||
MaxRepackBytes uint64
|
||||
|
||||
RepackCachableOnly bool
|
||||
RepackSmall bool
|
||||
RepackUncompressed bool
|
||||
RepackCacheableOnly bool
|
||||
RepackSmall bool
|
||||
RepackUncompressed bool
|
||||
}
|
||||
|
||||
type PruneStats struct {
|
||||
|
@ -381,7 +381,7 @@ func decidePackAction(ctx context.Context, opts PruneOptions, repo *Repository,
|
|||
stats.Blobs.Remove += p.unusedBlobs
|
||||
stats.Size.Remove += p.unusedSize
|
||||
|
||||
case opts.RepackCachableOnly && p.tpe == restic.DataBlob:
|
||||
case opts.RepackCacheableOnly && p.tpe == restic.DataBlob:
|
||||
// if this is a data pack and --repack-cacheable-only is set => keep pack!
|
||||
stats.Packs.Keep++
|
||||
|
||||
|
|
|
@ -80,9 +80,9 @@ func TestPrune(t *testing.T) {
|
|||
{
|
||||
name: "cachableonly",
|
||||
opts: repository.PruneOptions{
|
||||
MaxRepackBytes: math.MaxUint64,
|
||||
MaxUnusedBytes: func(used uint64) (unused uint64) { return used / 20 },
|
||||
RepackCachableOnly: true,
|
||||
MaxRepackBytes: math.MaxUint64,
|
||||
MaxUnusedBytes: func(used uint64) (unused uint64) { return used / 20 },
|
||||
RepackCacheableOnly: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -228,7 +228,7 @@ func (node Node) restoreGenericAttributes(path string, warn func(msg string)) (e
|
|||
return errors.CombineErrors(errs...)
|
||||
}
|
||||
|
||||
// genericAttributesToWindowsAttrs converts the generic attributes map to a WindowsAttributes and also returns a string of unkown attributes that it could not convert.
|
||||
// genericAttributesToWindowsAttrs converts the generic attributes map to a WindowsAttributes and also returns a string of unknown attributes that it could not convert.
|
||||
func genericAttributesToWindowsAttrs(attrs map[GenericAttributeType]json.RawMessage) (windowsAttributes WindowsAttributes, unknownAttribs []GenericAttributeType, err error) {
|
||||
waValue := reflect.ValueOf(&windowsAttributes).Elem()
|
||||
unknownAttribs, err = genericAttributesToOSAttrs(attrs, reflect.TypeOf(windowsAttributes), &waValue, "windows")
|
||||
|
|
|
@ -70,7 +70,7 @@ func getNode(name string, fileType string, genericAttributes map[GenericAttribut
|
|||
func getWindowsAttr(t *testing.T, testPath string, node *Node) WindowsAttributes {
|
||||
windowsAttributes, unknownAttribs, err := genericAttributesToWindowsAttrs(node.GenericAttributes)
|
||||
test.OK(t, errors.Wrapf(err, "Error getting windows attr from generic attr: %s", testPath))
|
||||
test.Assert(t, len(unknownAttribs) == 0, "Unkown attribs found: %s for: %s", unknownAttribs, testPath)
|
||||
test.Assert(t, len(unknownAttribs) == 0, "Unknown attribs found: %s for: %s", unknownAttribs, testPath)
|
||||
return windowsAttributes
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ func TestNewGenericAttributeType(t *testing.T) {
|
|||
_, ua, err := genericAttributesToWindowsAttrs(node.GenericAttributes)
|
||||
test.OK(t, err)
|
||||
// Since this GenericAttribute is unknown to this version of the software, it will not get set on the file.
|
||||
test.Assert(t, len(ua) == 0, "Unkown attributes: %s found for path: %s", ua, testPath)
|
||||
test.Assert(t, len(ua) == 0, "Unknown attributes: %s found for path: %s", ua, testPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ type OverwriteBehavior int
|
|||
const (
|
||||
OverwriteAlways OverwriteBehavior = iota
|
||||
// OverwriteIfChanged is like OverwriteAlways except that it skips restoring the content
|
||||
// of files with matching size&mtime. Metatdata is always restored.
|
||||
// of files with matching size&mtime. Metadata is always restored.
|
||||
OverwriteIfChanged
|
||||
OverwriteIfNewer
|
||||
OverwriteNever
|
||||
|
|
|
@ -1162,7 +1162,7 @@ func TestRestoreIfChanged(t *testing.T) {
|
|||
rtest.Equals(t, origData, string(data), "expected original file content")
|
||||
} else {
|
||||
// restore should not have noticed the changed file content
|
||||
rtest.Equals(t, modData, string(data), "expeced modified file content")
|
||||
rtest.Equals(t, modData, string(data), "expected modified file content")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
restoreui "github.com/restic/restic/internal/ui/restore"
|
||||
)
|
||||
|
||||
func TestRestorerRestoreEmptyHardlinkedFileds(t *testing.T) {
|
||||
func TestRestorerRestoreEmptyHardlinkedFields(t *testing.T) {
|
||||
repo := repository.TestRepository(t)
|
||||
|
||||
sn, _ := saveSnapshot(t, repo, Snapshot{
|
||||
|
|
|
@ -356,29 +356,29 @@ func verifyFileAttributes(t *testing.T, mainFilePath string, attr FileAttributes
|
|||
rtest.OK(t, err)
|
||||
//Test positive and negative scenarios
|
||||
if attr.ReadOnly {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_READONLY != 0, "Expected read only attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_READONLY != 0, "Expected read only attribute.")
|
||||
} else {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_READONLY == 0, "Unexpected read only attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_READONLY == 0, "Unexpected read only attribute.")
|
||||
}
|
||||
if attr.Hidden {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_HIDDEN != 0, "Expected hidden attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_HIDDEN != 0, "Expected hidden attribute.")
|
||||
} else {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_HIDDEN == 0, "Unexpected hidden attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_HIDDEN == 0, "Unexpected hidden attribute.")
|
||||
}
|
||||
if attr.System {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_SYSTEM != 0, "Expected system attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_SYSTEM != 0, "Expected system attribute.")
|
||||
} else {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_SYSTEM == 0, "Unexpected system attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_SYSTEM == 0, "Unexpected system attribute.")
|
||||
}
|
||||
if attr.Archive {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ARCHIVE != 0, "Expected archive attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ARCHIVE != 0, "Expected archive attribute.")
|
||||
} else {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ARCHIVE == 0, "Unexpected archive attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ARCHIVE == 0, "Unexpected archive attribute.")
|
||||
}
|
||||
if attr.Encrypted {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ENCRYPTED != 0, "Expected encrypted attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ENCRYPTED != 0, "Expected encrypted attribute.")
|
||||
} else {
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ENCRYPTED == 0, "Unexpected encrypted attibute.")
|
||||
rtest.Assert(t, fileAttributes&windows.FILE_ATTRIBUTE_ENCRYPTED == 0, "Unexpected encrypted attribute.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue