From 4b5fe3adad013b5e0bbf107e560968ea94d2772d Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 9 Feb 2021 10:12:23 +0000 Subject: [PATCH] delete,rmdirs: make --rmdirs obey the filters See: https://forum.rclone.org/t/a-problem-with-rclone-delete-from-list/22143 --- fs/operations/operations.go | 13 +++++++++-- fs/operations/operations_test.go | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/fs/operations/operations.go b/fs/operations/operations.go index 6e198c4bf..ab6381611 100644 --- a/fs/operations/operations.go +++ b/fs/operations/operations.go @@ -26,6 +26,7 @@ import ( "github.com/rclone/rclone/fs/accounting" "github.com/rclone/rclone/fs/cache" "github.com/rclone/rclone/fs/config" + "github.com/rclone/rclone/fs/filter" "github.com/rclone/rclone/fs/fserrors" "github.com/rclone/rclone/fs/fshttp" "github.com/rclone/rclone/fs/hash" @@ -1302,11 +1303,14 @@ func PublicLink(ctx context.Context, f fs.Fs, remote string, expire fs.Duration, // Rmdirs removes any empty directories (or directories only // containing empty directories) under f, including f. +// +// Rmdirs obeys the filters func Rmdirs(ctx context.Context, f fs.Fs, dir string, leaveRoot bool) error { ci := fs.GetConfig(ctx) + fi := filter.GetConfig(ctx) dirEmpty := make(map[string]bool) dirEmpty[dir] = !leaveRoot - err := walk.Walk(ctx, f, dir, true, ci.MaxDepth, func(dirPath string, entries fs.DirEntries, err error) error { + err := walk.Walk(ctx, f, dir, false, ci.MaxDepth, func(dirPath string, entries fs.DirEntries, err error) error { if err != nil { err = fs.CountError(err) fs.Errorf(f, "Failed to list %q: %v", dirPath, err) @@ -1353,7 +1357,12 @@ func Rmdirs(ctx context.Context, f fs.Fs, dir string, leaveRoot bool) error { sort.Strings(toDelete) for i := len(toDelete) - 1; i >= 0; i-- { dir := toDelete[i] - err := TryRmdir(ctx, f, dir) + // If a filter matches the directory then that + // directory is a candidate for deletion + if !fi.Include(dir+"/", 0, time.Now()) { + continue + } + err = TryRmdir(ctx, f, dir) if err != nil { err = fs.CountError(err) fs.Errorf(dir, "Failed to rmdir: %v", err) diff --git a/fs/operations/operations_test.go b/fs/operations/operations_test.go index 2421b5b9b..76172952b 100644 --- a/fs/operations/operations_test.go +++ b/fs/operations/operations_test.go @@ -651,6 +651,46 @@ func TestRmdirsLeaveRoot(t *testing.T) { ) } +func TestRmdirsWithFilter(t *testing.T) { + ctx := context.Background() + ctx, fi := filter.AddConfig(ctx) + require.NoError(t, fi.AddRule("+ /A1/B1/**")) + require.NoError(t, fi.AddRule("- *")) + r := fstest.NewRun(t) + defer r.Finalise() + r.Mkdir(ctx, r.Fremote) + + r.ForceMkdir(ctx, r.Fremote) + + require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A1")) + require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A1/B1")) + require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A1/B1/C1")) + + fstest.CheckListingWithPrecision( + t, + r.Fremote, + []fstest.Item{}, + []string{ + "A1", + "A1/B1", + "A1/B1/C1", + }, + fs.GetModifyWindow(ctx, r.Fremote), + ) + + require.NoError(t, operations.Rmdirs(ctx, r.Fremote, "", false)) + + fstest.CheckListingWithPrecision( + t, + r.Fremote, + []fstest.Item{}, + []string{ + "A1", + }, + fs.GetModifyWindow(ctx, r.Fremote), + ) +} + func TestCopyURL(t *testing.T) { ctx := context.Background() ci := fs.GetConfig(ctx)