Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ jobs:
with:
key: ${{ runner.os }}.nuget.${{ hashFiles('**/*.*proj', '**/*.props') }}
path: ${{ env.NUGET_PACKAGES }}
- if: startsWith(github.ref, 'refs/tags/v')
name: Verify that all the public API is marked as shipped
shell: pwsh
run: scripts/Test-PublicApiShipped.ps1
- id: version
name: Get version
shell: pwsh
Expand Down
21 changes: 21 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ process. Developer Mode lets an unelevated process create symbolic links, as doc
[`CreateSymbolicLinkW`][create-symbolic-link] API. When neither is available, these tests are skipped locally; CI
runners fail instead, ensuring that the tests are not silently skipped in automation.

Public API
----------
In TruePath, we track the changes made to the public API, for the package stability purposes.

The public API of every packable project is recorded per target framework in the `PublicAPI/<target framework>/` directories:
- `PublicAPI.Shipped.txt` lists the API of the latest release,
- `PublicAPI.Unshipped.txt` lists the changes made since then.

If you change the public API, the build-time diagnostic will report any difference as `RS0000`-style errors. These are warnings in local builds (for the development purpose) and errors on CI.

To update the files, either use the code fix for these diagnostics in your IDE, or run the following shell command for every changed project, e.g.:
```console
$ dotnet format analyzers <path to project> --diagnostics RS0016 --severity info --include-generated
```

This command only updates one target framework per run, so you might need to run it several times.

Removed members are not handled by this command, so they need to be removed separately:
- if the member is listed in `PublicAPI.Unshipped.txt`, delete that line;
- if the member is listed in `PublicAPI.Shipped.txt`, add a copy of that line prefixed with `*REMOVED*` to `PublicAPI.Unshipped.txt`.

Test Documentation
------------------
To open the project documentation site locally, use the following shell commands:
Expand Down
5 changes: 5 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ SPDX-License-Identifier: MIT
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- Public API diagnostics are only warnings for local development; CI treats them as errors. -->
<WarningsNotAsErrors Condition="'$(CI)' != 'true'">$(WarningsNotAsErrors);RS0016;RS0017;RS0022;RS0024;RS0025;RS0026;RS0027;RS0036;RS0037;RS0041;RS0048;RS0050</WarningsNotAsErrors>
<!-- XML documentation warnings are suppressed for local development; CI verifies them with -p:CheckXmlDoc=true. -->
<NoWarn Condition="'$(CheckXmlDoc)' != 'true'">CS0419;CS1570;CS1571;CS1572;CS1573;CS1574;CS1580;CS1581;CS1584;CS1587;CS1589;CS1590;CS1591;CS1592;CS1598;CS1710;CS1711;CS1712;$(NoWarn)</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand All @@ -33,6 +35,9 @@ SPDX-License-Identifier: MIT
<ItemGroup Condition="$(IsPackable) == 'true'">
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.403" PrivateAssets="All" />
<PackageReference Include="ChangelogAutomation.MSBuild" Version="3.0.5" PrivateAssets="All" />
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="5.6.0" PrivateAssets="All" />
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Shipped.txt" />
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt" />
<None Visible="false" Include="$(MSBuildThisFileDirectory)\LICENSES\**" Pack="true" PackagePath="\LICENSES" />
<None Visible="false" Include="$(MSBuildThisFileDirectory)\CHANGELOG.md" Pack="true" PackagePath="\" />
<None Visible="false" Include="$(MSBuildThisFileDirectory)\README.md" Pack="true" PackagePath="\" />
Expand Down
9 changes: 5 additions & 4 deletions MAINTAINING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ Publish a New Version
3. Update the copyright statement in the `Directory.Build.props` file, if required.
4. Prepare a corresponding entry in the `CHANGELOG.md` file (usually by renaming the "Unreleased" section).
5. Set `<Version>` in the `Directory.Build.props` file.
6. Merge the aforementioned changes via a pull request.
7. If you want to publish a new package (not a new version, but a new project/package) change the NuGet Trusted Publishing Policy: switch from **push only new packages versions** to **push new packages and package versions** (see below for more details).
8. Push a tag in form of `v<VERSION>`, e.g. `v0.0.0`. GitHub Actions will do the rest (push a NuGet packages).
9. If you were publishing a new package, revert back the change you did at step 8.
6. Mark the public API as shipped by running `pwsh -File scripts/Test-PublicApiShipped.ps1 -Autofix`. The release workflow fails if any entries are left in the `PublicAPI.Unshipped.txt` files.
7. Merge the aforementioned changes via a pull request.
8. If you want to publish a new package (not a new version, but a new project/package) change the NuGet Trusted Publishing Policy: switch from **push only new packages versions** to **push new packages and package versions** (see below for more details).
9. Push a tag in form of `v<VERSION>`, e.g. `v0.0.0`. GitHub Actions will do the rest (push a NuGet packages).
10. If you were publishing a new package, revert back the change you did at step 8.

NuGet Publishing Policy
-----------------------
Expand Down
6 changes: 6 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ precedence = "aggregate"
SPDX-FileCopyrightText = "2024 Friedrich von Never <friedrich@fornever.me>"
SPDX-License-Identifier = "MIT"

[[annotations]]
path = "**/PublicAPI/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 TruePath contributors <https://github.com/ForNeVeR/TruePath>"
SPDX-License-Identifier = "MIT"

[[annotations]]
path = "**.DotSettings"
precedence = "aggregate"
Expand Down
86 changes: 86 additions & 0 deletions TruePath.SystemIo/PublicAPI/net8.0/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#nullable enable
static TruePath.SystemIo.PathIo.AppendAllLines(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents) -> void
static TruePath.SystemIo.PathIo.AppendAllLines(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents, System.Text.Encoding! encoding) -> void
static TruePath.SystemIo.PathIo.AppendAllLinesAsync(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents, System.Text.Encoding! encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.AppendAllLinesAsync(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.AppendAllText(this TruePath.AbsolutePath path, string? contents) -> void
static TruePath.SystemIo.PathIo.AppendAllText(this TruePath.AbsolutePath path, string? contents, System.Text.Encoding! encoding) -> void
static TruePath.SystemIo.PathIo.AppendAllTextAsync(this TruePath.AbsolutePath path, string? contents, System.Text.Encoding! encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.AppendAllTextAsync(this TruePath.AbsolutePath path, string? contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.AppendText(this TruePath.AbsolutePath path) -> System.IO.StreamWriter!
static TruePath.SystemIo.PathIo.Copy(this TruePath.AbsolutePath sourceFile, TruePath.AbsolutePath destFile) -> void
static TruePath.SystemIo.PathIo.Copy(this TruePath.AbsolutePath sourceFile, TruePath.AbsolutePath destFile, bool overwrite) -> void
static TruePath.SystemIo.PathIo.Create(this TruePath.AbsolutePath path) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.Create(this TruePath.AbsolutePath path, int bufferSize) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.Create(this TruePath.AbsolutePath path, int bufferSize, System.IO.FileOptions options) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.CreateDirectory(this TruePath.AbsolutePath path) -> void
static TruePath.SystemIo.PathIo.CreateText(this TruePath.AbsolutePath path) -> System.IO.StreamWriter!
static TruePath.SystemIo.PathIo.Delete(this TruePath.AbsolutePath path) -> void
static TruePath.SystemIo.PathIo.DeleteDirectoryRecursively(this TruePath.AbsolutePath path) -> void
static TruePath.SystemIo.PathIo.DeleteEmptyDirectory(this TruePath.AbsolutePath path) -> void
static TruePath.SystemIo.PathIo.EnumerateFiles(this TruePath.AbsolutePath path) -> System.Collections.Generic.IEnumerable<TruePath.AbsolutePath>!
static TruePath.SystemIo.PathIo.EnumerateFiles(this TruePath.AbsolutePath path, string! searchPattern) -> System.Collections.Generic.IEnumerable<TruePath.AbsolutePath>!
static TruePath.SystemIo.PathIo.EnumerateFiles(this TruePath.AbsolutePath path, string! searchPattern, System.IO.EnumerationOptions! enumerationOptions) -> System.Collections.Generic.IEnumerable<TruePath.AbsolutePath>!
static TruePath.SystemIo.PathIo.EnumerateFiles(this TruePath.AbsolutePath path, string! searchPattern, System.IO.SearchOption searchOption) -> System.Collections.Generic.IEnumerable<TruePath.AbsolutePath>!
static TruePath.SystemIo.PathIo.Exists(this TruePath.AbsolutePath path) -> bool
static TruePath.SystemIo.PathIo.ExistsDirectory(this TruePath.AbsolutePath path) -> bool
static TruePath.SystemIo.PathIo.ExistsFile(this TruePath.AbsolutePath path) -> bool
static TruePath.SystemIo.PathIo.GetAttributes(this TruePath.AbsolutePath path) -> System.IO.FileAttributes
static TruePath.SystemIo.PathIo.GetCreationTime(this TruePath.AbsolutePath path) -> System.DateTime
static TruePath.SystemIo.PathIo.GetCreationTimeUtc(this TruePath.AbsolutePath path) -> System.DateTime
static TruePath.SystemIo.PathIo.GetDirectories(this TruePath.AbsolutePath path) -> string![]!
static TruePath.SystemIo.PathIo.GetDirectories(this TruePath.AbsolutePath path, string! searchPattern) -> string![]!
static TruePath.SystemIo.PathIo.GetDirectories(this TruePath.AbsolutePath path, string! searchPattern, System.IO.EnumerationOptions! enumerationOptions) -> string![]!
static TruePath.SystemIo.PathIo.GetDirectories(this TruePath.AbsolutePath path, string! searchPattern, System.IO.SearchOption searchOption) -> string![]!
static TruePath.SystemIo.PathIo.GetFiles(this TruePath.AbsolutePath path) -> string![]!
static TruePath.SystemIo.PathIo.GetFiles(this TruePath.AbsolutePath path, string! searchPattern) -> string![]!
static TruePath.SystemIo.PathIo.GetFiles(this TruePath.AbsolutePath path, string! searchPattern, System.IO.EnumerationOptions! enumerationOptions) -> string![]!
static TruePath.SystemIo.PathIo.GetFiles(this TruePath.AbsolutePath path, string! searchPattern, System.IO.SearchOption searchOption) -> string![]!
static TruePath.SystemIo.PathIo.GetFiles(this TruePath.AbsolutePath path, TruePath.LocalPathPattern searchPattern) -> TruePath.AbsolutePath[]!
static TruePath.SystemIo.PathIo.GetLastAccessTime(this TruePath.AbsolutePath path) -> System.DateTime
static TruePath.SystemIo.PathIo.GetLastAccessTimeUtc(this TruePath.AbsolutePath path) -> System.DateTime
static TruePath.SystemIo.PathIo.GetLastWriteTime(this TruePath.AbsolutePath path) -> System.DateTime
static TruePath.SystemIo.PathIo.GetLastWriteTimeUtc(this TruePath.AbsolutePath path) -> System.DateTime
static TruePath.SystemIo.PathIo.GetUnixFileMode(this TruePath.AbsolutePath path) -> System.IO.UnixFileMode
static TruePath.SystemIo.PathIo.Move(this TruePath.AbsolutePath sourceFile, TruePath.AbsolutePath destFile) -> void
static TruePath.SystemIo.PathIo.Move(this TruePath.AbsolutePath sourceFile, TruePath.AbsolutePath destFile, bool overwrite) -> void
static TruePath.SystemIo.PathIo.Open(this TruePath.AbsolutePath path, System.IO.FileMode mode) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.Open(this TruePath.AbsolutePath path, System.IO.FileMode mode, System.IO.FileAccess access) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.Open(this TruePath.AbsolutePath path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.OpenRead(this TruePath.AbsolutePath path) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.OpenText(this TruePath.AbsolutePath path) -> System.IO.StreamReader!
static TruePath.SystemIo.PathIo.OpenWrite(this TruePath.AbsolutePath path) -> System.IO.FileStream!
static TruePath.SystemIo.PathIo.ReadAllBytes(this TruePath.AbsolutePath path) -> byte[]!
static TruePath.SystemIo.PathIo.ReadAllBytesAsync(this TruePath.AbsolutePath path, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<byte[]!>!
static TruePath.SystemIo.PathIo.ReadAllLines(this TruePath.AbsolutePath path) -> string![]!
static TruePath.SystemIo.PathIo.ReadAllLines(this TruePath.AbsolutePath path, System.Text.Encoding! encoding) -> string![]!
static TruePath.SystemIo.PathIo.ReadAllLinesAsync(this TruePath.AbsolutePath path, System.Text.Encoding! encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<string![]!>!
static TruePath.SystemIo.PathIo.ReadAllLinesAsync(this TruePath.AbsolutePath path, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<string![]!>!
static TruePath.SystemIo.PathIo.ReadAllText(this TruePath.AbsolutePath path) -> string!
static TruePath.SystemIo.PathIo.ReadAllText(this TruePath.AbsolutePath path, System.Text.Encoding! encoding) -> string!
static TruePath.SystemIo.PathIo.ReadAllTextAsync(this TruePath.AbsolutePath path, System.Text.Encoding! encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<string!>!
static TruePath.SystemIo.PathIo.ReadAllTextAsync(this TruePath.AbsolutePath path, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<string!>!
static TruePath.SystemIo.PathIo.ReadLines(this TruePath.AbsolutePath path) -> System.Collections.Generic.IEnumerable<string!>!
static TruePath.SystemIo.PathIo.ReadLines(this TruePath.AbsolutePath path, System.Text.Encoding! encoding) -> System.Collections.Generic.IEnumerable<string!>!
static TruePath.SystemIo.PathIo.ReadLinesAsync(this TruePath.AbsolutePath path, System.Text.Encoding! encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Generic.IAsyncEnumerable<string!>!
static TruePath.SystemIo.PathIo.ReadLinesAsync(this TruePath.AbsolutePath path, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Generic.IAsyncEnumerable<string!>!
static TruePath.SystemIo.PathIo.SetAttributes(this TruePath.AbsolutePath path, System.IO.FileAttributes fileAttributes) -> void
static TruePath.SystemIo.PathIo.SetCreationTime(this TruePath.AbsolutePath path, System.DateTime creationTime) -> void
static TruePath.SystemIo.PathIo.SetCreationTimeUtc(this TruePath.AbsolutePath path, System.DateTime creationTimeUtc) -> void
static TruePath.SystemIo.PathIo.SetLastAccessTime(this TruePath.AbsolutePath path, System.DateTime lastAccessTime) -> void
static TruePath.SystemIo.PathIo.SetLastAccessTimeUtc(this TruePath.AbsolutePath path, System.DateTime lastAccessTimeUtc) -> void
static TruePath.SystemIo.PathIo.SetLastWriteTime(this TruePath.AbsolutePath path, System.DateTime lastWriteTime) -> void
static TruePath.SystemIo.PathIo.SetLastWriteTimeUtc(this TruePath.AbsolutePath path, System.DateTime lastWriteTimeUtc) -> void
static TruePath.SystemIo.PathIo.WriteAllBytes(this TruePath.AbsolutePath path, byte[]! bytes) -> void
static TruePath.SystemIo.PathIo.WriteAllBytesAsync(this TruePath.AbsolutePath path, byte[]! bytes, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.WriteAllLines(this TruePath.AbsolutePath path, string![]! contents) -> void
static TruePath.SystemIo.PathIo.WriteAllLines(this TruePath.AbsolutePath path, string![]! contents, System.Text.Encoding! encoding) -> void
static TruePath.SystemIo.PathIo.WriteAllLines(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents) -> void
static TruePath.SystemIo.PathIo.WriteAllLines(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents, System.Text.Encoding! encoding) -> void
static TruePath.SystemIo.PathIo.WriteAllLinesAsync(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents, System.Text.Encoding! encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.WriteAllLinesAsync(this TruePath.AbsolutePath path, System.Collections.Generic.IEnumerable<string!>! contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.WriteAllText(this TruePath.AbsolutePath path, string? contents) -> void
static TruePath.SystemIo.PathIo.WriteAllText(this TruePath.AbsolutePath path, string? contents, System.Text.Encoding! encoding) -> void
static TruePath.SystemIo.PathIo.WriteAllTextAsync(this TruePath.AbsolutePath path, string? contents, System.Text.Encoding! encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static TruePath.SystemIo.PathIo.WriteAllTextAsync(this TruePath.AbsolutePath path, string? contents, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
TruePath.SystemIo.PathIo
1 change: 1 addition & 0 deletions TruePath.SystemIo/PublicAPI/net8.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#nullable enable
Loading
Loading