Arlodotexe / OwlCore.Storage

The most flexible file system abstraction, ever. Built in partnership with the UWP Community.
16 stars 4 forks source link

Copying/moving folders #60

Open itsWindows11 opened 5 months ago

itsWindows11 commented 5 months ago

There doesn't seem to be a way to copy/move a directory through the abstraction, only files in an IModifiableFolder. This is a necessary feature to complete the basic file management capabilities for the abstraction, and to have it integrated in Files.

Most (if not all) storage implementations we've implemented or are planning to implement already support recursively moving a folder to another folder.

Arlodotexe commented 5 months ago

Correct, this is by design due to some pitfalls we recognized here.

We can't do recursive operations safely from within the abstraction in order to provide our usual "fallback" extension method implementation. The abstraction provides an API surface of "storage primitives" such as create, enumerate, delete, read/write. But handling results and catching errors when calling these must happen on a layer just above these storage primitives, usually the library consumer or inbox extensions.

Only the consumer knows what kind of handling/catching to do for the implementations they have and the app they're making. Recursion not only hides the place where you'd do custom logic and error handling for each item, we have no way to know what the best method to crawl the storage graph even is. See https://github.com/Arlodotexe/OwlCore.Storage/issues/35#issuecomment-1505902464.

We can create optional interfaces for this, but it's a much more difficult task to write a fallback that works for all possible implementations because recursion is involved and storage graphs don't need to be trees or even DAGs.

The solution to this would be complicated and likely need more specialization than we can account for without adding another layer of abstraction-- could be as simple as a callback or as complex as some parts of linq, or (less ideally) a separate interface entirely, like the suggested solution so far in #35.

I'm open to thoughts and ideas.