C# - Add default nuget feed if there's none

This commit is contained in:
Tamas Vajk
2024-02-09 23:01:00 +01:00
parent 933a8e648d
commit 26cea33cc6
3 changed files with 122 additions and 11 deletions

View File

@@ -169,13 +169,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
try
{
var nuget = new NugetPackages(sourceDir.FullName, legacyPackageDirectory, logger);
var count = nuget.InstallPackages();
if (nuget.PackageCount > 0)
using (var nuget = new NugetPackages(sourceDir.FullName, legacyPackageDirectory, logger))
{
CompilationInfos.Add(("packages.config files", nuget.PackageCount.ToString()));
CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
var count = nuget.InstallPackages();
if (nuget.PackageCount > 0)
{
CompilationInfos.Add(("packages.config files", nuget.PackageCount.ToString()));
CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
}
}
var nugetPackageDlls = legacyPackageDirectory.DirInfo.GetFiles("*.dll", new EnumerationOptions { RecurseSubdirectories = true });

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.DependencyFetching
@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// Locates packages in a source tree and downloads all of the
/// referenced assemblies to a temp folder.
/// </summary>
internal class NugetPackages
internal class NugetPackages : IDisposable
{
private readonly string? nugetExe;
private readonly Util.Logging.ILogger logger;
@@ -24,6 +24,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
public int PackageCount => packageFiles.Length;
private readonly string? backupNugetConfig;
private readonly string? nugetConfigPath;
/// <summary>
/// The computed packages directory.
/// This will be in the Temp location
@@ -47,6 +50,41 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
logger.LogInfo($"Found {packageFiles.Length} packages.config files, trying to use nuget.exe for package restore");
nugetExe = ResolveNugetExe(sourceDir);
if (HasNoPackageSource())
{
// We only modify or add a top level nuget.config file
nugetConfigPath = Path.Combine(sourceDir, "nuget.config");
try
{
if (File.Exists(nugetConfigPath))
{
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out var _);
do
{
backupNugetConfig = Path.Combine(tempFolderPath, Path.GetRandomFileName());
}
while (File.Exists(backupNugetConfig));
File.Copy(nugetConfigPath, backupNugetConfig, true);
}
else
{
File.WriteAllText(nugetConfigPath,
"""
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
</packageSources>
</configuration>
""");
}
AddDefaultPackageSource(nugetConfigPath);
}
catch (Exception e)
{
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
}
}
}
else
{
@@ -118,15 +156,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
*/
string exe, args;
if (Util.Win32.IsWindows())
if (Win32.IsWindows())
{
exe = nugetExe!;
args = string.Format("install -OutputDirectory {0} {1}", packageDirectory, package);
args = $"install -OutputDirectory {packageDirectory} {package}";
}
else
{
exe = "mono";
args = string.Format("{0} install -OutputDirectory {1} {2}", nugetExe, packageDirectory, package);
args = $"{nugetExe} install -OutputDirectory {packageDirectory} {package}";
}
var pi = new ProcessStartInfo(exe, args)
@@ -159,5 +197,75 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
return packageFiles.Count(package => TryRestoreNugetPackage(package.FullName));
}
private bool HasNoPackageSource()
{
if (Win32.IsWindows())
{
return false;
}
try
{
logger.LogInfo("Checking if default package source is available...");
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
if (stdout.All(line => line != "No sources found."))
{
return false;
}
return true;
}
catch (Exception e)
{
logger.LogWarning($"Failed to check if default package source is added: {e}");
return false;
}
}
private void RunMonoNugetCommand(string command, out IList<string> stdout)
{
var exe = "mono";
var args = $"{nugetExe} {command}";
var pi = new ProcessStartInfo(exe, args)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
var threadId = Environment.CurrentManagedThreadId;
void onOut(string s) => logger.LogInfo(s, threadId);
void onError(string s) => logger.LogError(s, threadId);
pi.ReadOutput(out stdout, onOut, onError);
}
private void AddDefaultPackageSource(string nugetConfig)
{
logger.LogInfo("Adding default package source...");
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source https://api.nuget.org/v3/index.json -ConfigFile \"{nugetConfig}\"", out var _);
}
public void Dispose()
{
if (nugetConfigPath is null)
{
return;
}
try
{
File.Delete(nugetConfigPath);
if (backupNugetConfig is not null)
{
File.Move(backupNugetConfig, nugetConfigPath);
}
}
catch (Exception exc)
{
logger.LogError($"Failed to restore original nuget.config file: {exc}");
}
}
}
}

View File

@@ -0,0 +1 @@
| /Newtonsoft.Json.6.0.4/lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.dll |