C#: Fetch .NET in dependency manager instead of autobuilder

This commit is contained in:
Tom Hvitved
2024-02-29 10:33:24 +01:00
parent c6426d8858
commit 62382fc5a2
31 changed files with 306 additions and 373 deletions

View File

@@ -46,7 +46,7 @@ namespace Semmle.Extraction.CIL.Driver
.ToArray();
foreach (var missingRef in options.MissingReferences)
logger.Log(Severity.Info, " Missing assembly " + missingRef);
logger.LogInfo(" Missing assembly " + missingRef);
var sw = new Stopwatch();
sw.Start();

View File

@@ -45,7 +45,7 @@ namespace Semmle.Extraction.CIL
}
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{
logger.Log(Severity.Error, string.Format("Exception extracting {0}: {1}", assemblyPath, ex));
logger.LogError(string.Format("Exception extracting {0}: {1}", assemblyPath, ex));
}
}
}

View File

@@ -7,6 +7,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Semmle.Util;
using Semmle.Util.Logging;
@@ -27,8 +28,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private readonly List<string> generatedSources;
private int dotnetFrameworkVersionVariantCount = 0;
private int conflictedReferences = 0;
private readonly IDependencyOptions options;
private readonly DirectoryInfo sourceDir;
private string? dotnetPath;
private readonly IDotNet dotnet;
private readonly FileContent fileContent;
private readonly TemporaryDirectory packageDirectory;
@@ -45,11 +46,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// </summary>
/// <param name="options">Dependency fetching options</param>
/// <param name="logger">Logger for dependency fetching progress.</param>
public DependencyManager(string srcDir, IDependencyOptions options, ILogger logger)
public DependencyManager(string srcDir, ILogger logger)
{
var startTime = DateTime.Now;
this.options = options;
this.logger = logger;
this.sourceDir = new DirectoryInfo(srcDir);
@@ -59,17 +59,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
tempWorkingDirectory = new TemporaryDirectory(FileUtils.GetTemporaryWorkingDirectory(out cleanupTempWorkingDirectory));
try
{
this.dotnet = DotNet.Make(options, logger, tempWorkingDirectory);
runtimeLazy = new Lazy<Runtime>(() => new Runtime(dotnet, logger));
}
catch
{
logger.LogError("Missing dotnet CLI");
throw;
}
logger.LogInfo($"Finding files in {srcDir}...");
var allFiles = GetAllFiles().ToList();
@@ -85,6 +74,33 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
logger.LogInfo($"Found {allFiles.Count} files, {nonGeneratedSources.Count} source files, {allProjects.Count} project files, {allSolutions.Count} solution files, {dllPaths.Count} DLLs.");
void startCallback(string s, bool silent)
{
logger.Log(silent ? Severity.Debug : Severity.Info, $"\nRunning {s}");
}
void exitCallback(int ret, string msg, bool silent)
{
logger.Log(silent ? Severity.Debug : Severity.Info, $"Exit code {ret}{(string.IsNullOrEmpty(msg) ? "" : $": {msg}")}");
}
DotNet.WithDotNet(SystemBuildActions.Instance, logger, smallNonBinaryFiles, tempWorkingDirectory.ToString(), shouldCleanUp: false, ensureDotNetAvailable: true, version: null, installDir =>
{
this.dotnetPath = installDir;
return BuildScript.Success;
}).Run(SystemBuildActions.Instance, startCallback, exitCallback);
try
{
this.dotnet = DotNet.Make(logger, dotnetPath, tempWorkingDirectory);
runtimeLazy = new Lazy<Runtime>(() => new Runtime(dotnet));
}
catch
{
logger.LogError("Missing dotnet CLI");
throw;
}
RestoreNugetPackages(allNonBinaryFiles, allProjects, allSolutions, dllPaths);
// Find DLLs in the .Net / Asp.Net Framework
// This needs to come after the nuget restore, because the nuget restore might fetch the .NET Core/Framework reference assemblies.
@@ -570,15 +586,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
}
public DependencyManager(string srcDir) : this(srcDir, DependencyOptions.Default, new ConsoleLogger(Verbosity.Info, logThreadId: true)) { }
private IEnumerable<FileInfo> GetAllFiles()
{
IEnumerable<FileInfo> files = sourceDir.GetFiles("*.*", new EnumerationOptions { RecurseSubdirectories = true });
if (options.DotNetPath != null)
if (dotnetPath != null)
{
files = files.Where(f => !f.FullName.StartsWith(options.DotNetPath, StringComparison.OrdinalIgnoreCase));
files = files.Where(f => !f.FullName.StartsWith(dotnetPath, StringComparison.OrdinalIgnoreCase));
}
files = files.Where(f =>
@@ -590,12 +604,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return true;
}
logger.Log(Severity.Warning, $"File {f.FullName} could not be processed.");
logger.LogWarning($"File {f.FullName} could not be processed.");
return false;
}
catch (Exception ex)
{
logger.Log(Severity.Warning, $"File {f.FullName} could not be processed: {ex.Message}");
logger.LogWarning($"File {f.FullName} could not be processed: {ex.Message}");
return false;
}
});
@@ -651,7 +665,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
catch (AssemblyLoadException)
{
logger.Log(Severity.Warning, $"Could not load assembly information from {usedReference.Key}");
logger.LogWarning($"Could not load assembly information from {usedReference.Key}");
}
}
@@ -738,7 +752,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void AnalyseSolutions(IEnumerable<string> solutions)
{
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, solutionFile =>
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = EnvironmentVariables.GetDefaultNumberOfThreads() }, solutionFile =>
{
try
{
@@ -828,7 +842,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var successCount = 0;
var assetFiles = new List<string>();
var sync = new object();
Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, project =>
Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = EnvironmentVariables.GetDefaultNumberOfThreads() }, project =>
{
logger.LogInfo($"Restoring project {project}...");
var res = dotnet.Restore(new(project, packageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true));
@@ -928,7 +942,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var successCount = 0;
var sync = new object();
Parallel.ForEach(notYetDownloadedPackages, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, package =>
Parallel.ForEach(notYetDownloadedPackages, new ParallelOptions { MaxDegreeOfParallelism = EnvironmentVariables.GetDefaultNumberOfThreads() }, package =>
{
var success = TryRestorePackageManually(package.Name, nugetConfig, package.PackageReferenceSource);
if (!success)

View File

@@ -1,32 +0,0 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
/// <summary>
/// Dependency fetching related options.
/// </summary>
public interface IDependencyOptions
{
/// <summary>
/// The number of threads to use.
/// </summary>
int Threads { get; }
/// <summary>
/// The path to the local ".dotnet" directory, if any.
/// </summary>
string? DotNetPath { get; }
}
public class DependencyOptions : IDependencyOptions
{
public static IDependencyOptions Default => new DependencyOptions();
public int Threads { get; set; } = EnvironmentVariables.GetDefaultNumberOfThreads();
public string? DotNetPath { get; set; } = null;
}
}

View File

@@ -2,7 +2,9 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
using Semmle.Util;
using Semmle.Util.Logging;
@@ -11,29 +13,26 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// <summary>
/// Utilities to run the "dotnet" command.
/// </summary>
internal partial class DotNet : IDotNet
public partial class DotNet : IDotNet
{
private readonly IDotNetCliInvoker dotnetCliInvoker;
private readonly ILogger logger;
private readonly TemporaryDirectory? tempWorkingDirectory;
private DotNet(IDotNetCliInvoker dotnetCliInvoker, ILogger logger, TemporaryDirectory? tempWorkingDirectory = null)
{
this.logger = logger;
this.tempWorkingDirectory = tempWorkingDirectory;
this.dotnetCliInvoker = dotnetCliInvoker;
Info();
}
private DotNet(IDependencyOptions options, ILogger logger, TemporaryDirectory tempWorkingDirectory) : this(new DotNetCliInvoker(logger, Path.Combine(options.DotNetPath ?? string.Empty, "dotnet")), logger, tempWorkingDirectory) { }
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory) : this(new DotNetCliInvoker(logger, Path.Combine(dotNetPath ?? string.Empty, "dotnet")), logger, tempWorkingDirectory) { }
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ILogger logger) => new DotNet(dotnetCliInvoker, logger);
public static IDotNet Make(IDependencyOptions options, ILogger logger, TemporaryDirectory tempWorkingDirectory) => new DotNet(options, logger, tempWorkingDirectory);
public static IDotNet Make(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory) => new DotNet(logger, dotNetPath, tempWorkingDirectory);
private void Info()
{
// TODO: make sure the below `dotnet` version is matching the one specified in global.json
var res = dotnetCliInvoker.RunCommand("--info");
if (!res)
{
@@ -108,5 +107,165 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var args = $"exec {execArgs}";
return dotnetCliInvoker.RunCommand(args);
}
// The version number should be kept in sync with the version .NET version used for building the application.
public const string LatestDotNetSdkVersion = "8.0.101";
/// <summary>
/// Returns a script for downloading relevant versions of the
/// .NET SDK. The SDK(s) will be installed at <code>installDir</code>
/// (provided that the script succeeds).
/// </summary>
private static BuildScript DownloadDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, string installDir, string? version, bool ensureDotNetAvailable)
{
if (!string.IsNullOrEmpty(version))
// Specific version requested
return DownloadDotNetVersion(actions, logger, tempWorkingDirectory, shouldCleanUp, installDir, version);
// Download versions mentioned in `global.json` files
// See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
var installScript = BuildScript.Success;
var validGlobalJson = false;
foreach (var path in files.Where(p => p.EndsWith("global.json", StringComparison.Ordinal)))
{
try
{
var o = JObject.Parse(File.ReadAllText(path));
version = (string)(o?["sdk"]?["version"]!);
}
catch
{
// not a valid global.json file
continue;
}
installScript &= DownloadDotNetVersion(actions, logger, tempWorkingDirectory, shouldCleanUp, installDir, version);
validGlobalJson = true;
}
if (validGlobalJson)
{
return installScript;
}
if (ensureDotNetAvailable)
{
return DownloadDotNetVersion(actions, logger, tempWorkingDirectory, shouldCleanUp, installDir, LatestDotNetSdkVersion, needExactVersion: false);
}
return BuildScript.Failure;
}
/// <summary>
/// Returns a script for downloading a specific .NET SDK version, if the
/// version is not already installed.
///
/// See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script.
/// </summary>
private static BuildScript DownloadDotNetVersion(IBuildActions actions, ILogger logger, string tempWorkingDirectory, bool shouldCleanUp, string path, string version, bool needExactVersion = true)
{
return BuildScript.Bind(GetInstalledSdksScript(actions), (sdks, sdksRet) =>
{
if (needExactVersion && sdksRet == 0 && sdks.Count == 1 && sdks[0].StartsWith(version + " ", StringComparison.Ordinal))
{
// The requested SDK is already installed (and no other SDKs are installed), so
// no need to reinstall
return BuildScript.Failure;
}
else if (!needExactVersion && sdksRet == 0 && sdks.Count > 0)
{
// there's at least one SDK installed, so no need to reinstall
return BuildScript.Failure;
}
else if (!needExactVersion && sdksRet != 0)
{
logger.LogInfo("No .NET SDK found.");
}
logger.LogInfo($"Attempting to download .NET {version}");
if (actions.IsWindows())
{
var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version {version} -InstallDir {path}";
BuildScript GetInstall(string pwsh) =>
new CommandBuilder(actions).
RunCommand(pwsh).
Argument("-NoProfile").
Argument("-ExecutionPolicy").
Argument("unrestricted").
Argument("-Command").
Argument("\"" + psCommand + "\"").
Script;
return GetInstall("pwsh") | GetInstall("powershell");
}
else
{
var dotnetInstallPath = actions.PathCombine(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
var downloadDotNetInstallSh = BuildScript.DownloadFile(
"https://dot.net/v1/dotnet-install.sh",
dotnetInstallPath,
e => logger.LogWarning($"Failed to download 'dotnet-install.sh': {e.Message}"));
var chmod = new CommandBuilder(actions).
RunCommand("chmod").
Argument("u+x").
Argument(dotnetInstallPath);
var install = new CommandBuilder(actions).
RunCommand(dotnetInstallPath).
Argument("--channel").
Argument("release").
Argument("--version").
Argument(version).
Argument("--install-dir").
Argument(path);
var buildScript = downloadDotNetInstallSh & chmod.Script & install.Script;
if (shouldCleanUp)
{
buildScript &= BuildScript.DeleteFile(dotnetInstallPath);
}
return buildScript;
}
});
}
private static BuildScript GetInstalledSdksScript(IBuildActions actions)
{
var listSdks = new CommandBuilder(actions, silent: true).
RunCommand("dotnet").
Argument("--list-sdks");
return listSdks.Script;
}
/// <summary>
/// Returns a script that attempts to download relevant version(s) of the
/// .NET SDK, followed by running the script generated by <paramref name="f"/>.
///
/// The argument to <paramref name="f"/> is the path to the directory in which the
/// .NET SDK(s) were installed.
/// </summary>
public static BuildScript WithDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, bool ensureDotNetAvailable, string? version, Func<string?, BuildScript> f)
{
var installDir = actions.PathCombine(tempWorkingDirectory, ".dotnet");
var installScript = DownloadDotNet(actions, logger, files, tempWorkingDirectory, shouldCleanUp, installDir, version, ensureDotNetAvailable);
return BuildScript.Bind(installScript, installed =>
{
if (installed != 0)
{
// The .NET SDK was not installed, either because the installation failed or because it was already installed.
installDir = null;
}
return f(installDir);
});
}
}
}
}

View File

@@ -55,12 +55,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
else
{
logger.Log(Severity.Info, $"Invalid filter: {filter}");
logger.LogInfo($"Invalid filter: {filter}");
continue;
}
var regex = new FilePattern(filterText).RegexPattern;
logger.Log(Severity.Info, $"Filtering {(include ? "in" : "out")} files matching '{regex}'. Original glob filter: '{filter}'");
logger.LogInfo($"Filtering {(include ? "in" : "out")} files matching '{regex}'. Original glob filter: '{filter}'");
pathFilters.Add(new PathFilter(new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline), include));
}
@@ -91,7 +91,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (!include)
{
logger.Log(Severity.Info, $"Excluding '{f.FileInfo.FullName}'");
logger.LogInfo($"Excluding '{f.FileInfo.FullName}'");
}
return include;

View File

@@ -5,7 +5,7 @@ using System.Text.RegularExpressions;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal interface IDotNet
public interface IDotNet
{
RestoreResult Restore(RestoreSettings restoreSettings);
bool New(string folder);
@@ -15,9 +15,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
bool Exec(string execArgs);
}
internal record class RestoreSettings(string File, string PackageDirectory, bool ForceDotnetRefAssemblyFetching, string? PathToNugetConfig = null, bool ForceReevaluation = false);
public record class RestoreSettings(string File, string PackageDirectory, bool ForceDotnetRefAssemblyFetching, string? PathToNugetConfig = null, bool ForceReevaluation = false);
internal partial record class RestoreResult(bool Success, IList<string> Output)
public partial record class RestoreResult(bool Success, IList<string> Output)
{
private readonly Lazy<IEnumerable<string>> assetsFilePaths = new(() => GetFirstGroupOnMatch(AssetsFileRegex(), Output));
public IEnumerable<string> AssetsFilePaths => Success ? assetsFilePaths.Value : Array.Empty<string>();

View File

@@ -18,14 +18,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private const string aspNetCoreApp = "Microsoft.AspNetCore.App";
private readonly IDotNet dotNet;
private readonly ILogger logger;
private readonly Lazy<Dictionary<string, DotNetVersion>> newestRuntimes;
private Dictionary<string, DotNetVersion> NewestRuntimes => newestRuntimes.Value;
public Runtime(IDotNet dotNet, ILogger logger)
public Runtime(IDotNet dotNet)
{
this.dotNet = dotNet;
this.logger = logger;
this.newestRuntimes = new(GetNewestRuntimes);
}

View File

@@ -3,7 +3,7 @@ using Semmle.Extraction.CSharp.StubGenerator;
using Semmle.Util.Logging;
var logger = new ConsoleLogger(Verbosity.Info, logThreadId: false);
using var dependencyManager = new DependencyManager(".", DependencyOptions.Default, logger);
using var dependencyManager = new DependencyManager(".", logger);
StubGenerator.GenerateStubs(logger, dependencyManager.ReferenceFiles, "codeql_csharp_stubs");
return 0;

View File

@@ -138,7 +138,7 @@ namespace Semmle.Extraction.CSharp.Standalone
using var logger = new ConsoleLogger(options.Verbosity, logThreadId: true);
logger.Log(Severity.Info, "Extracting C# in buildless mode");
using var dependencyManager = new DependencyManager(options.SrcDir, options.Dependencies, logger);
using var dependencyManager = new DependencyManager(options.SrcDir, logger);
if (!dependencyManager.AllSourceFiles.Any())
{

View File

@@ -23,18 +23,6 @@ namespace Semmle.Extraction.CSharp.Standalone
}
}
public override bool HandleOption(string key, string value)
{
switch (key)
{
case "dotnet":
dependencies.DotNetPath = value;
return true;
default:
return base.HandleOption(key, value);
}
}
public override bool HandleArgument(string arg)
{
return true;
@@ -51,12 +39,6 @@ namespace Semmle.Extraction.CSharp.Standalone
/// </summary>
public string SrcDir { get; } = Directory.GetCurrentDirectory();
private readonly DependencyOptions dependencies = new DependencyOptions();
/// <summary>
/// Dependency fetching related options.
/// </summary>
public IDependencyOptions Dependencies => dependencies;
/// <summary>
/// Whether errors were encountered parsing the arguments.
/// </summary>

View File

@@ -36,7 +36,7 @@ public static class StubGenerator
references.Add((reference, path));
});
logger.Log(Severity.Info, $"Generating stubs for {references.Count} assemblies.");
logger.LogInfo($"Generating stubs for {references.Count} assemblies.");
var compilation = CSharpCompilation.Create(
"stubgenerator.dll",
@@ -50,7 +50,7 @@ public static class StubGenerator
});
stopWatch.Stop();
logger.Log(Severity.Info, $"Stub generation took {stopWatch.Elapsed}.");
logger.LogInfo($"Stub generation took {stopWatch.Elapsed}.");
return stubPaths.ToArray();
}

View File

@@ -47,7 +47,7 @@ namespace Semmle.Extraction.Tests
"Microsoft.NETCore.App 7.0.2 [/path/dotnet/shared/Microsoft.NETCore.App]"
};
var dotnet = new DotNetStub(listedRuntimes, null!);
var runtime = new Runtime(dotnet, new LoggerStub());
var runtime = new Runtime(dotnet);
// Execute
var runtimes = runtime.GetNewestRuntimes();
@@ -73,7 +73,7 @@ namespace Semmle.Extraction.Tests
"Microsoft.NETCore.App 8.0.0-preview.5.23280.8 [/path/dotnet/shared/Microsoft.NETCore.App]"
};
var dotnet = new DotNetStub(listedRuntimes, null!);
var runtime = new Runtime(dotnet, new LoggerStub());
var runtime = new Runtime(dotnet);
// Execute
var runtimes = runtime.GetNewestRuntimes();
@@ -96,7 +96,7 @@ namespace Semmle.Extraction.Tests
"Microsoft.NETCore.App 8.0.0-preview.5.23280.8 [/path/dotnet/shared/Microsoft.NETCore.App]"
};
var dotnet = new DotNetStub(listedRuntimes, null!);
var runtime = new Runtime(dotnet, new LoggerStub());
var runtime = new Runtime(dotnet);
// Execute
var runtimes = runtime.GetNewestRuntimes();
@@ -125,7 +125,7 @@ namespace Semmle.Extraction.Tests
@"Microsoft.WindowsDesktop.App 7.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]"
};
var dotnet = new DotNetStub(listedRuntimes, null!);
var runtime = new Runtime(dotnet, new LoggerStub());
var runtime = new Runtime(dotnet);
// Execute
var runtimes = runtime.GetNewestRuntimes();

View File

@@ -43,7 +43,7 @@ namespace Semmle.Extraction
++Errors;
if (Errors == maxErrors)
{
Logger.Log(Severity.Info, " Stopping logging after {0} errors", Errors);
Logger.LogInfo(" Stopping logging after {0} errors", Errors);
}
}

View File

@@ -227,7 +227,7 @@ namespace Semmle.Extraction
{
// If this happened, it was probably because the same file was compiled multiple times.
// In any case, this is not a fatal error.
logger.Log(Severity.Warning, "Problem archiving " + dest + ": " + ex);
logger.LogWarning("Problem archiving " + dest + ": " + ex);
}
}

View File

@@ -287,4 +287,30 @@ namespace Semmle.Util
public static IBuildActions Instance { get; } = new SystemBuildActions();
}
public static class BuildActionExtensions
{
private static void FindFiles(this IBuildActions actions, string dir, int depth, int? maxDepth, IList<(string, int)> results)
{
foreach (var f in actions.EnumerateFiles(dir))
{
results.Add((f, depth));
}
if (depth < maxDepth)
{
foreach (var d in actions.EnumerateDirectories(dir))
{
actions.FindFiles(d, depth + 1, maxDepth, results);
}
}
}
public static (string path, int depth)[] FindFiles(this IBuildActions actions, string dir, int? maxDepth)
{
var results = new List<(string, int)>();
actions.FindFiles(dir, 0, maxDepth, results);
return results.OrderBy(f => f.Item2).ToArray();
}
}
}

View File

@@ -268,7 +268,7 @@ namespace Semmle.Util
catch // lgtm[cs/catch-of-all-exceptions]
{
// Failed to late-bind a suitable library.
logger.Log(Severity.Warning, "Preserving symlinks in canonical paths");
logger.LogWarning("Preserving symlinks in canonical paths");
pathStrategy = new QueryDirectoryStrategy();
}
break;

View File

@@ -133,14 +133,14 @@ namespace Semmle.Util
var directoryName = Path.GetDirectoryName(nested);
if (directoryName is null)
{
logger.Log(Severity.Warning, "Failed to get directory name from path '" + nested + "'.");
logger.LogWarning("Failed to get directory name from path '" + nested + "'.");
throw new InvalidOperationException();
}
Directory.CreateDirectory(directoryName);
}
catch (PathTooLongException)
{
logger.Log(Severity.Warning, "Failed to create parent directory of '" + nested + "': Path too long.");
logger.LogWarning("Failed to create parent directory of '" + nested + "': Path too long.");
throw;
}
return nested;