Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove custom logic of fetching dotnet dir #26851

Merged
merged 2 commits into from
Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 5 additions & 14 deletions src/Cli/dotnet/CommonOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,22 +231,13 @@ internal static string ResolveRidShorthandOptionsToRuntimeIdentifier(string os,
return $"{os}-{arch}";
}

public static string GetDotnetExeDirectory()
{
// Alternatively we could use Microsoft.DotNet.NativeWrapper.EnvironmentProvider.GetDotnetExeDirectory here
// (while injecting env resolver so that DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR is being returned as null)
// However - it first looks on PATH - which can be problematic in environment (e.g. dev) where we have installed and xcopy dotnet versions

var dotnetRootPath = Path.GetDirectoryName(Environment.ProcessPath);
// When running under test the path does not always contain "dotnet".
// The sdk folder is /d/ when run on helix because of space issues
dotnetRootPath = Path.GetFileName(dotnetRootPath).Contains("dotnet") || Path.GetFileName(dotnetRootPath).Contains("x64") || Path.GetFileName(dotnetRootPath).Equals("d") ? dotnetRootPath : Path.Combine(dotnetRootPath, "dotnet");
return dotnetRootPath;
}

public static string GetCurrentRuntimeId()
{
var dotnetRootPath = GetDotnetExeDirectory();
// Get the dotnet directory, while ignoring custom msbuild resolvers
string dotnetRootPath = Microsoft.DotNet.NativeWrapper.EnvironmentProvider.GetDotnetExeDirectory(key =>
key.Equals("DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR", StringComparison.InvariantCultureIgnoreCase)
? null
: Environment.GetEnvironmentVariable(key));
var ridFileName = "NETCoreSdkRuntimeIdentifierChain.txt";
// When running under test the Product.Version might be empty or point to version not installed in dotnetRootPath.
string runtimeIdentifierChainPath = string.IsNullOrEmpty(Product.Version) || !Directory.Exists(Path.Combine(dotnetRootPath, "sdk", Product.Version)) ?
Expand Down
17 changes: 15 additions & 2 deletions src/Cli/dotnet/commands/dotnet-new/SdkInfoProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,19 @@ namespace Microsoft.DotNet.Tools.New
{
internal class SdkInfoProvider : ISdkInfoProvider
{
private readonly Func<string> _getCurrentProcessPath;

public Guid Id { get; } = Guid.Parse("{A846C4E2-1E85-4BF5-954D-17655D916928}");

public SdkInfoProvider()
: this(null)
{ }

internal SdkInfoProvider(Func<string> getCurrentProcessPath)
{
_getCurrentProcessPath = getCurrentProcessPath;
}

public Task<string> GetCurrentVersionAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Product.Version);
Expand All @@ -29,10 +40,12 @@ public Task<string> GetCurrentVersionAsync(CancellationToken cancellationToken)
public Task<IEnumerable<string>> GetInstalledVersionsAsync(CancellationToken cancellationToken)
{
// Get the dotnet directory, while ignoring custom msbuild resolvers
string dotnetDir = Microsoft.DotNet.NativeWrapper.EnvironmentProvider.GetDotnetExeDirectory(key =>
string dotnetDir = Microsoft.DotNet.NativeWrapper.EnvironmentProvider.GetDotnetExeDirectory(
key =>
key.Equals("DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR", StringComparison.InvariantCultureIgnoreCase)
? null
: Environment.GetEnvironmentVariable(key));
: Environment.GetEnvironmentVariable(key),
_getCurrentProcessPath);

IEnumerable<string> sdks;
try
Expand Down
8 changes: 5 additions & 3 deletions src/Microsoft.DotNet.TemplateLocator/TemplateLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ public sealed class TemplateLocator
private IWorkloadResolver? _workloadResolver;
private readonly Lazy<NETCoreSdkResolver> _netCoreSdkResolver;
private readonly Func<string, string> _getEnvironmentVariable;
private readonly Func<string>? _getCurrentProcessPath;
#nullable disable
public TemplateLocator()
: this(Environment.GetEnvironmentVariable, VSSettings.Ambient, null, null)
: this(Environment.GetEnvironmentVariable, null, VSSettings.Ambient, null, null)
{
}
#nullable restore

/// <summary>
/// Test constructor
/// </summary>
public TemplateLocator(Func<string, string> getEnvironmentVariable, VSSettings vsSettings,
public TemplateLocator(Func<string, string> getEnvironmentVariable, Func<string>? getCurrentProcessPath, VSSettings vsSettings,
IWorkloadManifestProvider? workloadManifestProvider, IWorkloadResolver? workloadResolver)
{
_netCoreSdkResolver =
Expand All @@ -36,6 +37,7 @@ public TemplateLocator(Func<string, string> getEnvironmentVariable, VSSettings v
_workloadManifestProvider = workloadManifestProvider;
_workloadResolver = workloadResolver;
_getEnvironmentVariable = getEnvironmentVariable;
_getCurrentProcessPath = getCurrentProcessPath;
}

public IReadOnlyCollection<IOptionalSdkTemplatePackageInfo> GetDotnetSdkTemplatePackages(
Expand Down Expand Up @@ -63,7 +65,7 @@ public IReadOnlyCollection<IOptionalSdkTemplatePackageInfo> GetDotnetSdkTemplate

public bool TryGetDotnetSdkVersionUsedInVs(string vsVersion, out string? sdkVersion)
{
string dotnetExeDir = EnvironmentProvider.GetDotnetExeDirectory(_getEnvironmentVariable);
string dotnetExeDir = EnvironmentProvider.GetDotnetExeDirectory(_getEnvironmentVariable, _getCurrentProcessPath);

if (!Version.TryParse(vsVersion, out var parsedVsVersion))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,21 @@ public sealed class DotNetMSBuildSdkResolver : SdkResolver
public override int Priority => 5000;

private readonly Func<string, string> _getEnvironmentVariable;
private readonly Func<string> _getCurrentProcessPath;
private readonly NETCoreSdkResolver _netCoreSdkResolver;

private static CachingWorkloadResolver _staticWorkloadResolver = new CachingWorkloadResolver();

public DotNetMSBuildSdkResolver()
: this(Environment.GetEnvironmentVariable, VSSettings.Ambient)
: this(Environment.GetEnvironmentVariable, null, VSSettings.Ambient)
{
}

// Test constructor
public DotNetMSBuildSdkResolver(Func<string, string> getEnvironmentVariable, VSSettings vsSettings)
public DotNetMSBuildSdkResolver(Func<string, string> getEnvironmentVariable, Func<string> getCurrentProcessPath, VSSettings vsSettings)
{
_getEnvironmentVariable = getEnvironmentVariable;
_getCurrentProcessPath = getCurrentProcessPath;
_netCoreSdkResolver = new NETCoreSdkResolver(getEnvironmentVariable, vsSettings);
}

Expand Down Expand Up @@ -87,7 +89,7 @@ public override SdkResult Resolve(SdkReference sdkReference, SdkResolverContext

if (msbuildSdksDir == null)
{
dotnetRoot = EnvironmentProvider.GetDotnetExeDirectory(_getEnvironmentVariable);
dotnetRoot = EnvironmentProvider.GetDotnetExeDirectory(_getEnvironmentVariable, _getCurrentProcessPath);
string globalJsonStartDir = GetGlobalJsonStartDir(context);
var resolverResult = _netCoreSdkResolver.ResolveNETCoreSdkDirectory(globalJsonStartDir, context.MSBuildVersion, context.IsRunningInVisualStudio, dotnetRoot);

Expand Down
53 changes: 40 additions & 13 deletions src/Resolvers/Microsoft.DotNet.NativeWrapper/EnvironmentProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@ public class EnvironmentProvider
private IEnumerable<string> _searchPaths;

private readonly Func<string, string> _getEnvironmentVariable;
private readonly Func<string> _getCurrentProcessPath;

public EnvironmentProvider(Func<string, string> getEnvironmentVariable)
: this(getEnvironmentVariable, GetCurrentProcessPath)
{ }

public EnvironmentProvider(Func<string, string> getEnvironmentVariable, Func<string> getCurrentProcessPath)
{
_getEnvironmentVariable = getEnvironmentVariable;
_getCurrentProcessPath = getCurrentProcessPath;
}

private IEnumerable<string> SearchPaths
Expand Down Expand Up @@ -61,22 +67,24 @@ public string GetDotnetExeDirectory()
return environmentOverride;
}

var dotnetExe = GetCommandPath(Constants.DotNet);
string dotnetExe = _getCurrentProcessPath();

if (dotnetExe != null && !Interop.RunningOnWindows)
if (string.IsNullOrEmpty(dotnetExe) || !Path.GetFileNameWithoutExtension(dotnetExe)
.Equals(Constants.DotNet, StringComparison.InvariantCultureIgnoreCase))
{
// e.g. on Linux the 'dotnet' command from PATH is a symlink so we need to
// resolve it to get the actual path to the binary
dotnetExe = Interop.Unix.realpath(dotnetExe) ?? dotnetExe;
}
string dotnetExeFromPath = GetCommandPath(Constants.DotNet);

if (dotnetExeFromPath != null && !Interop.RunningOnWindows)
{
// e.g. on Linux the 'dotnet' command from PATH is a symlink so we need to
// resolve it to get the actual path to the binary
dotnetExeFromPath = Interop.Unix.realpath(dotnetExeFromPath) ?? dotnetExeFromPath;
}

if (string.IsNullOrWhiteSpace(dotnetExe))
{
#if NET6_0_OR_GREATER
dotnetExe = Environment.ProcessPath;
#else
dotnetExe = Process.GetCurrentProcess().MainModule.FileName;
#endif
if (!string.IsNullOrWhiteSpace(dotnetExeFromPath))
{
dotnetExe = dotnetExeFromPath;
}
}

return Path.GetDirectoryName(dotnetExe);
Expand All @@ -91,5 +99,24 @@ public static string GetDotnetExeDirectory(Func<string, string> getEnvironmentVa
var environmentProvider = new EnvironmentProvider(getEnvironmentVariable);
return environmentProvider.GetDotnetExeDirectory();
}

public static string GetDotnetExeDirectory(Func<string, string> getEnvironmentVariable, Func<string> getCurrentProcessPath)
{
getEnvironmentVariable ??= Environment.GetEnvironmentVariable;
getCurrentProcessPath ??= GetCurrentProcessPath;
var environmentProvider = new EnvironmentProvider(getEnvironmentVariable, getCurrentProcessPath);
return environmentProvider.GetDotnetExeDirectory();
}

private static string GetCurrentProcessPath()
{
string currentProcessPath;
#if NET6_0_OR_GREATER
currentProcessPath = Environment.ProcessPath;
#else
currentProcessPath = Process.GetCurrentProcess().MainModule.FileName;
#endif
return currentProcessPath;
}
}
}
Loading