Skip to content

Commit de13ff6

Browse files
authored
Merge pull request github#15577 from tamasvajk/feature/missing-nuget-sources
C# - Add default nuget feed if there's none
2 parents faefa05 + 888f47c commit de13ff6

File tree

28 files changed

+195
-28
lines changed

28 files changed

+195
-28
lines changed

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,15 @@ private void RestoreNugetPackages(List<FileInfo> allNonBinaryFiles, IEnumerable<
169169
{
170170
try
171171
{
172-
var nuget = new NugetPackages(sourceDir.FullName, legacyPackageDirectory, logger);
173-
var count = nuget.InstallPackages();
174-
175-
if (nuget.PackageCount > 0)
172+
using (var nuget = new NugetPackages(sourceDir.FullName, legacyPackageDirectory, logger))
176173
{
177-
CompilationInfos.Add(("packages.config files", nuget.PackageCount.ToString()));
178-
CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
174+
var count = nuget.InstallPackages();
175+
176+
if (nuget.PackageCount > 0)
177+
{
178+
CompilationInfos.Add(("packages.config files", nuget.PackageCount.ToString()));
179+
CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
180+
}
179181
}
180182

181183
var nugetPackageDlls = legacyPackageDirectory.DirInfo.GetFiles("*.dll", new EnumerationOptions { RecurseSubdirectories = true });

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

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.IO;
45
using System.Linq;
5-
using Microsoft.Build.Framework;
66
using Semmle.Util;
77

88
namespace Semmle.Extraction.CSharp.DependencyFetching
@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
1212
/// Locates packages in a source tree and downloads all of the
1313
/// referenced assemblies to a temp folder.
1414
/// </summary>
15-
internal class NugetPackages
15+
internal class NugetPackages : IDisposable
1616
{
1717
private readonly string? nugetExe;
1818
private readonly Util.Logging.ILogger logger;
@@ -24,6 +24,9 @@ internal class NugetPackages
2424

2525
public int PackageCount => packageFiles.Length;
2626

27+
private readonly string? backupNugetConfig;
28+
private readonly string? nugetConfigPath;
29+
2730
/// <summary>
2831
/// The computed packages directory.
2932
/// This will be in the Temp location
@@ -47,6 +50,41 @@ public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory, Util
4750
{
4851
logger.LogInfo($"Found {packageFiles.Length} packages.config files, trying to use nuget.exe for package restore");
4952
nugetExe = ResolveNugetExe(sourceDir);
53+
if (HasNoPackageSource())
54+
{
55+
// We only modify or add a top level nuget.config file
56+
nugetConfigPath = Path.Combine(sourceDir, "nuget.config");
57+
try
58+
{
59+
if (File.Exists(nugetConfigPath))
60+
{
61+
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out var _);
62+
63+
do
64+
{
65+
backupNugetConfig = Path.Combine(tempFolderPath, Path.GetRandomFileName());
66+
}
67+
while (File.Exists(backupNugetConfig));
68+
File.Copy(nugetConfigPath, backupNugetConfig, true);
69+
}
70+
else
71+
{
72+
File.WriteAllText(nugetConfigPath,
73+
"""
74+
<?xml version="1.0" encoding="utf-8"?>
75+
<configuration>
76+
<packageSources>
77+
</packageSources>
78+
</configuration>
79+
""");
80+
}
81+
AddDefaultPackageSource(nugetConfigPath);
82+
}
83+
catch (Exception e)
84+
{
85+
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
86+
}
87+
}
5088
}
5189
else
5290
{
@@ -118,15 +156,15 @@ private bool TryRestoreNugetPackage(string package)
118156
*/
119157

120158
string exe, args;
121-
if (Util.Win32.IsWindows())
159+
if (Win32.IsWindows())
122160
{
123161
exe = nugetExe!;
124-
args = string.Format("install -OutputDirectory {0} {1}", packageDirectory, package);
162+
args = $"install -OutputDirectory {packageDirectory} {package}";
125163
}
126164
else
127165
{
128166
exe = "mono";
129-
args = string.Format("{0} install -OutputDirectory {1} {2}", nugetExe, packageDirectory, package);
167+
args = $"{nugetExe} install -OutputDirectory {packageDirectory} {package}";
130168
}
131169

132170
var pi = new ProcessStartInfo(exe, args)
@@ -159,5 +197,87 @@ public int InstallPackages()
159197
{
160198
return packageFiles.Count(package => TryRestoreNugetPackage(package.FullName));
161199
}
200+
201+
private bool HasNoPackageSource()
202+
{
203+
if (Win32.IsWindows())
204+
{
205+
return false;
206+
}
207+
208+
try
209+
{
210+
logger.LogInfo("Checking if default package source is available...");
211+
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
212+
if (stdout.All(line => line != "No sources found."))
213+
{
214+
return false;
215+
}
216+
217+
return true;
218+
}
219+
catch (Exception e)
220+
{
221+
logger.LogWarning($"Failed to check if default package source is added: {e}");
222+
return false;
223+
}
224+
}
225+
226+
private void RunMonoNugetCommand(string command, out IList<string> stdout)
227+
{
228+
var exe = "mono";
229+
var args = $"{nugetExe} {command}";
230+
var pi = new ProcessStartInfo(exe, args)
231+
{
232+
RedirectStandardOutput = true,
233+
RedirectStandardError = true,
234+
UseShellExecute = false
235+
};
236+
237+
var threadId = Environment.CurrentManagedThreadId;
238+
void onOut(string s) => logger.LogInfo(s, threadId);
239+
void onError(string s) => logger.LogError(s, threadId);
240+
pi.ReadOutput(out stdout, onOut, onError);
241+
}
242+
243+
private void AddDefaultPackageSource(string nugetConfig)
244+
{
245+
logger.LogInfo("Adding default package source...");
246+
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source https://api.nuget.org/v3/index.json -ConfigFile \"{nugetConfig}\"", out var _);
247+
}
248+
249+
public void Dispose()
250+
{
251+
if (nugetConfigPath is null)
252+
{
253+
return;
254+
}
255+
256+
try
257+
{
258+
if (backupNugetConfig is null)
259+
{
260+
logger.LogInfo("Removing nuget.config file");
261+
File.Delete(nugetConfigPath);
262+
return;
263+
}
264+
265+
logger.LogInfo("Reverting nuget.config file content");
266+
// The content of the original nuget.config file is reverted without changing the file's attributes or casing:
267+
using (var backup = File.OpenRead(backupNugetConfig))
268+
using (var current = File.OpenWrite(nugetConfigPath))
269+
{
270+
current.SetLength(0); // Truncate file
271+
backup.CopyTo(current); // Restore original content
272+
}
273+
274+
logger.LogInfo("Deleting backup nuget.config file");
275+
File.Delete(backupNugetConfig);
276+
}
277+
catch (Exception exc)
278+
{
279+
logger.LogError($"Failed to restore original nuget.config file: {exc}");
280+
}
281+
}
162282
}
163283
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from create_database_utils import *
22

3-
run_codeql_database_create([], lang="csharp", extra_args=["--extractor-option=cil=false"])
3+
run_codeql_database_create([], lang="csharp")
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from create_database_utils import *
22

3-
run_codeql_database_create(['dotnet build'], lang="csharp", extra_args=["--extractor-option=cil=false"])
3+
run_codeql_database_create(['dotnet build'], lang="csharp")
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import os
22
from create_database_utils import *
33

4-
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true", "--extractor-option=cil=false"])
4+
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true"])

csharp/ql/integration-tests/all-platforms/cshtml_standalone_disabled/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
from create_database_utils import *
33

44
os.environ['CODEQL_EXTRACTOR_CSHARP_STANDALONE_EXTRACT_WEB_VIEWS'] = 'false'
5-
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true", "--extractor-option=cil=false"])
5+
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true"])
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import os
22
from create_database_utils import *
33

4-
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true", "--extractor-option=cil=false"])
4+
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true"])
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import os
22
from create_database_utils import *
33

4-
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true", "--extractor-option=cil=false"])
4+
run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true"])
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from create_database_utils import *
22

3-
run_codeql_database_create(['dotnet build'], lang="csharp", extra_args=["--extractor-option=cil=false"])
3+
run_codeql_database_create(['dotnet build'], lang="csharp")
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from create_database_utils import *
22

3-
run_codeql_database_create([], lang="csharp", extra_args=["--extractor-option=buildless=true", "--extractor-option=cil=false"])
3+
run_codeql_database_create([], lang="csharp", extra_args=["--extractor-option=buildless=true"])

0 commit comments

Comments
 (0)