Skip to content

Commit 9ecac04

Browse files
authored
Merge pull request #15680 from tamasvajk/buildless/no-mono-fallback-impr
C#: Improve fallback nuget package restore in buildless
2 parents 218a387 + 0c46b49 commit 9ecac04

File tree

4 files changed

+73
-19
lines changed

4 files changed

+73
-19
lines changed

csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -882,14 +882,14 @@ private void DownloadMissingPackages(List<FileInfo> allFiles, ISet<string> dllPa
882882
var alreadyDownloadedPackages = GetRestoredPackageDirectoryNames(packageDirectory.DirInfo);
883883
var alreadyDownloadedLegacyPackages = GetRestoredLegacyPackageNames();
884884

885-
var notYetDownloadedPackages = new HashSet<string>(fileContent.AllPackages);
885+
var notYetDownloadedPackages = new HashSet<PackageReference>(fileContent.AllPackages);
886886
foreach (var alreadyDownloadedPackage in alreadyDownloadedPackages)
887887
{
888-
notYetDownloadedPackages.Remove(alreadyDownloadedPackage);
888+
notYetDownloadedPackages.Remove(new(alreadyDownloadedPackage, PackageReferenceSource.SdkCsProj));
889889
}
890890
foreach (var alreadyDownloadedLegacyPackage in alreadyDownloadedLegacyPackages)
891891
{
892-
notYetDownloadedPackages.Remove(alreadyDownloadedLegacyPackage);
892+
notYetDownloadedPackages.Remove(new(alreadyDownloadedLegacyPackage, PackageReferenceSource.PackagesConfig));
893893
}
894894

895895
if (notYetDownloadedPackages.Count == 0)
@@ -930,7 +930,7 @@ private void DownloadMissingPackages(List<FileInfo> allFiles, ISet<string> dllPa
930930

931931
Parallel.ForEach(notYetDownloadedPackages, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, package =>
932932
{
933-
var success = TryRestorePackageManually(package, nugetConfig);
933+
var success = TryRestorePackageManually(package.Name, nugetConfig, package.PackageReferenceSource);
934934
if (!success)
935935
{
936936
return;
@@ -947,7 +947,10 @@ private void DownloadMissingPackages(List<FileInfo> allFiles, ISet<string> dllPa
947947
dllPaths.Add(missingPackageDirectory.DirInfo.FullName);
948948
}
949949

950-
private bool TryRestorePackageManually(string package, string? nugetConfig)
950+
[GeneratedRegex(@"<TargetFramework>.*</TargetFramework>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
951+
private static partial Regex TargetFramework();
952+
953+
private bool TryRestorePackageManually(string package, string? nugetConfig, PackageReferenceSource packageReferenceSource = PackageReferenceSource.SdkCsProj)
951954
{
952955
logger.LogInfo($"Restoring package {package}...");
953956
using var tempDir = new TemporaryDirectory(ComputeTempDirectory(package, "missingpackages_workingdir"));
@@ -957,6 +960,11 @@ private bool TryRestorePackageManually(string package, string? nugetConfig)
957960
return false;
958961
}
959962

963+
if (packageReferenceSource == PackageReferenceSource.PackagesConfig)
964+
{
965+
TryChangeTargetFrameworkMoniker(tempDir.DirInfo);
966+
}
967+
960968
success = dotnet.AddPackage(tempDir.DirInfo.FullName, package);
961969
if (!success)
962970
{
@@ -972,7 +980,9 @@ private bool TryRestorePackageManually(string package, string? nugetConfig)
972980
res = dotnet.Restore(new(tempDir.DirInfo.FullName, missingPackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: false, PathToNugetConfig: null, ForceReevaluation: true));
973981
}
974982

975-
// TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package.
983+
// TODO: the restore might fail, we could retry with
984+
// - a prerelease (*-* instead of *) version of the package,
985+
// - a different target framework moniker.
976986

977987
if (!res.Success)
978988
{
@@ -984,6 +994,38 @@ private bool TryRestorePackageManually(string package, string? nugetConfig)
984994
return true;
985995
}
986996

997+
private void TryChangeTargetFrameworkMoniker(DirectoryInfo tempDir)
998+
{
999+
try
1000+
{
1001+
logger.LogInfo($"Changing the target framework moniker in {tempDir.FullName}...");
1002+
1003+
var csprojs = tempDir.GetFiles("*.csproj", new EnumerationOptions { RecurseSubdirectories = false, MatchCasing = MatchCasing.CaseInsensitive });
1004+
if (csprojs.Length != 1)
1005+
{
1006+
logger.LogError($"Could not find the .csproj file in {tempDir.FullName}, count = {csprojs.Length}");
1007+
return;
1008+
}
1009+
1010+
var csproj = csprojs[0];
1011+
var content = File.ReadAllText(csproj.FullName);
1012+
var matches = TargetFramework().Matches(content);
1013+
if (matches.Count == 0)
1014+
{
1015+
logger.LogError($"Could not find target framework in {csproj.FullName}");
1016+
}
1017+
else
1018+
{
1019+
content = TargetFramework().Replace(content, $"<TargetFramework>{FrameworkPackageNames.LatestNetFrameworkMoniker}</TargetFramework>", 1);
1020+
File.WriteAllText(csproj.FullName, content);
1021+
}
1022+
}
1023+
catch (Exception exc)
1024+
{
1025+
logger.LogError($"Failed to update target framework in {tempDir.FullName}: {exc}");
1026+
}
1027+
}
1028+
9871029
public void Dispose(TemporaryDirectory? dir, string name)
9881030
{
9891031
try

csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ internal partial class FileContent
1919
private readonly ILogger logger;
2020
private readonly IUnsafeFileReader unsafeFileReader;
2121
private readonly IEnumerable<string> files;
22-
private readonly HashSet<string> allPackages = new HashSet<string>();
22+
private readonly HashSet<PackageReference> allPackages = new HashSet<PackageReference>();
2323
private readonly HashSet<string> implicitUsingNamespaces = new HashSet<string>();
2424
private readonly Initializer initialize;
2525

26-
public HashSet<string> AllPackages
26+
public HashSet<PackageReference> AllPackages
2727
{
2828
get
2929
{
@@ -157,15 +157,15 @@ private static bool IsGroupMatch(ReadOnlySpan<char> line, Regex regex, string gr
157157
return false;
158158
}
159159

160-
private void AddPackageReference(ReadOnlySpan<char> line, string groupName, Func<Regex> regex)
160+
private void AddPackageReference(ReadOnlySpan<char> line, string groupName, Func<Regex> regex, PackageReferenceSource source)
161161
{
162162
foreach (var valueMatch in regex().EnumerateMatches(line))
163163
{
164164
// We can't get the group from the ValueMatch, so doing it manually:
165165
var packageName = GetGroup(line, valueMatch, groupName).ToLowerInvariant();
166166
if (!string.IsNullOrEmpty(packageName))
167167
{
168-
allPackages.Add(packageName);
168+
allPackages.Add(new PackageReference(packageName, source));
169169
}
170170
}
171171
}
@@ -181,11 +181,13 @@ private void DoInitialize()
181181
foreach (ReadOnlySpan<char> line in unsafeFileReader.ReadLines(file))
182182
{
183183
// Find all the packages.
184-
AddPackageReference(line, "Include", PackageReference);
185-
186184
if (isPackagesConfig)
187185
{
188-
AddPackageReference(line, "id", LegacyPackageReference);
186+
AddPackageReference(line, "id", LegacyPackageReference, PackageReferenceSource.PackagesConfig);
187+
}
188+
else
189+
{
190+
AddPackageReference(line, "Include", PackageReference, PackageReferenceSource.SdkCsProj);
189191
}
190192

191193
// Determine if ASP.NET is used.
@@ -268,4 +270,12 @@ public IEnumerable<string> ReadLines(string file)
268270
}
269271
}
270272
}
273+
274+
public enum PackageReferenceSource
275+
{
276+
SdkCsProj,
277+
PackagesConfig
278+
}
279+
280+
public record PackageReference(string Name, PackageReferenceSource PackageReferenceSource);
271281
}

csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FrameworkPackageNames.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
44
{
55
internal static class FrameworkPackageNames
66
{
7-
public static string LatestNetFrameworkReferenceAssemblies { get; } = "microsoft.netframework.referenceassemblies.net481";
7+
public const string LatestNetFrameworkMoniker = "net481";
8+
9+
public static string LatestNetFrameworkReferenceAssemblies { get; } = $"microsoft.netframework.referenceassemblies.{LatestNetFrameworkMoniker}";
810

911
public static string AspNetCoreFramework { get; } = "microsoft.aspnetcore.app.ref";
1012

csharp/extractor/Semmle.Extraction.Tests/FileContent.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ public void TestFileContent1()
5555
// Verify
5656
Assert.False(useAspNetDlls);
5757
Assert.Equal(3, allPackages.Count);
58-
Assert.Contains("DotNetAnalyzers.DocumentationAnalyzers".ToLowerInvariant(), allPackages);
59-
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), allPackages);
60-
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), allPackages);
58+
Assert.Contains(new PackageReference("DotNetAnalyzers.DocumentationAnalyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
59+
Assert.Contains(new PackageReference("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
60+
Assert.Contains(new PackageReference("StyleCop.Analyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
6161
}
6262

6363
[Fact]
@@ -80,8 +80,8 @@ public void TestFileContent2()
8080
// Verify
8181
Assert.True(useAspNetDlls);
8282
Assert.Equal(2, allPackages.Count);
83-
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), allPackages);
84-
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), allPackages);
83+
Assert.Contains(new PackageReference("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
84+
Assert.Contains(new PackageReference("StyleCop.Analyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
8585
}
8686

8787
private static void CsProjSettingsTest(string line, bool expected, Func<FileContent, bool> func)

0 commit comments

Comments
 (0)