This PR is the final change, where all backends are now purely implemented with async interfaces.
The code changes here replace the LIST call with an async version. This affect all backends (and then some) but the changes are mostly mechanical rewrites of the code.
In many places, the backeds were already prepared for async output, in other some glue was needed.
To reduce the scope of this change, some backends simply report a synchronous result as an async list.
With this interface it is possible to wrap the current support for snapshots and USN and simplify the enumeration.
This makes a number of assumptions into fields such as `IsMetaEntry` and `IsRootEntry` that removes code that was checking for various properties.
This first commit has support for VSS and USN as well as "naked" files, keeping feature parity.
There is also an experimental support for loading a backend-as-a-source. The support for this is currently limited as the backends need to be extended to support a folder concept.
Mono sometimes reports the total size of unknown file systems as zero. Because it should be obvious when the size is actually zero, ignore the quota in this case.
The implementations of ISystemIO.FileOpenWrite call File.OpenWrite,
which does not truncate the existing file. As such, if we overwrite a
larger file with a smaller one, tail remnants of the existing file will
remain.
Since most of the put operations involve unique filenames, this is only
a problem when overwriting existing files (e.g.,
duplicati-verification.json).
This fixes a regression introduced in revision 71c6aca8a7 ("Fixed IO
calls in Filebackend") from pull request #3456. The previous
implementation called File.Open with FileMode.Create, which truncates
existing files.
This fixes#4486.
By changing to IEnumerable, it is possible to iterate only a portion of the list, which is useful when not all entries are needed (e.g., when testing a connection).
All existing backends have been updated, and any which were able to be changed to yield return results in a straightforward way now do.
Many backends had a try/catch in the List() method. Due to the fact that yield returns can't be placed within a try/catch block, these have been refactored to either scope the try/catch to the parts that (should) be the only places throwing exceptions, so that exceptions are still caught and handled.
Note that lazy evaluation may cause some changes in behavior - exceptions that were previously thrown at the point of invokation of List() may now be thrown while it is being enumerated.
I believe this will not be problematic though, as the only well-known exception seems to be FolderMissingException, which should be thrown by Test(), but TestList() attempts to enumerate the list to force this exception.
Any places that require the legacy behavior can get it by simply converting the lazy enumerable to a List()
It also makes quota enabled backends return an instance of this interface instead of the quota components separately.
This way, getting quota stats requires only a single remote request on backends like Google Drive and OneDrive.