Skip to content

Commit a79105e

Browse files
committed
C#: Use nuget.exe from the executing machine instead of always downloading it
1 parent b1329fd commit a79105e

File tree

3 files changed

+65
-31
lines changed

3 files changed

+65
-31
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ internal class EnvironmentVariableNames
6060
/// </summary>
6161
public const string FallbackNugetFeeds = "CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_FALLBACK";
6262

63+
/// <summary>
64+
/// Specifies the path to the nuget executable to be used for package restoration.
65+
/// </summary>
66+
public const string NugetExePath = "CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_PATH";
67+
6368
/// <summary>
6469
/// Specifies the location of the diagnostic directory.
6570
/// </summary>

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class FileProvider
2020
private readonly Lazy<string[]> solutions;
2121
private readonly Lazy<string[]> dlls;
2222
private readonly Lazy<string[]> nugetConfigs;
23+
private readonly Lazy<string[]> nugetExes;
2324
private readonly Lazy<string[]> globalJsons;
2425
private readonly Lazy<string[]> packagesConfigs;
2526
private readonly Lazy<string[]> razorViews;
@@ -45,6 +46,7 @@ public FileProvider(DirectoryInfo sourceDir, ILogger logger)
4546
resources = new Lazy<string[]>(() => SelectTextFileNamesByExtension("resource", ".resx"));
4647

4748
rootNugetConfig = new Lazy<string?>(() => all.SelectRootFiles(SourceDir).SelectFileNamesByName("nuget.config").FirstOrDefault());
49+
nugetExes = new Lazy<string[]>(() => all.SelectFileNamesByName("nuget.exe").ToArray());
4850
}
4951

5052
private string[] ReturnAndLogFiles(string filetype, IEnumerable<string> files)
@@ -123,6 +125,7 @@ private FileInfo[] GetAllFiles()
123125
public ICollection<string> Solutions => solutions.Value;
124126
public IEnumerable<string> Dlls => dlls.Value;
125127
public ICollection<string> NugetConfigs => nugetConfigs.Value;
128+
public ICollection<string> NugetExes => nugetExes.Value;
126129
public string? RootNugetConfig => rootNugetConfig.Value;
127130
public IEnumerable<string> GlobalJsons => globalJsons.Value;
128131
public ICollection<string> PackagesConfigs => packagesConfigs.Value;

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

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,11 @@ internal class NugetExeWrapper : IDisposable
1717
private readonly string? nugetExe;
1818
private readonly Util.Logging.ILogger logger;
1919

20-
/// <summary>
21-
/// The list of package files.
22-
/// </summary>
23-
private readonly ICollection<string> packageFiles;
24-
25-
public int PackageCount => packageFiles.Count;
20+
public int PackageCount => fileProvider.PackagesConfigs.Count;
2621

2722
private readonly string? backupNugetConfig;
2823
private readonly string? nugetConfigPath;
24+
private readonly FileProvider fileProvider;
2925

3026
/// <summary>
3127
/// The computed packages directory.
@@ -39,15 +35,14 @@ internal class NugetExeWrapper : IDisposable
3935
/// </summary>
4036
public NugetExeWrapper(FileProvider fileProvider, TemporaryDirectory packageDirectory, Util.Logging.ILogger logger)
4137
{
38+
this.fileProvider = fileProvider;
4239
this.packageDirectory = packageDirectory;
4340
this.logger = logger;
4441

45-
packageFiles = fileProvider.PackagesConfigs;
46-
47-
if (packageFiles.Count > 0)
42+
if (fileProvider.PackagesConfigs.Count > 0)
4843
{
4944
logger.LogInfo($"Found packages.config files, trying to use nuget.exe for package restore");
50-
nugetExe = ResolveNugetExe(fileProvider.SourceDir.FullName);
45+
nugetExe = ResolveNugetExe();
5146
if (HasNoPackageSource())
5247
{
5348
// We only modify or add a top level nuget.config file
@@ -87,25 +82,44 @@ public NugetExeWrapper(FileProvider fileProvider, TemporaryDirectory packageDire
8782
}
8883

8984
/// <summary>
90-
/// Tries to find the location of `nuget.exe` in the nuget directory under the directory
91-
/// containing the executing assembly. If it can't be found, it is downloaded to the
92-
/// `.nuget` directory under the source directory.
85+
/// Tries to find the location of `nuget.exe`. It looks for
86+
/// - the environment variable specifying a location,
87+
/// - files in the repository,
88+
/// - tries to resolve nuget from the PATH, or
89+
/// - downloads it if it is not found.
9390
/// </summary>
94-
/// <param name="sourceDir">The source directory.</param>
95-
private string ResolveNugetExe(string sourceDir)
91+
private string ResolveNugetExe()
9692
{
97-
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location;
98-
var directory = Path.GetDirectoryName(currentAssembly)
99-
?? throw new FileNotFoundException($"Directory path '{currentAssembly}' of current assembly is null");
93+
var envVarPath = Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetExePath);
94+
if (!string.IsNullOrEmpty(envVarPath))
95+
{
96+
logger.LogInfo($"Using nuget.exe from environment variable: '{envVarPath}'");
97+
return envVarPath;
98+
}
10099

101-
var nuget = Path.Combine(directory, "nuget", "nuget.exe");
102-
if (File.Exists(nuget))
100+
var nugetExesInRepo = fileProvider.NugetExes;
101+
if (nugetExesInRepo.Count > 1)
103102
{
104-
logger.LogInfo($"Found nuget.exe at {nuget}");
105-
return nuget;
103+
logger.LogInfo($"Found multiple nuget.exe files in the repository: {string.Join(", ", nugetExesInRepo.OrderBy(s => s))}");
106104
}
107105

108-
return DownloadNugetExe(sourceDir);
106+
if (nugetExesInRepo.Count > 0)
107+
{
108+
var path = nugetExesInRepo.First();
109+
logger.LogInfo($"Using nuget.exe from path '{path}'");
110+
return path;
111+
}
112+
113+
var executableName = Win32.IsWindows() ? "nuget.exe" : "nuget";
114+
var nugetPath = FileUtils.FindProgramOnPath(executableName);
115+
if (nugetPath is not null)
116+
{
117+
nugetPath = Path.Combine(nugetPath, executableName);
118+
logger.LogInfo($"Using nuget.exe from PATH: {nugetPath}");
119+
return nugetPath;
120+
}
121+
122+
return DownloadNugetExe(fileProvider.SourceDir.FullName);
109123
}
110124

111125
private string DownloadNugetExe(string sourceDir)
@@ -135,6 +149,8 @@ private string DownloadNugetExe(string sourceDir)
135149
}
136150
}
137151

152+
private bool RunWithMono => !Win32.IsWindows() && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
153+
138154
/// <summary>
139155
/// Restore all files in a specified package.
140156
/// </summary>
@@ -150,15 +166,15 @@ private bool TryRestoreNugetPackage(string package)
150166
*/
151167

152168
string exe, args;
153-
if (Win32.IsWindows())
169+
if (RunWithMono)
154170
{
155-
exe = nugetExe!;
156-
args = $"install -OutputDirectory {packageDirectory} {package}";
171+
exe = "mono";
172+
args = $"{nugetExe} install -OutputDirectory {packageDirectory} {package}";
157173
}
158174
else
159175
{
160-
exe = "mono";
161-
args = $"{nugetExe} install -OutputDirectory {packageDirectory} {package}";
176+
exe = nugetExe!;
177+
args = $"install -OutputDirectory {packageDirectory} {package}";
162178
}
163179

164180
var pi = new ProcessStartInfo(exe, args)
@@ -189,7 +205,7 @@ private bool TryRestoreNugetPackage(string package)
189205
/// </summary>
190206
public int InstallPackages()
191207
{
192-
return packageFiles.Count(package => TryRestoreNugetPackage(package));
208+
return fileProvider.PackagesConfigs.Count(package => TryRestoreNugetPackage(package));
193209
}
194210

195211
private bool HasNoPackageSource()
@@ -219,8 +235,18 @@ private bool HasNoPackageSource()
219235

220236
private void RunMonoNugetCommand(string command, out IList<string> stdout)
221237
{
222-
var exe = "mono";
223-
var args = $"{nugetExe} {command}";
238+
string exe, args;
239+
if (RunWithMono)
240+
{
241+
exe = "mono";
242+
args = $"{nugetExe} {command}";
243+
}
244+
else
245+
{
246+
exe = nugetExe!;
247+
args = command;
248+
}
249+
224250
var pi = new ProcessStartInfo(exe, args)
225251
{
226252
RedirectStandardOutput = true,

0 commit comments

Comments
 (0)