mirror of
https://github.com/restic/restic.git
synced 2025-12-27 01:36:42 +00:00
Merge pull request #5183 from wplapper/cmd_prune
restic prune: selection of packs to repack based on size
This commit is contained in:
@@ -67,6 +67,9 @@ type PruneOptions struct {
|
||||
RepackCacheableOnly bool
|
||||
RepackSmall bool
|
||||
RepackUncompressed bool
|
||||
|
||||
SmallPackSize string
|
||||
SmallPackBytes uint64
|
||||
}
|
||||
|
||||
func (opts *PruneOptions) AddFlags(f *pflag.FlagSet) {
|
||||
@@ -81,6 +84,7 @@ func (opts *PruneOptions) AddLimitedFlags(f *pflag.FlagSet) {
|
||||
f.BoolVar(&opts.RepackCacheableOnly, "repack-cacheable-only", false, "only repack packs which are cacheable")
|
||||
f.BoolVar(&opts.RepackSmall, "repack-small", false, "repack pack files below 80% of target pack size")
|
||||
f.BoolVar(&opts.RepackUncompressed, "repack-uncompressed", false, "repack all uncompressed data")
|
||||
f.StringVar(&opts.SmallPackSize, "repack-smaller-than", "", "pack `below-limit` packfiles (allowed suffixes: k/K, m/M)")
|
||||
}
|
||||
|
||||
func verifyPruneOptions(opts *PruneOptions) error {
|
||||
@@ -139,6 +143,15 @@ func verifyPruneOptions(opts *PruneOptions) error {
|
||||
}
|
||||
}
|
||||
|
||||
if opts.SmallPackSize != "" {
|
||||
size, err := ui.ParseBytes(opts.SmallPackSize)
|
||||
if err != nil {
|
||||
return errors.Fatalf("invalid number of bytes %q for --repack-smaller-than: %v", opts.SmallPackSize, err)
|
||||
}
|
||||
opts.SmallPackBytes = uint64(size)
|
||||
opts.RepackSmall = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -194,6 +207,7 @@ func runPruneWithRepo(ctx context.Context, opts PruneOptions, gopts GlobalOption
|
||||
|
||||
MaxUnusedBytes: opts.maxUnusedBytes,
|
||||
MaxRepackBytes: opts.MaxRepackBytes,
|
||||
SmallPackBytes: opts.SmallPackBytes,
|
||||
|
||||
RepackCacheableOnly: opts.RepackCacheableOnly,
|
||||
RepackSmall: opts.RepackSmall,
|
||||
|
||||
@@ -13,14 +13,25 @@ import (
|
||||
)
|
||||
|
||||
func testRunPrune(t testing.TB, gopts GlobalOptions, opts PruneOptions) {
|
||||
t.Helper()
|
||||
rtest.OK(t, testRunPruneOutput(gopts, opts))
|
||||
}
|
||||
|
||||
func testRunPruneMustFail(t testing.TB, gopts GlobalOptions, opts PruneOptions) {
|
||||
t.Helper()
|
||||
err := testRunPruneOutput(gopts, opts)
|
||||
rtest.Assert(t, err != nil, "expected non nil error")
|
||||
}
|
||||
|
||||
func testRunPruneOutput(gopts GlobalOptions, opts PruneOptions) error {
|
||||
oldHook := gopts.backendTestHook
|
||||
gopts.backendTestHook = func(r backend.Backend) (backend.Backend, error) { return newListOnceBackend(r), nil }
|
||||
defer func() {
|
||||
gopts.backendTestHook = oldHook
|
||||
}()
|
||||
rtest.OK(t, withTermStatus(gopts, func(ctx context.Context, term *termstatus.Terminal) error {
|
||||
return withTermStatus(gopts, func(ctx context.Context, term *termstatus.Terminal) error {
|
||||
return runPrune(context.TODO(), opts, gopts, term)
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
func TestPrune(t *testing.T) {
|
||||
@@ -237,3 +248,20 @@ func testEdgeCaseRepo(t *testing.T, tarfile string, optionsCheck CheckOptions, o
|
||||
"prune should have reported an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPruneRepackSmallerThanSmoke(t *testing.T) {
|
||||
env, cleanup := withTestEnvironment(t)
|
||||
defer cleanup()
|
||||
|
||||
// the implementation is already unit tested, so just check that
|
||||
// the setting reaches its goal
|
||||
createPrunableRepo(t, env)
|
||||
testRunPrune(t, env.gopts, PruneOptions{
|
||||
SmallPackSize: "4M",
|
||||
MaxUnused: "5%",
|
||||
})
|
||||
testRunPruneMustFail(t, env.gopts, PruneOptions{
|
||||
SmallPackSize: "500M",
|
||||
MaxUnused: "5%",
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user