diff --git a/pkg/tree/ops/deletebranch.go b/pkg/tree/ops/deletebranch.go index fe00ed30..6bae97c0 100644 --- a/pkg/tree/ops/deletebranch.go +++ b/pkg/tree/ops/deletebranch.go @@ -28,6 +28,9 @@ func DeleteBranch(ctx context.Context, e api.Entry, path *sdcpb.Path, owner stri // if the relativePath is present, we need to naviagate entry, err = NavigateSdcpbPath(ctx, e, path) if err != nil { + if errors.Is(err, ErrNavigateSdcpbPathNotFound) { + return nil + } return err } if entry == nil { diff --git a/pkg/tree/ops/navigatesdcpbpath.go b/pkg/tree/ops/navigatesdcpbpath.go index 64798ee6..09a079b0 100644 --- a/pkg/tree/ops/navigatesdcpbpath.go +++ b/pkg/tree/ops/navigatesdcpbpath.go @@ -2,6 +2,7 @@ package ops import ( "context" + "errors" "fmt" "github.com/sdcio/data-server/pkg/tree/api" @@ -10,9 +11,9 @@ import ( sdcpb "github.com/sdcio/sdc-protos/sdcpb" ) -var ( - ErrNavigateSdcpbPathNotFound = fmt.Errorf("path not found in tree") -) +// ErrNavigateSdcpbPathNotFound is returned (wrapped) when tree navigation cannot +// resolve a path segment. Delete-by-path callers (e.g. DeleteBranch) treat this as idempotent. +var ErrNavigateSdcpbPathNotFound = errors.New("path not found in tree") func NavigateSdcpbPath(ctx context.Context, e api.Entry, path *sdcpb.Path) (api.Entry, error) { if e == nil { diff --git a/pkg/tree/sharedEntryAttributes_test.go b/pkg/tree/sharedEntryAttributes_test.go index f5c333a3..5424d623 100644 --- a/pkg/tree/sharedEntryAttributes_test.go +++ b/pkg/tree/sharedEntryAttributes_test.go @@ -198,6 +198,8 @@ func Test_sharedEntryAttributes_DeleteSubtree(t *testing.T) { sharedEntryAttributes func(t *testing.T) api.Entry args args wantErr bool + // skipLeafCheck: path may not exist; idempotent DeleteBranch returns nil without deleting anything. + skipLeafCheck bool }{ { name: "one", @@ -275,7 +277,8 @@ func Test_sharedEntryAttributes_DeleteSubtree(t *testing.T) { }, owner: owner1, }, - wantErr: true, + wantErr: false, + skipLeafCheck: true, }, } for _, tt := range tests { @@ -289,6 +292,9 @@ func Test_sharedEntryAttributes_DeleteSubtree(t *testing.T) { if tt.wantErr { return } + if tt.skipLeafCheck { + return + } e, err := ops.NavigateSdcpbPath(ctx, s, tt.args.relativePath) if err != nil { t.Error(err)