Skip to content

Commit cfc4937

Browse files
authored
NuGet.Packaging nullability - Signing APIs (#7219)
1 parent 279cdad commit cfc4937

144 files changed

Lines changed: 945 additions & 1155 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/copilot-instructions.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,15 @@
1414
## Project-Specific Rules
1515

1616
- All files in the repository are nullable by default (project-level nullable enable). No need to add `#nullable enable` directives to individual files.
17+
18+
## Nullable Migration Rules
19+
20+
- **Shipped.txt format must be precise** — e.g. `string![]!` not `string![]`, `byte[]?` not `byte?[]`. Always match the format of existing base class entries in the same file.
21+
- **`~` (oblivious) entries get replaced in place** — replace the `~` prefixed line with the annotated line in `PublicAPI.Shipped.txt`. Do not add to `PublicAPI.Unshipped.txt`.
22+
- **Internal types don't need Shipped.txt updates** — only public API surfaces require `PublicAPI.Shipped.txt` changes.
23+
- **Don't suppress nullability with `!`** when the value genuinely can be null — make the type honest, let callers handle it.
24+
- **Covariant return nullability**`byte[]` override of `byte[]?` base is valid in C# 9+. Use it when a subclass guarantees non-null.
25+
- **`Debug.Assert(x != null)` + `x!` can be replaced** by removing both when the parameter is non-null typed and all callers are nullable-enabled.
26+
- **`required` on private/internal types** is cleaner than `null!` field initializers.
27+
- **TryCreate/TryGet patterns** — out params need `?`, callers use `!` after the success guard. Out parameters that are guaranteed non-null when the method returns true should be annotated with `[NotNullWhen(true)]`. Don't annotate `[NotNullWhen]` unless it's actually true for all code paths.
28+
- **Work in batches** — group related files, fix source, fix cascading, build, repeat. If this means we need multiple pull requests for enabling nullable, that's fine. Don't try to do it all in one go.

src/NuGet.Core/NuGet.Packaging/PackageExtraction/PackageHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public static async Task<IEnumerable<ZipFilePair>> GetInstalledPackageFilesAsync
172172
if (!string.IsNullOrEmpty(packageDirectory))
173173
{
174174
var packageFiles = await packageReader.GetPackageFilesAsync(packageSaveMode, cancellationToken);
175-
var entries = packageReader.EnumeratePackageEntries(packageFiles, packageDirectory);
175+
var entries = packageReader.EnumeratePackageEntries(packageFiles, packageDirectory!);
176176
installedPackageFiles = entries.Where(e => e.IsInstalled());
177177
}
178178

src/NuGet.Core/NuGet.Packaging/PackageExtractor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ public static async Task<IEnumerable<string>> CopySatelliteFilesAsync(
946946
var nupkgFilePath = packagePathResolver.GetInstalledPackageFilePath(packageIdentity);
947947
if (File.Exists(nupkgFilePath))
948948
{
949-
using (var packageReader = new PackageArchiveReader(nupkgFilePath))
949+
using (var packageReader = new PackageArchiveReader(nupkgFilePath!))
950950
{
951951
return await CopySatelliteFilesAsync(
952952
packageReader,

src/NuGet.Core/NuGet.Packaging/PackagePathResolver.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
#nullable disable
5-
64
using System;
75
using System.Globalization;
86
using System.IO;
@@ -87,14 +85,14 @@ public virtual string GetInstallPath(PackageIdentity packageIdentity)
8785
return Path.Combine(_rootDirectory, GetPackageDirectoryName(packageIdentity));
8886
}
8987

90-
public virtual string GetInstalledPath(PackageIdentity packageIdentity)
88+
public virtual string? GetInstalledPath(PackageIdentity packageIdentity)
9189
{
9290
var installedPackageFilePath = GetInstalledPackageFilePath(packageIdentity);
9391

9492
return string.IsNullOrEmpty(installedPackageFilePath) ? null : Path.GetDirectoryName(installedPackageFilePath);
9593
}
9694

97-
public virtual string GetInstalledPackageFilePath(PackageIdentity packageIdentity)
95+
public virtual string? GetInstalledPackageFilePath(PackageIdentity packageIdentity)
9896
{
9997
return PackagePathHelper.GetInstalledPackageFilePath(packageIdentity, this);
10098
}

src/NuGet.Core/NuGet.Packaging/PublicAPI/net472/PublicAPI.Shipped.txt

Lines changed: 280 additions & 280 deletions
Large diffs are not rendered by default.

src/NuGet.Core/NuGet.Packaging/PublicAPI/net8.0/PublicAPI.Shipped.txt

Lines changed: 269 additions & 269 deletions
Large diffs are not rendered by default.

src/NuGet.Core/NuGet.Packaging/Signing/Archive/CentralDirectoryHeader.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
#nullable disable
5-
4+
using System.Diagnostics.CodeAnalysis;
65
using System.IO;
76

87
// ZIP specification: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
@@ -31,9 +30,9 @@ internal sealed class CentralDirectoryHeader
3130
internal ushort InternalFileAttributes { get; private set; }
3231
internal uint ExternalFileAttributes { get; private set; }
3332
internal uint RelativeOffsetOfLocalHeader { get; private set; }
34-
internal byte[] FileName { get; private set; }
35-
internal byte[] ExtraField { get; private set; }
36-
internal byte[] FileComment { get; private set; }
33+
internal byte[] FileName { get; private set; } = null!;
34+
internal byte[] ExtraField { get; private set; } = null!;
35+
internal byte[] FileComment { get; private set; } = null!;
3736

3837
// This property is not part of the ZIP specification.
3938
internal long OffsetFromStart { get; private set; }
@@ -46,7 +45,7 @@ internal uint GetSizeInBytes()
4645
FileCommentLength;
4746
}
4847

49-
internal static bool TryRead(BinaryReader reader, out CentralDirectoryHeader header)
48+
internal static bool TryRead(BinaryReader reader, [NotNullWhen(returnValue: true)] out CentralDirectoryHeader? header)
5049
{
5150
header = null;
5251

src/NuGet.Core/NuGet.Packaging/Signing/Archive/Crc32.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
#nullable disable
6-
75
using System;
86

97
namespace NuGet.Packaging.Signing

src/NuGet.Core/NuGet.Packaging/Signing/Archive/EndOfCentralDirectoryRecord.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
#nullable disable
5-
64
using System;
75
using System.Collections.Generic;
86
using System.Globalization;
@@ -24,7 +22,7 @@ internal sealed class EndOfCentralDirectoryRecord
2422
internal uint SizeOfCentralDirectory { get; private set; }
2523
internal uint OffsetOfStartOfCentralDirectory { get; private set; }
2624
internal ushort FileCommentLength { get; private set; }
27-
internal byte[] FileComment { get; private set; }
25+
internal byte[] FileComment { get; private set; } = null!; // Set to non-null in the static Read method.
2826

2927
// This property is not part of the ZIP specification.
3028
internal long OffsetFromStart { get; private set; }

src/NuGet.Core/NuGet.Packaging/Signing/Archive/ExtraField.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
#nullable disable
5-
64
using System.Collections.Generic;
5+
using System.Diagnostics.CodeAnalysis;
76
using System.IO;
87

98
// ZIP specification: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
@@ -23,7 +22,7 @@ protected ExtraField(ushort headerId, ushort dataSize, byte[] data)
2322
Data = data;
2423
}
2524

26-
internal static bool TryRead(CentralDirectoryHeader header, out IReadOnlyList<ExtraField> extraFields)
25+
internal static bool TryRead(CentralDirectoryHeader header, [NotNullWhen(returnValue: true)] out IReadOnlyList<ExtraField>? extraFields)
2726
{
2827
extraFields = null;
2928

@@ -46,7 +45,7 @@ internal static bool TryRead(CentralDirectoryHeader header, out IReadOnlyList<Ex
4645
out extraFields);
4746
}
4847

49-
internal static bool TryRead(LocalFileHeader header, out IReadOnlyList<ExtraField> extraFields)
48+
internal static bool TryRead(LocalFileHeader header, [NotNullWhen(returnValue: true)] out IReadOnlyList<ExtraField>? extraFields)
5049
{
5150
extraFields = null;
5251

0 commit comments

Comments
 (0)