### Motivation:
`NIOFileSystem` currently exposes the same API as `_NIOFileSystem`,
which is not API stable. `NIOFileSystem`
was created in error, and its lack of underscore incorrectly implies API
stability. Users who are currently importing `NIOFileSystem` should
ideally move to `_NIOFileSystem`. However this isn't made clear in the
docs:
1. The README talks about the non-underscored `NIOFileSystem`.
2. There are no hosted API docs `NIOFileSystem`.
3. The hosted API docs for `NIO` point to the docs for `NIOFileSystem`
-- results in 404.
### Modifications:
- Update the README to refer to `_NIOFileSystem`.
- Update the hosted API docs for `NIO` to point to docs for
`_NIOFileSystem`.
- Add hosted API docs for `NIOFileSystem` with a statement explaining
the situation and pointing people to the docs
for `_NIOFileSystem`.
### Result:
Clearer documentation on the state and relationship of the
`NIOFileSystem` and `_NIOFileSystem` modules.
Motivation:
We accidentally removed the 'NIOFileSystem' module from the
'_NIOFileSystem' product in the last release.
Modifications:
- Rename 'NIOFileSystem' and 'NIOFileSystemFoundationCompat' to 'NIOFS'
and 'NIOFSFoundationCompat'
- Add back 'NIOFileSystem' which re-exports '_NIOFileSystem' (there was
no publicly available 'NIOFileSystemFoundationCompat' module to
remove, only '_NIOFileSystemFoundationCompat').
Result:
Fewer breaks
Motivation:
We changed the file path type in `_NIOFileSystem` to use `NIOFilePath`
instead of `FilePath`. Originally we planned to use API shims to avoid
breaking API, however in some cases this was inevitable (i.e. where a
file path is returned to the caller).
To roll over to the new API we will instead introduce the
`NIOFileSystem` module using `NIOFilePath` and have `_NIOFileSystem` use
`FilePath`. Users can then opt-in to the new stable API rather than
having it forced upon them.
The first wave of these changes turns `_NIOFileSystem` into
`NIOFileSystem` and uses `NIOFilePath` for its APIs.
Modifications:
- Remove disfavoured overloads (i.e. `FilePath` APIs)
- Update the `DirectoryEntry` API to use `NIOFilePath`.
- Update tests to use `NIOFilePath` since many were relying on the newly
removed shims
- Remove the underscore from the module names and products
- Remove deprecated methods
A follow up change will re-instate the `_NIOFileSystem` (and compat)
module and products using `FilePath`.
Result:
`NIOFileSystem` has a stable API.
Motivation:
Currently, file paths are represented by the `SystemPackage.FilePath`
type in `NIOFileSystem`. Following from #3322, we want to use
`NIOFilePath` instead.
Modifications:
This change provides `NIOFilePath` accepting/returning variants to all
existing public methods that accept/return `SystemPackage.FilePath`.
The bulk of the changes are in `FileSystemProtocol` and
`FileHandleProtocol`, and their conforming types. The protocols have
been modified to require `NIOFilePath` accepting/returning methods.
Default implementations are provided for `SystemPackage.FilePath`
accepting/returning methods---these call through to the `NIOFilePath`
variants.
Result:
`NIOFilePath` path representations can now be used with the methods for
interacting with the file system.
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
Motivation:
Two separate types for representing file paths currently exist:
[`SystemPackage`'s
`FilePath`](https://swiftpackageindex.com/apple/swift-system/1.6.0/documentation/systempackage/filepath)
type and [`System`'s
`FilePath`](https://developer.apple.com/documentation/system/filepath)
type.
`NIOFileSystem` currently uses `SystemPackage`'s `FilePath`. However,
the lack of an API for converting between the two representations means
that users whose application also uses `System.FilePath` may find
interacting with `NIOFileSystem` difficult.
Modifications:
- Added `NIOFilePath`, and its subcomponents `NIOFilePath.Root`,
`NIOFilePath.Component`, and `NIOFilePath.ComponentView`.
- These types mirror the API of `SystemPackage`'s `FilePath` and are
internally backed by it.
- `NIOFilePath` can be initialized from either an instance of
`SystemPackage.FilePath` or `System.FilePath`.
Result:
Reduces the friction of interacting with `NIOFileSystem` by providing a
bridge between `SystemPackage.FilePath` and `System.FilePath`.
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
Fixes all warnings when `-require-explicit-sendable` flag is enabled and
enables the flag on macOS CI.
### Motivation:
We want to ensure our public API is either explicitly marked as
`Sendable` or not.
### Modifications:
Marked appropriate public types as `Sendable`, or explicitly defined
their conformance to the `Sendable` protocol as unavailable.
### Result:
We can now enable `-require-explicit-sendable` compiler flag in our
codebase.
### Motivation:
`inEventLoop` is very much in the performance path of SwiftNIO,
especially these days with Concurrency, `NIOLoopBound` and friends.
Previously, we relied on `pthread_equal(pthread_self(), myPthread)`,
however, this could cause a number of issues.
1. Holding onto a `pthread_t` after `.join` is actually illegal (fixed
in #3297)
2. Potential ABA issues when `pthread_t` pointer are re-used for new
pthreads
3. Fix would require a lock around `myPthread` which makes things (2x
slower, even without contention)
### Modifications:
- New type `SelectableEventLoopUniqueID` which can be packed into a
`UInt`
- Attach them into a C thread local
### Result:
- Even faster than the old, incorrect version
- old: `measuring: el_in_eventloop_100M: 0.257395375, 0.241049208,
0.243188792, 0.259125916, 0.24843225, 0.229690125, 0.244281541,
0.225078834, 0.236395, 0.233305167`
- new: `measuring: el_in_eventloop_100M: 0.175561125, 0.187225625,
0.199269375, 0.19740975, 0.1922695, 0.179850958, 0.177612458,
0.17665125, 0.17897475, 0.18038775`
- More correct
- Groundwork to make #3297 not make things slower
Motivation:
Android messed up their nullability annotations in fts_open. The
original change in
https://android.googlesource.com/platform/bionic/+/dec8efd72a6ad8b807a15a614ae1519487cfa456
asserted that fts_open's path argument took a non-null pointer to an
array of non-null pointers to strings. That's challenging, because the
_end_ of that array is indicated by a null pointer.
Regardless, this was eventually fixed in
https://android.googlesource.com/platform/bionic/+/da81ec4d1cbd0279014feb60535bf38defcd9346.
Unfortunately, that was more than a year after the offending change, so
we need to work around it.
Modifications:
Add a shim for Android that omits the nullability annotations. Use that
shim on Android.
Result:
Android works again.
Resolves#3273.
Motivation
With the introduction of isolated conformances, it has become necessary
to start managing the use of metatypes for some of our protocols. In
general, we don't want to force the relevant protocols to only be
conformed in non-isolated forms. Instead, we just want to make the
specific APIs non-usable.
Modifications
- Add shims for SendableMetatype that only use it when it is available.
- Require SendableMetatype where needed, gated by @preconcurrency.
Result
We continue to be safe.
Fix visionOS builds and tests
### Motivation:
visionOS builds and tests were failing because of missing cases in
availability guards.
### Modifications:
Spell guards in terms of Darwin where appropriate, add visionOS
### Result:
Example run of this working in CI
https://github.com/apple/swift-nio/actions/runs/14876166161/job/41773757638?pr=3220
Motivation:
We're continuing out Strict Concurrency journey, making sure users of
NIO can write data-race-free code.
Modifications:
- Added some missing Sendable annotations in NIOAsyncSequenceProducer
- Made BufferedStream unconditionally Sendable, and required its Element
type to also be Sendable.
The prior constraint wasn't actually correct. We always
behaved as though the element types were Sendable, by passing
them into continuations. This cleans things up.
- Made AnyAsyncSequence Sendable, which it needs to be.
- Made BufferedOrAnyStream Sendable, which it needs to be.
- Made DirectoryEntries explicitly Sendable, which it was.
- Made DirectoryEntries.Batched explicitly Sendable.
Result:
Better concurrency-safety
### Motivation:
Makes it possible to read contents of an NIOFileSystem.FilePath into a
String directly. Closes#3010.
### Modifications:
- Added a new `String+FileSystem.swift` into `NIOFileSystem` target.
- Added basic tests to the existing `ConvenienceTests.swift`.
- Added a test to cover `Array+FileSystem` initializer as well.
### Result:
- String initializer for `FilePath` is now available
- Array initializer for `FilePath` now has a test
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
I added this changed function call for Android in #2660 earlier this
year, because of [an incorrect Bionic function signature as explained
recently](https://github.com/apple/swift-nio/pull/3009#discussion_r1864807270),
but now that it has been worked around through a new API note as
mentioned there, this change is no longer needed.
I simply did not notice this earlier because it still compiles and
merely gives a warning, which removing this call now silences.
Introduce parallel removal of items, instead of only doing a sequential
removal (and discovery) one-by-one
### Motivation:
#2933 mentioned this function call appears to be slow. If we attempt to
delete a directory with lots of subdirectories, we end up discovering
each subdirectory one by one on a single thread.
### Modifications:
This PR refactors the logic to remove items. Instead of sequentially
discovering and deleting items one by one, we traverse all directories
up to a maximum concurrency, and issue file deletions in parallel within
each directory.
### Result:
The new concurrent implementation was measured to be ~1.4x faster than
`FileManager`, ~1.5x faster than `rm -rf` and ~3x faster than the
current sequential implementation on `main`. This new concurrent
implementation does use the most CPU out of all the other approaches.
Results are broken down into two sections. We delete a copy of the
`swift-nio` repository, where the `.build/` folder has grown to a large
size, providing lots of additional files and subdirectories.
We produce a single CLI using `--configration=release` that can switch
between using the `.sequential` mode (what is currently available on the
`main` branch), `.parallel` (the new concurrent implementation in this
PR) and `filemanager` (uses `Foundation.FileManager` as a comparison).
Resolves https://github.com/apple/swift-nio/issues/2933
#### Normal size
**Description:** The `swift-nio` library as found when building the CLI
used for benchmarking.
**Benchmark run with:** 3579 directories, 11657 files
```
$ hyperfine --runs 10 --warmup 2 --prepare "rm -rf /tmp/swift-nio && cp -r $(pwd) /tmp/swift-nio" ".build/release/NIOTestCLI --sequential /tmp/swift-nio" ".build/release/NIOTestCLI --parallel /tmp/swift-nio" ".build/release/NIOTestCLI --filemanager /tmp/swift-nio" "rm -rf /tmp/swift-nio"
Benchmark 1: .build/release/NIOTestCLI --sequential /tmp/swift-nio
Time (mean ± σ): 2.712 s ± 0.053 s [User: 0.526 s, System: 8.632 s]
Range (min … max): 2.625 s … 2.781 s 10 runs
Benchmark 2: .build/release/NIOTestCLI --parallel /tmp/swift-nio
Time (mean ± σ): 896.7 ms ± 25.6 ms [User: 302.9 ms, System: 5313.5 ms]
Range (min … max): 853.2 ms … 942.1 ms 10 runs
Benchmark 3: .build/release/NIOTestCLI --filemanager /tmp/swift-nio
Time (mean ± σ): 1.337 s ± 0.076 s [User: 0.022 s, System: 1.253 s]
Range (min … max): 1.252 s … 1.508 s 10 runs
Benchmark 4: rm -rf /tmp/swift-nio
Time (mean ± σ): 1.483 s ± 0.037 s [User: 0.015 s, System: 1.416 s]
Range (min … max): 1.413 s … 1.541 s 10 runs
Summary
.build/release/NIOTestCLI --parallel /tmp/swift-nio ran
1.49 ± 0.10 times faster than .build/release/NIOTestCLI --filemanager /tmp/swift-nio
1.65 ± 0.06 times faster than rm -rf /tmp/swift-nio
3.02 ± 0.10 times faster than .build/release/NIOTestCLI --sequential /tmp/swift-nio
```
#### Large size
**Description:** The `swift-nio` library as found after re-running the
`.github` workflow many times locally. I'm unable to reproduce this
directory size, but have benchmarked against it.
**Benchmark run with:** 15260 directories, 46842 files
```
$ hyperfine --runs 10 --warmup 2 --prepare "rm -rf /tmp/swift-nio && cp -r $(pwd) /tmp/swift-nio" ".build/release/NIOTestCLI --sequential /tmp/swift-nio" ".build/release/NIOTestCLI --parallel /tmp/swift-nio" ".build/release/NIOTestCLI --filemanager /tmp/swift-nio" "rm -rf /tmp/swift-nio"
Benchmark 1: .build/release/NIOTestCLI --sequential /tmp/swift-nio
Time (mean ± σ): 12.082 s ± 0.354 s [User: 2.180 s, System: 41.547 s]
Range (min … max): 11.717 s … 12.923 s 10 runs
Benchmark 2: .build/release/NIOTestCLI --parallel /tmp/swift-nio
Time (mean ± σ): 4.770 s ± 0.102 s [User: 1.357 s, System: 25.785 s]
Range (min … max): 4.570 s … 4.883 s 10 runs
Benchmark 3: .build/release/NIOTestCLI --filemanager /tmp/swift-nio
Time (mean ± σ): 6.503 s ± 0.115 s [User: 0.081 s, System: 5.427 s]
Range (min … max): 6.262 s … 6.687 s 10 runs
Benchmark 4: rm -rf /tmp/swift-nio
Time (mean ± σ): 7.056 s ± 0.246 s [User: 0.064 s, System: 6.119 s]
Range (min … max): 6.435 s … 7.233 s 10 runs
Summary
.build/release/NIOTestCLI --parallel /tmp/swift-nio ran
1.36 ± 0.04 times faster than .build/release/NIOTestCLI --filemanager /tmp/swift-nio
1.48 ± 0.06 times faster than rm -rf /tmp/swift-nio
2.53 ± 0.09 times faster than .build/release/NIOTestCLI --sequential /tmp/swift-nio
```
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
### Motivation:
Get this repo building again for Android with NDK 27
### Modifications:
- Update some networking declarations for newly added nullability
annotations
- Import the new Android overlay instead in some tests
- Add two force-unwraps on all platforms, that are needed for Android
### Result:
This repo and its tests build for Android again
I've been [using these patches on my Android
CI](https://github.com/finagolfin/swift-android-sdk/blob/main/swift-nio-ndk27.patch)
and natively on Android for a couple months now. I didn't bother keeping
this patch building for Android with Swift 5 anymore, as my Android CI
no longer tests Swift 5.
I built this pull and ran the tests on linux x86_64 to make sure there
was no regression.
Updates to documentation comments in `NIOFileSystem`.
### Motivation:
I've been reviewing some parts of `NIOFileSystem` and came across a
variety of formatting of documentation comments.
### Modifications:
I've adopted a stricter 100-character limit (arbitrary, really; it could
be longer or shorter and is totally not consistent with the rest of the
repository). Also updated a bunch of grammar in comments. Fixed a few
typos along the way.
### Result:
- Updated comments have a better flow while reading, and aren't as
abrupt as before.
- Fewer typos in comments
---------
Co-authored-by: Cory Benfield <lukasa@apple.com>
### Motivation:
Opening the `swift-nio` repository made me warning blind because there
were always so many trivially fixable warnings about things that were
correct but cannot be understood by the compiler.
### Modifications:
Fix all the sendable warnings that popped up, except for one test where
`NIOLockedValueBox<Thread?>` isn't sendable because `Foundation.Thread`
seemingly isn't `Sendable` which is odd. Guessing that'll be fixed on
their end.
### Result:
- Fewer warnings
- Less warning-blindness
- More checks
### Motivation:
Documentation checking catches more issues in Swift 6.0.
### Modifications:
Adopt the Swift 6.0 image and fix the errors.
### Result:
More accurate docs.
Add Vision support
### Motivation:
https://github.com/apple/swift-nio/issues/2900 - close this
### Modifications:
- Bump SystemPackage to 1.4.0 and remove @preconcurrency
- remove `#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) ||
os(Linux) || os(Android)` to allow for visionOS support
- Remove conditional import for swift system
### Result:
Vision OS support
Motivation:
As requested in issues
[#2875](https://github.com/apple/swift-nio/issues/2875) and
[#2876](https://github.com/apple/swift-nio/issues/2876), it would be
convenient to be able to read the contents of a file into more data
types such as `Array`, `ArraySlice` & Foundation's `Data`.
Modifications:
- Extend `Array`, `ArraySlice` & `Data` to be initialisable with the
contents of a file.
Result:
The contents of a file can be read into more data types.
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
### Motivation:
Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem to reduce code
duplication.
### Modifications:
Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem
`DirectoryEntryProducer` and `FileChunkProducer`.
This change was previously merged and then backed out due to issues
(#2879). The original change is in the first commit, the second commit
contains additional changes.
In the original adoption of `NIOThrowingAsyncSequenceProducer` the code
did not deal with backpressure being applied very well, in some cases
causes hangs.
A key bug was that it was not protected against re-entrant calls to
`produceMore`. Such calls may happen e.g. when the producer has been
asked to pause producing and then resume again before the initial read
had completed. This resulted in overlapping reads and re-ordered data.
This change introduces a new activity state which is protected by a lock
and keeps track of if we are in the critical section to serialize
access.
`DirectoryEntryProducer` performs most of its logic within a lock and so
doesn't seem to be impacted in the same way.
### Result:
No functional changes. Internal changes reduce code duplication.
Motivation:
As described in issue
[#2877](https://github.com/apple/swift-nio/issues/2877), there is no API
available to specify allowing a read of unlimited size.
Modifications:
- Add a new `public static` property, `unlimited`, to `ByteCount`
representing an unlimited amount of bytes.
- Adapt
`ReadableFileHandleProtocol.readToEnd(fromAbsoluteOffset:maximumSizeAllowed:)`
to work with `maximumSizeAllowed` being `ByteCount.unlimited`.
Result:
An API to specify allowing a read of an unlimited size will be
available.
Motivation:
As described in issue
[#2878](https://github.com/apple/swift-nio/issues/2878), NIOFileSystem
crashes when reading more than `ByteBuffer` capacity.
Modifications:
- Add a new static property, `byteBufferCapacity`, to `ByteCount`
representing the maximum amount of bytes that can be written to
`ByteBuffer`.
- Throw a `FileSystemError` in
`ReadableFileHandleProtocol.readToEnd(fromAbsoluteOffset:maximumSizeAllowed:)`
when `maximumSizeAllowed` is more than `ByteCount.byteBufferCapacity`.
Result:
NIOFileSystem will `throw` instead of crashing.
Motivation:
Several arithmetic and comparison operations are done with `ByteCount`
using the `bytes` property. Operating on the `ByteCount` type directly
will be more convenient.
Modifications:
- Add `AdditiveArithmetic` and `Comparable` conformances to `ByteCount`.
Result:
The `ByteCount` type can undergo arithmetic and comparison operations.
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
This reverts commit 282f5935cf.
### Motivation:
Repeated testing in linux containers has surfaced issues with the
implementation which require some rethinking of the code, let's revert
it for now and fix it up.
### Modifications:
Revert the adoption commit.
### Result:
The change is backed out.
Motivation:
`FileChunks` is an `AsyncSequence` so should be `Sendable` otherwise
it's difficult to use.
Modifications:
- Conform `FileChunks` to `Sendable`
Result:
- Resolves https://github.com/apple/swift-nio/issues/2752
Motivation:
Per @jakepetroules, swift-build copies symlinks as-is into resource
bundles. That means these symlinks are dead when built with swift-build.
There's sort of no point in that.
Modifications:
Remove symlinks, replace with files.
Result:
Privacy info works.
### Motivation:
Copying regular files on Darwin was taking more time than it needed to
because it was manually opening files and copying over bites rather than
making use of the system's ability to create CoW clones.
### Modifications:
The primary change is to switch `copyItem` to be backed by Darwin's
`copyfile` method rather than `fcopyfile`. `fcopyfile` ignores the flag
we were passing in to indicate that the file should be cloned if
possible, whereas `copyfile` is a higher-level API which takes this into
account.
This change exposes a `copyfile` wrapper method as a new public
function.
This change also adds a workaround to a seeming compiler bug on channel
options blocking building tests on more recent Xcodes.
### Result:
Copying files on Darwin will be faster.
FilesystemProtocol/copyItem has an overload providing the default CopyStrategy
Motivation:
Based on user feedback from #2806
This makes it easier to use, especially when copying files such that it is irrelevant.
Modifications:
Add overload providing (at:to:shouldProceedAfterError:shouldCopyItem:) with CopyStrategy.platformDefault
as the strategy.
Fix a cancellation bug which resulted in a test being flaky.
In addition made the test cover that case reliably to prevent it coming back.
Result:
A simpler and more robust to change API will exist for copyItem()
Motivation:
Using some limited parallelism can improved the speed of the copy for very limited increase in cpu use.
In circumstances where the source and/or destination are on a high latency device, such as a network file system,
the resulting speed up can be even more significant.
Providing conservative defaults, while allowing users the ability to control it directly if desired, provides for a faster default and access to user targeted gains in performance.
The use of parallel by default is considered in keeping with the swift-nio model of concurrent capabilities.
The parallelism used is restricted because the underlying limited resource for this is highly likely to be limited system file descriptors, rather than the limits of the underlying executor itself, especially on embedded devices with significantly more limited concurrent descriptors.
Modifications:
All copyItem overloads except ```copyItem(sourcePath:destinationPath:shouldProceedAfterError:shouldCopyFile)```
can, and likely will, use concurrent copies when copying directories.
A Newly type ```CopyStrategy``` controls the behaviour, allowing:
* ```parallel(maxDescriptors: Int)```
* Parallel limited to a maximum number of concurrently open file descriptors.
* ```sequential```
* The previous behaviour, still asynchronous but only one operation at a time
* ```platformDefault```
* Whatever the API determines the default should be from the prior options
The cancellation semantics of copyItem were previously unclear/undocumented.
These are now stated and cancellation is tested.
There were some aspects of naming/types on this API which were inconsistent/unclear. Those have been altered to aid clarity.
* Less duplication with the protocol docs
* Consistent use of `item` not `file`
* Use DirectoryEntry for the source in both ```shouldXxx``` callbacks
NIOFileSystem package status remains unchanged, it is still _NIOFileSystem with the semantics that entails.
Result:
For any use of the following functions on FileSystemProtocol, when backed by FileSystem:
- ```copyItem(*)```:
The shouldCopyItem check happens before the internal FileSystem "do I know how to copy this sort of FileType" check. This makes the code a little simpler, but the desire is to allow consuming code to filter out anything unexpected if they like without needing to trap errors.
- ```copyItem(sourcePath:destinationPath)```:
Depending on the platform this will become parallel, users on MacOS, Linux and Windows will have up to 4 concurrent file system operations at once.
Empirical testing on a MacBook pro with a significant dense directory hierarchy of 12 GiB had performance improvements of ~50% reduction in elapsed time for CPU usage increases below the noise floor of the testing
- ```copyItem(sourcePath:destinationPath:shouldProceedAfterError:shouldCopyFile)```:
When migrating from this to ```copyItem(sourcePath:destinationPath:copyStrategy:shouldProceedAfterError:shouldCopyItem)```care should be taken to ensure the should callbacks are safe to use in different concurrency domains, or that CopyStrategy.sequential is explicitly stated.
The backward compatibility shim provided does this by default.
Motivation:
Get this repo building again for Android with the new overlay
Modifications:
- Import the new module or overlay wherever `Glibc` is used
- Keep this repo building with Swift 5 by duplicating some declarations
Result:
All the same tests keep passing on my Android CI, finagolfin/swift-android-sdk#158
* Apply formatting
* Apply no block comments rule
* Apply OmitExplicitReturns
* Apple OnlyOneTrailingClosureArgument
* Apply NoAssignmentInExpressions
* Fix up DontRepeatTypeInStaticProperties lint errors
* Apply `OrderedImports`
* Apply `ReplaceForEachWithForLoop`
* format file
* Enable the formatting pipeline
* Adopt `AmbiguousTrailingClosureOverload`
* Fix license header
* Fix format check
* Fix `EndOfLineComment`
* Fix CI
* Adapt CI script to check if changes when running formatting
* Separate lint and format into to steps
* Fix format
* Adopt `UseEarlyExits`
* Revert "Adopt `UseEarlyExits`"
This reverts commit d1ac5bbe12.
# Motivation
Next up replacing the documentation check.
# Modification
This moves the current approach of the script into a GH action. I tried just running the documentation check against all targets but that also results in warnings from downstream deps in their docs to show up.
I also fixed up some new errors that appeared since our current pipeline was running on 5.8.
# Result
Next CI job migrated to GHA
Motivation:
The existing link to NIOFileSystem docs 404's
Modifications:
Speculative fixes because getting any links to work locally is
challenging.
* rename `NIOFileSystem.md` -> `index.md` in line with other modules
* modify the link on the NIO index page to reference `_NIOFileSystem`
local experiments suggest it might change the form of the generated
URL to where the docs can be found
(https://swiftpackageindex.com/apple/swift-nio/2.67.0/documentation/_NIOFileSystem).
Result:
Hopefully the NIOFileSystem docs link will work
This PR adds API to set a file's last accessed and last modified times, as well as a `touch()` shorthand that updates both to the current time.
Motivation:
Feature request: https://github.com/apple/swift-nio/issues/2712
Modifications:
This PR adds API to set a file's last accessed and last modified times, as well as a `touch()` shorthand that updates both to the current time.
Result:
Files' last accessed and last modified times can be updated.
Motivation:
'renameat2' can fail with EINVAL if the RENAME_NOREPLACE flag isn't
supported. However, not all kernel versions support this flag which can
result in an error when creating a file 'transactionally'.
Using 'renameat2' only happens on Linux as a fallback when O_TMPFILE
isn't available.
Modifications:
- On Linux, fallback to a combination of 'stat' and 'rename' if 'renameat2' fails with EINVAL.
- Add a couple of tests
Result:
Files can still be created exclusively
* Add a version of 'write' for 'ByteBuffer'
Motivation:
At the moment 'WritableFileHandleProtocol' is in terms of
`some Sequence<UInt8>`. To use a `ByteBuffer` users must pass in the
readable view of the buffer, which is inconvenient.
Modifications:
- Add an extension to `WritableFileHandleProtocol` which takes a
`ByteBuffer`.
Result:
Easier to use API
* fix docs
Motivation:
The name of the syscall used in errors for all rename calls is "rename".
However, this isn't always correct, in some cases "renamex_np" is used,
and in others "renameat2" is used.
Modifications:
- Allow the name of the syscall to be provided to the rename error
- Use the correct syscall name
Result:
Better errors
Motivation:
Existentials are boxed if they are wider than 24 bytes. A number of
value types in NIO are implemented with storage classes so that the
alloaction is only paid for once. However, existential errors are
treated differently, they are unconditionally boxed. Implementing errors
with storage classes therefore introduces an unnecessary allocation.
Modifications:
- Remove the storage class for FileSystemError
- Remove the copy-on-write test
Result:
Fewer allocations
Motivation:
Single letter names are discouraged but are used in a handful of places
in NIOFileSystem.
Modifications:
- Replace 'R' with 'ReturnType' where appropriate
Result:
Clearer APIs
Motivation:
NIOFileSystem can create the path of a temporary directory but doesn't
offer any API to create and then remove a directory.
Modifications:
- Add `withTemporaryDirectory`
Result:
- Users can get scoped access to a temporary directory which is
subsequently removed for them
- Resolves#2664
Motivation:
The `BufferedWriter` in `NIOFileSystem` has API in terms
of `some Sequence<UInt8>`, meaning that you need to pass
`byteBuffer.readableBytesView` which is a bit inconvenient.
Modifications:
- Add overloads which allow you to pass `ByteBuffer` directly
- Remove redundant availability guards; they are already applied to the
type
Result:
- Better API for users
- Resolves#2662
Motivation:
Many of the filesystem with methods have a requirement that the
result type is sendable. In most cases this is not required as
the result is not shared or sent.
Modifications:
Remove sendable requirement for result types where it is not required.
Result:
Users will not have to make so many types sendable.
Motivation:
NIOPosix and NIOFileSystem use stat(2) (or some variation of it). These
are "required reason APIs" meaning that their usage and reason must be
declared in a privacy manifest in order to be submitted to the App Store.
Modifications:
- Add a privacy manifest to NIOPosix and NIOFileSystem
Result:
Apps using NIO won't be rejected from App Store submission for missing
privacy manifests.