Skip to content

Commit

Permalink
detect dependencies with restore property to work around NuGet bug
Browse files Browse the repository at this point in the history
  • Loading branch information
brettfo committed Mar 4, 2025
1 parent b19f62f commit abf2f65
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1381,4 +1381,57 @@ await TestDiscoveryAsync(
}
);
}

// If the "Restore" target is invoked and $(RestoreUseStaticGraphEvaluation) is set to true, NuGet can throw
// a NullReferenceException.
// https://github.com/NuGet/Home/issues/11761#issuecomment-1105218996
[Fact]
public async Task NullReferenceExceptionFromNuGetRestoreIsWorkedAround()
{
await TestDiscoveryAsync(
packages: [
MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.3", "net8.0"),
],
experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
workspacePath: "",
files: [
("project.csproj", """
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RestoreUseStaticGraphEvaluation>true</RestoreUseStaticGraphEvaluation>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Some.Package" Version="1.2.3" />
</ItemGroup>
</Project>
"""),
// a pattern seen in the wild; always run restore
("Directory.Build.rsp", """
/Restore
""")
],
expectedResult: new()
{
Path = "",
Projects = [
new()
{
FilePath = "project.csproj",
TargetFrameworks = ["net8.0"],
Dependencies = [
new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true)
],
Properties = [
new("RestoreUseStaticGraphEvaluation", "true", "project.csproj"),
new("TargetFramework", "net8.0", "project.csproj"),
],
ReferencedProjectPaths = [],
ImportedFiles = [],
AdditionalFiles = [],
}
]
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithBin
{
// the built-in target `GenerateBuildDependencyFile` forces resolution of all NuGet packages, but doesn't invoke a full build
var dependencyDiscoveryTargetsPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "DependencyDiscovery.targets");
var args = new string[]
var args = new List<string>()
{
"build",
startingProjectPath,
Expand All @@ -112,6 +112,16 @@ public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithBin
$"/bl:{binLogPath}"
};
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, startingProjectDirectory, experimentsManager);
if (exitCode != 0 && stdOut.Contains("error : Object reference not set to an instance of an object."))
{
// https://github.com/NuGet/Home/issues/11761#issuecomment-1105218996
// Due to a bug in NuGet, there can be a null reference exception thrown and adding this command line argument will work around it,
// but this argument can't always be added; it can cause problems in other instances, so we're taking the approach of not using it
// unless we have to.
args.Add("/RestoreProperty:__Unused__=__Unused__");
(exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, startingProjectDirectory, experimentsManager);
}

return (exitCode, stdOut, stdErr);
}, logger, retainMSBuildSdks: true);
MSBuildHelper.ThrowOnError(stdOut);
Expand Down

0 comments on commit abf2f65

Please sign in to comment.