Tools shim maker and env path handling (#8085)

* Tools shim maker and env path handling

Includes component:

* Given executable, create shim (all three OSs)
* Add executable path to Env PATH during first run
* including manual instruction when there is no access
This commit is contained in:
William Lee 2017-11-27 10:45:43 -08:00 committed by GitHub
parent c17ffbf7e8
commit cc80ed43e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 1149 additions and 79 deletions

View file

@ -232,6 +232,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Msbuild.Tests.Utilities", "
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackageObtainer.Tests", "test\Microsoft.DotNet.ToolPackageObtainer.Tests\Microsoft.DotNet.ToolPackageObtainer.Tests.csproj", "{F0D50831-9468-4ACB-8FD8-E9883DD553FB}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackageObtainer.Tests", "test\Microsoft.DotNet.ToolPackageObtainer.Tests\Microsoft.DotNet.ToolPackageObtainer.Tests.csproj", "{F0D50831-9468-4ACB-8FD8-E9883DD553FB}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShimMaker.Tests", "test\Microsoft.DotNet.ShellShimMaker.Tests\Microsoft.DotNet.ShellShimMaker.Tests.csproj", "{20376E28-68EB-4BE5-81A5-51500F1235E2}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -1640,6 +1642,30 @@ Global
{F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x86.Build.0 = Release|Any CPU {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x64.ActiveCfg = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x64.Build.0 = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x86.ActiveCfg = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x86.Build.0 = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x86.Build.0 = Debug|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|Any CPU.Build.0 = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x64.ActiveCfg = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x64.Build.0 = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x86.ActiveCfg = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x86.Build.0 = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1713,6 +1739,7 @@ Global
{44759218-B558-4AF0-8991-515F1100DCF5} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {44759218-B558-4AF0-8991-515F1100DCF5} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{E7C72EF2-8480-48B4-AAE8-A596F1A6048E} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {E7C72EF2-8480-48B4-AAE8-A596F1A6048E} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{F0D50831-9468-4ACB-8FD8-E9883DD553FB} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {F0D50831-9468-4ACB-8FD8-E9883DD553FB} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{20376E28-68EB-4BE5-81A5-51500F1235E2} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B526D2CE-EE2D-4AD4-93EF-1867D90FF1F5} SolutionGuid = {B526D2CE-EE2D-4AD4-93EF-1867D90FF1F5}

View file

@ -13,9 +13,10 @@ done
REPO_ROOT="$( cd -P "$( dirname "$SOURCE" )/../" && pwd )" REPO_ROOT="$( cd -P "$( dirname "$SOURCE" )/../" && pwd )"
if [ "$uname" = "Darwin" ] uname=$(uname)
if [ "$(uname)" == "Darwin" ]
then then
RID=osx-x64 RID=osx.10.13-x64
else else
RID=linux-x64 RID=linux-x64
fi fi

View file

@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Cli.Utils
{
public interface IEnvironmentPath: IEnvironmentPathInstruction
{
void AddPackageExecutablePathToUserPath();
}
}

View file

@ -0,0 +1,7 @@
namespace Microsoft.DotNet.Cli.Utils
{
public interface IEnvironmentPathInstruction
{
void PrintAddPathInstructionIfPathDoesNotExist();
}
}

View file

@ -12,3 +12,4 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.DotNet.TestFramework, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.TestFramework, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectJsonMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectJsonMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShimMaker.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View file

@ -1,33 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.PlatformAbstractions;
using NuGet.Common;
namespace Microsoft.DotNet.Configurer
{
public class CliFallbackFolderPathCalculator
{
public string CliFallbackFolderPath =>
Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_FALLBACKFOLDER") ??
Path.Combine(new DirectoryInfo(AppContext.BaseDirectory).Parent.FullName, "NuGetFallbackFolder");
public string DotnetUserProfileFolderPath
{
get
{
string profileDir = Environment.GetEnvironmentVariable(
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME");
return Path.Combine(profileDir, ".dotnet");
}
}
public string NuGetUserSettingsDirectory =>
NuGetEnvironment.GetFolderPath(NuGetFolderPath.UserSettingsDirectory);
}
}

View file

@ -0,0 +1,38 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.PlatformAbstractions;
using NuGet.Common;
namespace Microsoft.DotNet.Configurer
{
public class CliFolderPathCalculator
{
private const string ToolsFolderName = "tools";
private const string DotnetProfileDirectoryName = ".dotnet";
public string CliFallbackFolderPath => Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_FALLBACKFOLDER") ??
Path.Combine(new DirectoryInfo(AppContext.BaseDirectory).Parent.FullName, "NuGetFallbackFolder");
public string ExecutablePackagesPath => Path.Combine(DotnetUserProfileFolderPath, ToolsFolderName) ;
public readonly string ExecutablePackagesPathOnMacEnvPath = $"~/{DotnetProfileDirectoryName}/{ToolsFolderName}";
public static string DotnetUserProfileFolderPath
{
get
{
string profileDir = Environment.GetEnvironmentVariable(
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME");
return Path.Combine(profileDir, DotnetProfileDirectoryName);
}
}
public string NuGetUserSettingsDirectory =>
NuGetEnvironment.GetFolderPath(NuGetFolderPath.UserSettingsDirectory);
}
}

View file

@ -1,7 +1,9 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. // Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.EnvironmentAbstractions;
@ -15,6 +17,7 @@ namespace Microsoft.DotNet.Configurer
private INuGetCacheSentinel _nugetCacheSentinel; private INuGetCacheSentinel _nugetCacheSentinel;
private IFirstTimeUseNoticeSentinel _firstTimeUseNoticeSentinel; private IFirstTimeUseNoticeSentinel _firstTimeUseNoticeSentinel;
private string _cliFallbackFolderPath; private string _cliFallbackFolderPath;
private readonly IEnvironmentPath _pathAdder;
public DotnetFirstTimeUseConfigurer( public DotnetFirstTimeUseConfigurer(
INuGetCachePrimer nugetCachePrimer, INuGetCachePrimer nugetCachePrimer,
@ -22,7 +25,8 @@ namespace Microsoft.DotNet.Configurer
IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel,
IEnvironmentProvider environmentProvider, IEnvironmentProvider environmentProvider,
IReporter reporter, IReporter reporter,
string cliFallbackFolderPath) string cliFallbackFolderPath,
IEnvironmentPath pathAdder)
{ {
_nugetCachePrimer = nugetCachePrimer; _nugetCachePrimer = nugetCachePrimer;
_nugetCacheSentinel = nugetCacheSentinel; _nugetCacheSentinel = nugetCacheSentinel;
@ -30,10 +34,13 @@ namespace Microsoft.DotNet.Configurer
_environmentProvider = environmentProvider; _environmentProvider = environmentProvider;
_reporter = reporter; _reporter = reporter;
_cliFallbackFolderPath = cliFallbackFolderPath; _cliFallbackFolderPath = cliFallbackFolderPath;
_pathAdder = pathAdder ?? throw new ArgumentNullException(nameof(pathAdder));
} }
public void Configure() public void Configure()
{ {
AddPackageExecutablePath();
if (ShouldPrintFirstTimeUseNotice()) if (ShouldPrintFirstTimeUseNotice())
{ {
PrintFirstTimeUseNotice(); PrintFirstTimeUseNotice();
@ -54,6 +61,23 @@ namespace Microsoft.DotNet.Configurer
} }
} }
private void AddPackageExecutablePath()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (!_firstTimeUseNoticeSentinel.Exists())
{
// Invoke when Windows first run
_pathAdder.AddPackageExecutablePathToUserPath();
}
}
else
{
// Invoke during installer, otherwise, _pathAdder will be no op object that this point
_pathAdder.AddPackageExecutablePathToUserPath();
}
}
private bool ShouldPrintFirstTimeUseNotice() private bool ShouldPrintFirstTimeUseNotice()
{ {
var showFirstTimeUseNotice = var showFirstTimeUseNotice =

View file

@ -19,9 +19,9 @@ namespace Microsoft.DotNet.Configurer
private string SentinelPath => Path.Combine(_dotnetUserProfileFolderPath, SENTINEL); private string SentinelPath => Path.Combine(_dotnetUserProfileFolderPath, SENTINEL);
public FirstTimeUseNoticeSentinel(CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator) : public FirstTimeUseNoticeSentinel(CliFolderPathCalculator cliFolderPathCalculator) :
this( this(
cliFallbackFolderPathCalculator.DotnetUserProfileFolderPath, CliFolderPathCalculator.DotnetUserProfileFolderPath,
FileSystemWrapper.Default.File, FileSystemWrapper.Default.File,
FileSystemWrapper.Default.Directory) FileSystemWrapper.Default.Directory)
{ {

View file

@ -17,15 +17,15 @@ namespace Microsoft.DotNet.Configurer
private readonly INuGetCacheSentinel _nuGetCacheSentinel; private readonly INuGetCacheSentinel _nuGetCacheSentinel;
private readonly CliFallbackFolderPathCalculator _cliFallbackFolderPathCalculator; private readonly CliFolderPathCalculator _cliFolderPathCalculator;
public NuGetCachePrimer( public NuGetCachePrimer(
INuGetPackagesArchiver nugetPackagesArchiver, INuGetPackagesArchiver nugetPackagesArchiver,
INuGetCacheSentinel nuGetCacheSentinel, INuGetCacheSentinel nuGetCacheSentinel,
CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator) CliFolderPathCalculator cliFolderPathCalculator)
: this(nugetPackagesArchiver, : this(nugetPackagesArchiver,
nuGetCacheSentinel, nuGetCacheSentinel,
cliFallbackFolderPathCalculator, cliFolderPathCalculator,
FileSystemWrapper.Default.File) FileSystemWrapper.Default.File)
{ {
} }
@ -33,14 +33,14 @@ namespace Microsoft.DotNet.Configurer
internal NuGetCachePrimer( internal NuGetCachePrimer(
INuGetPackagesArchiver nugetPackagesArchiver, INuGetPackagesArchiver nugetPackagesArchiver,
INuGetCacheSentinel nuGetCacheSentinel, INuGetCacheSentinel nuGetCacheSentinel,
CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator, CliFolderPathCalculator cliFolderPathCalculator,
IFile file) IFile file)
{ {
_nugetPackagesArchiver = nugetPackagesArchiver; _nugetPackagesArchiver = nugetPackagesArchiver;
_nuGetCacheSentinel = nuGetCacheSentinel; _nuGetCacheSentinel = nuGetCacheSentinel;
_cliFallbackFolderPathCalculator = cliFallbackFolderPathCalculator; _cliFolderPathCalculator = cliFolderPathCalculator;
_file = file; _file = file;
} }
@ -52,7 +52,7 @@ namespace Microsoft.DotNet.Configurer
return; return;
} }
var nuGetFallbackFolder = _cliFallbackFolderPathCalculator.CliFallbackFolderPath; var nuGetFallbackFolder = _cliFolderPathCalculator.CliFallbackFolderPath;
_nugetPackagesArchiver.ExtractArchive(nuGetFallbackFolder); _nugetPackagesArchiver.ExtractArchive(nuGetFallbackFolder);

View file

@ -27,8 +27,8 @@ namespace Microsoft.DotNet.Configurer
private Stream InProgressSentinel { get; set; } private Stream InProgressSentinel { get; set; }
public NuGetCacheSentinel(CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator) : public NuGetCacheSentinel(CliFolderPathCalculator cliFolderPathCalculator) :
this(cliFallbackFolderPathCalculator.CliFallbackFolderPath, this(cliFolderPathCalculator.CliFallbackFolderPath,
FileSystemWrapper.Default.File, FileSystemWrapper.Default.File,
FileSystemWrapper.Default.Directory) FileSystemWrapper.Default.Directory)
{ {

View file

@ -14,9 +14,9 @@ namespace Microsoft.DotNet.Configurer
private readonly IDirectory _directory; private readonly IDirectory _directory;
private string _dotnetUserProfileFolderPath; private string _dotnetUserProfileFolderPath;
public UserLevelCacheWriter(CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator) : public UserLevelCacheWriter(CliFolderPathCalculator cliFolderPathCalculator) :
this( this(
cliFallbackFolderPathCalculator.DotnetUserProfileFolderPath, CliFolderPathCalculator.DotnetUserProfileFolderPath,
FileSystemWrapper.Default.File, FileSystemWrapper.Default.File,
FileSystemWrapper.Default.Directory) FileSystemWrapper.Default.Directory)
{ {

View file

@ -6,6 +6,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyMetadataAttribute("Serviceable", "True")] [assembly: AssemblyMetadataAttribute("Serviceable", "True")]
[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("dotnet, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Configurer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Configurer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
@ -13,3 +14,4 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
[assembly: InternalsVisibleTo("dotnet-test.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")] [assembly: InternalsVisibleTo("dotnet-test.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShimMaker.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View file

@ -4,15 +4,19 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Telemetry; using Microsoft.DotNet.Cli.Telemetry;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Configurer; using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.PlatformAbstractions; using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.DotNet.ShellShimMaker;
using Microsoft.DotNet.Tools.Help; using Microsoft.DotNet.Tools.Help;
using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Frameworks; using NuGet.Frameworks;
using Command = Microsoft.DotNet.Cli.Utils.Command; using Command = Microsoft.DotNet.Cli.Utils.Command;
using RuntimeEnvironment = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment;
namespace Microsoft.DotNet.Cli namespace Microsoft.DotNet.Cli
{ {
@ -80,8 +84,9 @@ namespace Microsoft.DotNet.Cli
var success = true; var success = true;
var command = string.Empty; var command = string.Empty;
var lastArg = 0; var lastArg = 0;
var cliFallbackFolderPathCalculator = new CliFallbackFolderPathCalculator(); var cliFallbackFolderPathCalculator = new CliFolderPathCalculator();
TopLevelCommandParserResult topLevelCommandParserResult = TopLevelCommandParserResult.Empty; TopLevelCommandParserResult topLevelCommandParserResult = TopLevelCommandParserResult.Empty;
using (INuGetCacheSentinel nugetCacheSentinel = new NuGetCacheSentinel(cliFallbackFolderPathCalculator)) using (INuGetCacheSentinel nugetCacheSentinel = new NuGetCacheSentinel(cliFallbackFolderPathCalculator))
using (IFirstTimeUseNoticeSentinel disposableFirstTimeUseNoticeSentinel = using (IFirstTimeUseNoticeSentinel disposableFirstTimeUseNoticeSentinel =
new FirstTimeUseNoticeSentinel(cliFallbackFolderPathCalculator)) new FirstTimeUseNoticeSentinel(cliFallbackFolderPathCalculator))
@ -120,22 +125,24 @@ namespace Microsoft.DotNet.Cli
{ {
// It's the command, and we're done! // It's the command, and we're done!
command = args[lastArg]; command = args[lastArg];
if (string.IsNullOrEmpty(command)) if (string.IsNullOrEmpty(command))
{ {
command = "help"; command = "help";
} }
topLevelCommandParserResult = new TopLevelCommandParserResult(args[lastArg]); topLevelCommandParserResult = new TopLevelCommandParserResult(command);
var hasSuperUserAccess = false;
if (IsDotnetBeingInvokedFromNativeInstaller(topLevelCommandParserResult)) if (IsDotnetBeingInvokedFromNativeInstaller(topLevelCommandParserResult))
{ {
firstTimeUseNoticeSentinel = new NoOpFirstTimeUseNoticeSentinel(); firstTimeUseNoticeSentinel = new NoOpFirstTimeUseNoticeSentinel();
hasSuperUserAccess = true;
} }
ConfigureDotNetForFirstTimeUse( ConfigureDotNetForFirstTimeUse(
nugetCacheSentinel, nugetCacheSentinel,
firstTimeUseNoticeSentinel, firstTimeUseNoticeSentinel,
cliFallbackFolderPathCalculator); cliFallbackFolderPathCalculator,
hasSuperUserAccess);
break; break;
} }
@ -197,24 +204,29 @@ namespace Microsoft.DotNet.Cli
private static void ConfigureDotNetForFirstTimeUse( private static void ConfigureDotNetForFirstTimeUse(
INuGetCacheSentinel nugetCacheSentinel, INuGetCacheSentinel nugetCacheSentinel,
IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel,
CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator) CliFolderPathCalculator cliFolderPathCalculator,
bool hasSuperUserAccess)
{ {
var environmentProvider = new EnvironmentProvider();
using (PerfTrace.Current.CaptureTiming()) using (PerfTrace.Current.CaptureTiming())
{ {
var nugetPackagesArchiver = new NuGetPackagesArchiver(); var nugetPackagesArchiver = new NuGetPackagesArchiver();
var environmentProvider = new EnvironmentProvider(); var environmentPath =
EnvironmentPathFactory.CreateEnvironmentPath(cliFolderPathCalculator, hasSuperUserAccess, environmentProvider);
var commandFactory = new DotNetCommandFactory(alwaysRunOutOfProc: true); var commandFactory = new DotNetCommandFactory(alwaysRunOutOfProc: true);
var nugetCachePrimer = new NuGetCachePrimer( var nugetCachePrimer = new NuGetCachePrimer(
nugetPackagesArchiver, nugetPackagesArchiver,
nugetCacheSentinel, nugetCacheSentinel,
cliFallbackFolderPathCalculator); cliFolderPathCalculator);
var dotnetConfigurer = new DotnetFirstTimeUseConfigurer( var dotnetConfigurer = new DotnetFirstTimeUseConfigurer(
nugetCachePrimer, nugetCachePrimer,
nugetCacheSentinel, nugetCacheSentinel,
firstTimeUseNoticeSentinel, firstTimeUseNoticeSentinel,
environmentProvider, environmentProvider,
Reporter.Output, Reporter.Output,
cliFallbackFolderPathCalculator.CliFallbackFolderPath); cliFolderPathCalculator.CliFallbackFolderPath,
environmentPath);
dotnetConfigurer.Configure(); dotnetConfigurer.Configure();
} }

View file

@ -17,4 +17,5 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("dotnet-sln-remove.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("dotnet-sln-remove.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("dotnet-msbuild.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("dotnet-msbuild.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("dotnet-run.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("dotnet-run.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackageObtainer.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackageObtainer.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShimMaker.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View file

@ -0,0 +1,22 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.ShellShimMaker
{
public class DoNothingEnvironmentPath : IEnvironmentPath
{
public void AddPackageExecutablePathToUserPath()
{
}
public void PrintAddPathInstructionIfPathDoesNotExist()
{
}
}
}

View file

@ -0,0 +1,66 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Xml.Xsl;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Configurer;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.ShellShimMaker
{
internal static class EnvironmentPathFactory
{
public static IEnvironmentPath CreateEnvironmentPath(
CliFolderPathCalculator cliFolderPathCalculator = null,
bool hasSuperUserAccess = false,
IEnvironmentProvider environmentProvider = null)
{
if (cliFolderPathCalculator == null)
{
cliFolderPathCalculator = new CliFolderPathCalculator();
}
if (environmentProvider == null)
{
environmentProvider = new EnvironmentProvider();
}
IEnvironmentPath environmentPath = new DoNothingEnvironmentPath();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
environmentPath = new WindowsEnvironmentPath(
cliFolderPathCalculator.ExecutablePackagesPath,
Reporter.Output,
environmentProvider);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && hasSuperUserAccess)
{
environmentPath = new LinuxEnvironmentPath(
cliFolderPathCalculator.ExecutablePackagesPath,
Reporter.Output,
environmentProvider, new FileWrapper());
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && hasSuperUserAccess)
{
environmentPath = new OSXEnvironmentPath(
packageExecutablePathWithTilde: cliFolderPathCalculator.ExecutablePackagesPathOnMacEnvPath,
fullPackageExecutablePath: cliFolderPathCalculator.ExecutablePackagesPath,
reporter: Reporter.Output,
environmentProvider: environmentProvider,
fileSystem: new FileWrapper());
}
return environmentPath;
}
public static IEnvironmentPathInstruction CreateEnvironmentPathInstruction(
CliFolderPathCalculator cliFolderPathCalculator = null,
IEnvironmentProvider environmentProvider = null)
{
return CreateEnvironmentPath(cliFolderPathCalculator, true, environmentProvider);
}
}
}

View file

@ -0,0 +1,78 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.ShellShimMaker
{
internal class LinuxEnvironmentPath : IEnvironmentPath
{
private readonly IFile _fileSystem;
private readonly IEnvironmentProvider _environmentProvider;
private readonly IReporter _reporter;
private const string PathName = "PATH";
private readonly string _packageExecutablePath;
private readonly string _profiledDotnetCliToolsPath
= Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_LINUX_PROFILED_PATH")
?? @"/etc/profile.d/dotnet-cli-tools-bin-path.sh";
internal LinuxEnvironmentPath(
string packageExecutablePath,
IReporter reporter,
IEnvironmentProvider environmentProvider,
IFile fileSystem)
{
_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
_environmentProvider
= environmentProvider ?? throw new ArgumentNullException(nameof(environmentProvider));
_reporter
= reporter ?? throw new ArgumentNullException(nameof(reporter));
_packageExecutablePath
= packageExecutablePath ?? throw new ArgumentNullException(nameof(packageExecutablePath));
}
public void AddPackageExecutablePathToUserPath()
{
if (PackageExecutablePathExists())
{
return;
}
var script = $"export PATH=\"$PATH:{_packageExecutablePath}\"";
_fileSystem.WriteAllText(_profiledDotnetCliToolsPath, script);
}
private bool PackageExecutablePathExists()
{
return _environmentProvider
.GetEnvironmentVariable(PathName)
.Split(':').Contains(_packageExecutablePath);
}
public void PrintAddPathInstructionIfPathDoesNotExist()
{
if (!PackageExecutablePathExists())
{
if (_fileSystem.Exists(_profiledDotnetCliToolsPath))
{
_reporter.WriteLine("Since you just installed the .NET Core SDK, you will need to logout or restart your session before running the tool you installed.");
}
else
{
// similar to https://code.visualstudio.com/docs/setup/mac
_reporter.WriteLine(
$"Cannot find the tools executable path. Please ensure {_packageExecutablePath} is added to your PATH.{Environment.NewLine}" +
$"If you are using bash. You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" +
$"cat << EOF >> ~/.bash_profile{Environment.NewLine}" +
$"# Add .NET Core SDK tools{Environment.NewLine}" +
$"export PATH=\"$PATH:{_packageExecutablePath}\"{Environment.NewLine}" +
$"EOF");
}
}
}
}
}

View file

@ -0,0 +1,85 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.ShellShimMaker
{
internal class OSXEnvironmentPath : IEnvironmentPath
{
private const string PathName = "PATH";
private readonly string _packageExecutablePathWithTilde;
private readonly string _fullPackageExecutablePath;
private readonly IFile _fileSystem;
private readonly IEnvironmentProvider _environmentProvider;
private readonly IReporter _reporter;
private static readonly string PathDDotnetCliToolsPath
= Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_OSX_PATHSD_PATH")
?? @"/etc/paths.d/dotnet-cli-tools";
public OSXEnvironmentPath(
string packageExecutablePathWithTilde,
string fullPackageExecutablePath,
IReporter reporter,
IEnvironmentProvider environmentProvider,
IFile fileSystem
)
{
_fullPackageExecutablePath = fullPackageExecutablePath ??
throw new ArgumentNullException(nameof(fullPackageExecutablePath));
_packageExecutablePathWithTilde = packageExecutablePathWithTilde ??
throw new ArgumentNullException(nameof(packageExecutablePathWithTilde));
_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
_environmentProvider
= environmentProvider ?? throw new ArgumentNullException(nameof(environmentProvider));
_reporter
= reporter ?? throw new ArgumentNullException(nameof(reporter));
}
public void AddPackageExecutablePathToUserPath()
{
if (PackageExecutablePathExists())
{
return;
}
var script = $"{_packageExecutablePathWithTilde}";
_fileSystem.WriteAllText(PathDDotnetCliToolsPath, script);
}
private bool PackageExecutablePathExists()
{
return _environmentProvider.GetEnvironmentVariable(PathName).Split(':')
.Contains(_packageExecutablePathWithTilde) ||
_environmentProvider.GetEnvironmentVariable(PathName).Split(':')
.Contains(_fullPackageExecutablePath);
}
public void PrintAddPathInstructionIfPathDoesNotExist()
{
if (!PackageExecutablePathExists())
{
if (_fileSystem.Exists(PathDDotnetCliToolsPath))
{
_reporter.WriteLine(
"Since you just installed the .NET Core SDK, you will need to reopen terminal before running the tool you installed.");
}
else
{
// similar to https://code.visualstudio.com/docs/setup/mac
_reporter.WriteLine(
$"Cannot find the tools executable path. Please ensure {_fullPackageExecutablePath} is added to your PATH.{Environment.NewLine}" +
$"If you are using bash, You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" +
$"cat << EOF >> ~/.bash_profile{Environment.NewLine}" +
$"# Add .NET Core SDK tools{Environment.NewLine}" +
$"export PATH=\"$PATH:{_fullPackageExecutablePath}\"{Environment.NewLine}" +
$"EOF");
}
}
}
}
}

View file

@ -0,0 +1,89 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.ShellShimMaker
{
public class ShellShimMaker
{
private readonly string _pathToPlaceShim;
public ShellShimMaker(string pathToPlaceShim)
{
_pathToPlaceShim =
pathToPlaceShim ?? throw new ArgumentNullException(nameof(pathToPlaceShim));
}
public void CreateShim(string packageExecutablePath, string shellCommandName)
{
var packageExecutable = new FilePath(packageExecutablePath);
var script = new StringBuilder();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
script.AppendLine("@echo off");
script.AppendLine($"dotnet {packageExecutable.ToQuotedString()} %*");
}
else
{
script.AppendLine("#!/bin/sh");
script.AppendLine($"dotnet {packageExecutable.ToQuotedString()} \"$@\"");
}
FilePath scriptPath = GetScriptPath(shellCommandName);
File.WriteAllText(scriptPath.Value, script.ToString());
SetUserExecutionPermissionToShimFile(scriptPath);
}
public void EnsureCommandNameUniqueness(string shellCommandName)
{
if (File.Exists(Path.Combine(_pathToPlaceShim, shellCommandName)))
{
throw new GracefulException(
$"Failed to install tool {shellCommandName}. A command with the same name already exists.");
}
}
public void Remove(string shellCommandName)
{
File.Delete(GetScriptPath(shellCommandName).Value);
}
private FilePath GetScriptPath(string shellCommandName)
{
var scriptPath = Path.Combine(_pathToPlaceShim, shellCommandName);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
scriptPath += ".cmd";
}
return new FilePath(scriptPath);
}
private static void SetUserExecutionPermissionToShimFile(FilePath scriptPath)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return;
CommandResult result = new CommandFactory()
.Create("chmod", new[] {"u+x", scriptPath.Value})
.CaptureStdOut()
.CaptureStdErr()
.Execute();
if (result.ExitCode != 0)
{
throw new GracefulException(
"Failed to change permission:" +
$"{Environment.NewLine}Error: " + result.StdErr +
$"{Environment.NewLine}Output: " + result.StdOut);
}
}
}
}

View file

@ -0,0 +1,70 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.ShellShimMaker
{
internal class WindowsEnvironmentPath : IEnvironmentPath
{
private readonly IReporter _reporter;
private readonly IEnvironmentProvider _environmentProvider;
private const string PathName = "PATH";
private readonly string _packageExecutablePath;
public WindowsEnvironmentPath(
string packageExecutablePath, IReporter reporter,
IEnvironmentProvider environmentProvider)
{
_packageExecutablePath
= packageExecutablePath ?? throw new ArgumentNullException(nameof(packageExecutablePath));
_environmentProvider
= environmentProvider ?? throw new ArgumentNullException(nameof(environmentProvider));
_reporter
= reporter ?? throw new ArgumentNullException(nameof(reporter));
}
public void AddPackageExecutablePathToUserPath()
{
if (PackageExecutablePathExists())
{
return;
}
var existingUserEnvPath = Environment.GetEnvironmentVariable(PathName, EnvironmentVariableTarget.User);
Environment.SetEnvironmentVariable(
PathName,
$"{existingUserEnvPath};{_packageExecutablePath}",
EnvironmentVariableTarget.User);
}
private bool PackageExecutablePathExists()
{
return _environmentProvider.GetEnvironmentVariable(PathName).Split(';').Contains(_packageExecutablePath);
}
public void PrintAddPathInstructionIfPathDoesNotExist()
{
if (!PackageExecutablePathExists())
{
if (Environment.GetEnvironmentVariable(PathName, EnvironmentVariableTarget.User).Split(';')
.Contains(_packageExecutablePath))
{
_reporter.WriteLine(
"Since you just installed the .NET Core SDK, you will need to reopen the Command Prompt window before running the tool you installed.");
}
else
{
_reporter.WriteLine(
$"Cannot find the tools executable path. Please ensure {_packageExecutablePath} is added to your PATH.{Environment.NewLine}" +
$"You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" +
$"setx PATH \\\"%PATH%;{_packageExecutablePath}\"{Environment.NewLine}");
}
}
}
}
}

View file

@ -24,7 +24,7 @@ namespace Microsoft.DotNet.Cli.Telemetry
_hasher = hasher ?? Sha256Hasher.Hash; _hasher = hasher ?? Sha256Hasher.Hash;
_getMACAddress = getMACAddress ?? MacAddressGetter.GetMacAddress; _getMACAddress = getMACAddress ?? MacAddressGetter.GetMacAddress;
_dockerContainerDetector = dockerContainerDetector ?? new DockerContainerDetectorForTelemetry(); _dockerContainerDetector = dockerContainerDetector ?? new DockerContainerDetectorForTelemetry();
_userLevelCacheWriter = userLevelCacheWriter ?? new UserLevelCacheWriter(new CliFallbackFolderPathCalculator()); _userLevelCacheWriter = userLevelCacheWriter ?? new UserLevelCacheWriter(new CliFolderPathCalculator());
} }
private readonly IDockerContainerDetector _dockerContainerDetector; private readonly IDockerContainerDetector _dockerContainerDetector;

View file

@ -14,7 +14,7 @@ namespace Microsoft.DotNet.Tools.MSBuild
public sealed class MSBuildLogger : Logger public sealed class MSBuildLogger : Logger
{ {
private readonly IFirstTimeUseNoticeSentinel _sentinel = private readonly IFirstTimeUseNoticeSentinel _sentinel =
new FirstTimeUseNoticeSentinel(new CliFallbackFolderPathCalculator()); new FirstTimeUseNoticeSentinel(new CliFolderPathCalculator());
private readonly ITelemetry _telemetry; private readonly ITelemetry _telemetry;
private const string NewEventName = "msbuild"; private const string NewEventName = "msbuild";
private const string TargetFrameworkTelemetryEventName = "targetframeworkeval"; private const string TargetFrameworkTelemetryEventName = "targetframeworkeval";

View file

@ -32,7 +32,7 @@ namespace Microsoft.DotNet.Tools.New
var sessionId = var sessionId =
Environment.GetEnvironmentVariable(MSBuildForwardingApp.TelemetrySessionIdEnvironmentVariableName); Environment.GetEnvironmentVariable(MSBuildForwardingApp.TelemetrySessionIdEnvironmentVariableName);
var telemetry = var telemetry =
new Telemetry(new FirstTimeUseNoticeSentinel(new CliFallbackFolderPathCalculator()), sessionId); new Telemetry(new FirstTimeUseNoticeSentinel(new CliFolderPathCalculator()), sessionId);
var logger = new TelemetryLogger(null); var logger = new TelemetryLogger(null);
if (telemetry.Enabled) if (telemetry.Enabled)

View file

@ -84,6 +84,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.TestFramew
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackageObtainer.Tests", "Microsoft.DotNet.ToolPackageObtainer.Tests\Microsoft.DotNet.ToolPackageObtainer.Tests.csproj", "{C2A907A3-677B-4C73-9AA4-E53613E13C78}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackageObtainer.Tests", "Microsoft.DotNet.ToolPackageObtainer.Tests\Microsoft.DotNet.ToolPackageObtainer.Tests.csproj", "{C2A907A3-677B-4C73-9AA4-E53613E13C78}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShimMaker.Tests", "Microsoft.DotNet.ShellShimMaker.Tests\Microsoft.DotNet.ShellShimMaker.Tests.csproj", "{1146EAAC-E434-404A-8198-B4F0CB23BC57}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -550,6 +552,18 @@ Global
{C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x64.Build.0 = Release|Any CPU {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x64.Build.0 = Release|Any CPU
{C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x86.ActiveCfg = Release|Any CPU {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x86.ActiveCfg = Release|Any CPU
{C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x86.Build.0 = Release|Any CPU {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x86.Build.0 = Release|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x64.ActiveCfg = Debug|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x64.Build.0 = Debug|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x86.ActiveCfg = Debug|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x86.Build.0 = Debug|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|Any CPU.Build.0 = Release|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x64.ActiveCfg = Release|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x64.Build.0 = Release|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x86.ActiveCfg = Release|Any CPU
{1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -20,6 +20,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
private Mock<IFirstTimeUseNoticeSentinel> _firstTimeUseNoticeSentinelMock; private Mock<IFirstTimeUseNoticeSentinel> _firstTimeUseNoticeSentinelMock;
private Mock<IEnvironmentProvider> _environmentProviderMock; private Mock<IEnvironmentProvider> _environmentProviderMock;
private Mock<IReporter> _reporterMock; private Mock<IReporter> _reporterMock;
private Mock<IEnvironmentPath> _pathAdder;
public GivenADotnetFirstTimeUseConfigurer() public GivenADotnetFirstTimeUseConfigurer()
{ {
@ -28,6 +29,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock = new Mock<IFirstTimeUseNoticeSentinel>(); _firstTimeUseNoticeSentinelMock = new Mock<IFirstTimeUseNoticeSentinel>();
_environmentProviderMock = new Mock<IEnvironmentProvider>(); _environmentProviderMock = new Mock<IEnvironmentProvider>();
_reporterMock = new Mock<IReporter>(); _reporterMock = new Mock<IReporter>();
_pathAdder = new Mock<IEnvironmentPath>();
_environmentProviderMock _environmentProviderMock
.Setup(e => e.GetEnvironmentVariableAsBool("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", false)) .Setup(e => e.GetEnvironmentVariableAsBool("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", false))
@ -48,7 +50,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -70,7 +73,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -92,7 +96,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -111,7 +116,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -130,7 +136,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -148,7 +155,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -166,7 +174,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -187,7 +196,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -205,7 +215,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -224,7 +235,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -246,7 +258,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -258,6 +271,26 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_reporterMock.Verify(r => r.Write(It.IsAny<string>()), Times.Never); _reporterMock.Verify(r => r.Write(It.IsAny<string>()), Times.Never);
} }
[Fact]
public void It_adds_executable_package_path_to_environment_path_when_the_first_notice_sentinel_does_not_exist()
{
_nugetCacheSentinelMock.Setup(n => n.Exists()).Returns(true);
_firstTimeUseNoticeSentinelMock.Setup(n => n.Exists()).Returns(false);
var dotnetFirstTimeUseConfigurer = new DotnetFirstTimeUseConfigurer(
_nugetCachePrimerMock.Object,
new FakeCreateWillExistNuGetCacheSentinel(false, true),
new FakeCreateWillExistFirstTimeUseNoticeSentinel(false),
_environmentProviderMock.Object,
_reporterMock.Object,
CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure();
_pathAdder.Verify(p => p.AddPackageExecutablePathToUserPath(), Times.AtLeastOnce);
}
[Fact] [Fact]
public void It_prints_the_unauthorized_notice_if_the_cache_sentinel_reports_Unauthorized() public void It_prints_the_unauthorized_notice_if_the_cache_sentinel_reports_Unauthorized()
{ {
@ -269,7 +302,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
@ -295,11 +329,69 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_firstTimeUseNoticeSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object, _environmentProviderMock.Object,
_reporterMock.Object, _reporterMock.Object,
CliFallbackFolderPath); CliFallbackFolderPath,
_pathAdder.Object);
dotnetFirstTimeUseConfigurer.Configure(); dotnetFirstTimeUseConfigurer.Configure();
_nugetCachePrimerMock.Verify(r => r.PrimeCache(), Times.Never); _nugetCachePrimerMock.Verify(r => r.PrimeCache(), Times.Never);
} }
private class FakeCreateWillExistFirstTimeUseNoticeSentinel : IFirstTimeUseNoticeSentinel
{
private bool _exists;
public FakeCreateWillExistFirstTimeUseNoticeSentinel(bool exists)
{
_exists = exists;
}
public void Dispose()
{
}
public bool Exists()
{
return _exists;
}
public void CreateIfNotExists()
{
_exists = true;
}
}
private class FakeCreateWillExistNuGetCacheSentinel : INuGetCacheSentinel
{
private bool _inProgressSentinelAlreadyExists;
private bool _exists;
public FakeCreateWillExistNuGetCacheSentinel(bool inProgressSentinelAlreadyExists, bool exists)
{
_inProgressSentinelAlreadyExists = inProgressSentinelAlreadyExists;
_exists = exists;
}
public void Dispose()
{
}
public bool InProgressSentinelAlreadyExists()
{
return _inProgressSentinelAlreadyExists;
}
public bool Exists()
{
return _exists;
}
public void CreateIfNotExists()
{
_exists = true;
}
public bool UnauthorizedAccess { get; set; }
}
} }
} }

View file

@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
private Mock<INuGetPackagesArchiver> _nugetPackagesArchiverMock; private Mock<INuGetPackagesArchiver> _nugetPackagesArchiverMock;
private Mock<INuGetCacheSentinel> _nugetCacheSentinel; private Mock<INuGetCacheSentinel> _nugetCacheSentinel;
private CliFallbackFolderPathCalculator _cliFallbackFolderPathCalculator; private CliFolderPathCalculator _cliFolderPathCalculator;
public GivenANuGetCachePrimer() public GivenANuGetCachePrimer()
{ {
@ -40,12 +40,12 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_nugetCacheSentinel = new Mock<INuGetCacheSentinel>(); _nugetCacheSentinel = new Mock<INuGetCacheSentinel>();
_cliFallbackFolderPathCalculator = new CliFallbackFolderPathCalculator(); _cliFolderPathCalculator = new CliFolderPathCalculator();
var nugetCachePrimer = new NuGetCachePrimer( var nugetCachePrimer = new NuGetCachePrimer(
_nugetPackagesArchiverMock.Object, _nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object, _nugetCacheSentinel.Object,
_cliFallbackFolderPathCalculator, _cliFolderPathCalculator,
_fileSystemMock.File); _fileSystemMock.File);
nugetCachePrimer.PrimeCache(); nugetCachePrimer.PrimeCache();
@ -63,7 +63,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
var nugetCachePrimer = new NuGetCachePrimer( var nugetCachePrimer = new NuGetCachePrimer(
nugetPackagesArchiverMock.Object, nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object, _nugetCacheSentinel.Object,
_cliFallbackFolderPathCalculator, _cliFolderPathCalculator,
fileSystemMock.File); fileSystemMock.File);
nugetCachePrimer.PrimeCache(); nugetCachePrimer.PrimeCache();
@ -75,7 +75,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
public void It_extracts_the_archive_to_the_fallback_folder() public void It_extracts_the_archive_to_the_fallback_folder()
{ {
_nugetPackagesArchiverMock.Verify(n => _nugetPackagesArchiverMock.Verify(n =>
n.ExtractArchive(_cliFallbackFolderPathCalculator.CliFallbackFolderPath), n.ExtractArchive(_cliFolderPathCalculator.CliFallbackFolderPath),
Times.Exactly(1)); Times.Exactly(1));
} }
@ -95,7 +95,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
var nugetCachePrimer = new NuGetCachePrimer( var nugetCachePrimer = new NuGetCachePrimer(
nugetPackagesArchiveMock.Object, nugetPackagesArchiveMock.Object,
nugetCacheSentinel.Object, nugetCacheSentinel.Object,
_cliFallbackFolderPathCalculator, _cliFolderPathCalculator,
_fileSystemMock.File); _fileSystemMock.File);
Action action = () => nugetCachePrimer.PrimeCache(); Action action = () => nugetCachePrimer.PrimeCache();

View file

@ -0,0 +1,48 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.ShellShimMaker.Tests
{
internal class FakeEnvironmentProvider : IEnvironmentProvider
{
private readonly Dictionary<string, string> _environmentVariables;
public FakeEnvironmentProvider(Dictionary<string, string> environmentVariables)
{
_environmentVariables =
environmentVariables ?? throw new ArgumentNullException(nameof(environmentVariables));
}
public IEnumerable<string> ExecutableExtensions { get; }
public string GetCommandPath(string commandName, params string[] extensions)
{
throw new NotImplementedException();
}
public string GetCommandPathFromRootPath(string rootPath, string commandName, params string[] extensions)
{
throw new NotImplementedException();
}
public string GetCommandPathFromRootPath(string rootPath, string commandName,
IEnumerable<string> extensions)
{
throw new NotImplementedException();
}
public bool GetEnvironmentVariableAsBool(string name, bool defaultValue)
{
throw new NotImplementedException();
}
public string GetEnvironmentVariable(string name)
{
return _environmentVariables.ContainsKey(name) ? _environmentVariables[name] : "";
}
}
}

View file

@ -0,0 +1,55 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.ShellShimMaker.Tests
{
internal class FakeFile : IFile
{
private Dictionary<string, string> _files;
public FakeFile(Dictionary<string, string> files)
{
_files = files;
}
public bool Exists(string path)
{
return _files.ContainsKey(path);
}
public string ReadAllText(string path)
{
throw new NotImplementedException();
}
public Stream OpenRead(string path)
{
throw new NotImplementedException();
}
public Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare,
int bufferSize,
FileOptions fileOptions)
{
throw new NotImplementedException();
}
public void CreateEmptyFile(string path)
{
_files.Add(path, String.Empty);
}
public void WriteAllText(string path, string content)
{
_files[path] = content;
}
public static FakeFile Empty => new FakeFile(new Dictionary<string, string>());
}
}

View file

@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.ShellShimMaker.Tests
{
internal class FakeReporter : IReporter
{
public string Message { get; private set; } = "";
public void WriteLine(string message)
{
Message = message;
}
public void WriteLine()
{
throw new NotImplementedException();
}
public void Write(string message)
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,82 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using FluentAssertions;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.DependencyModel.Tests;
using Xunit;
namespace Microsoft.DotNet.ShellShimMaker.Tests
{
public class LinuxEnvironmentPathTests
{
[Fact]
public void GivenEnvironmentAndReporterItCanPrintOutInstructionToAddPath()
{
var fakeReporter = new FakeReporter();
var linuxEnvironmentPath = new LinuxEnvironmentPath(
@"executable\path",
fakeReporter,
new FakeEnvironmentProvider(
new Dictionary<string, string>
{
{"PATH", ""}
}),
FakeFile.Empty);
linuxEnvironmentPath.PrintAddPathInstructionIfPathDoesNotExist();
// similar to https://code.visualstudio.com/docs/setup/mac
fakeReporter.Message.Should().Be(
$"Cannot find the tools executable path. Please ensure executable\\path is added to your PATH.{Environment.NewLine}" +
$"If you are using bash. You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" +
$"cat << EOF >> ~/.bash_profile{Environment.NewLine}" +
$"# Add .NET Core SDK tools{Environment.NewLine}" +
$"export PATH=\"$PATH:executable\\path\"{Environment.NewLine}" +
$"EOF");
}
[Fact]
public void GivenEnvironmentAndReporterItPrintsNothingWhenenvironmentExists()
{
var fakeReporter = new FakeReporter();
var linuxEnvironmentPath = new LinuxEnvironmentPath(
@"executable\path",
fakeReporter,
new FakeEnvironmentProvider(
new Dictionary<string, string>
{
{"PATH", @"executable\path"}
}),
FakeFile.Empty);
linuxEnvironmentPath.PrintAddPathInstructionIfPathDoesNotExist();
fakeReporter.Message.Should().BeEmpty();
}
[Fact]
public void GivenAddPackageExecutablePathToUserPathJustRunItPrintsInstructionToLogout()
{
var fakeReporter = new FakeReporter();
var linuxEnvironmentPath = new LinuxEnvironmentPath(
@"executable\path",
fakeReporter,
new FakeEnvironmentProvider(
new Dictionary<string, string>
{
{"PATH", @""}
}),
FakeFile.Empty);
linuxEnvironmentPath.AddPackageExecutablePathToUserPath();
linuxEnvironmentPath.PrintAddPathInstructionIfPathDoesNotExist();
fakeReporter.Message.Should().Be("Since you just installed the .NET Core SDK, you will need to logout or restart your session before running the tool you installed.");
}
}
}

View file

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFramework>$(CliTargetFramework)</TargetFramework>
<RuntimeFrameworkVersion>$(CLI_SharedFrameworkVersion)</RuntimeFrameworkVersion>
<AssemblyOriginatorKeyFile>../../tools/Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<AssetTargetFallback>$(AssetTargetFallback);dotnet5.4;portable-net451+win8</AssetTargetFallback>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.DotNet.Configurer\Microsoft.DotNet.Configurer.csproj" />
<ProjectReference Include="..\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" />
<ProjectReference Include="..\..\src\dotnet\dotnet.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="FluentAssertions" Version="4.18.0" />
<PackageReference Include="Moq" Version="4.7.25" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="System.ComponentModel.TypeConverter" Version="4.3.0" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,88 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using FluentAssertions;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.DependencyModel.Tests;
using Xunit;
namespace Microsoft.DotNet.ShellShimMaker.Tests
{
public class OsxEnvironmentPathTests
{
[Fact]
public void GivenEnvironmentAndReporterItCanPrintOutInstructionToAddPath()
{
var fakeReporter = new FakeReporter();
var osxEnvironmentPath = new OSXEnvironmentPath(
@"~/executable/path",
@"/Users/name/executable/path",
fakeReporter,
new FakeEnvironmentProvider(
new Dictionary<string, string>
{
{"PATH", ""}
}),
FakeFile.Empty);
osxEnvironmentPath.PrintAddPathInstructionIfPathDoesNotExist();
// similar to https://code.visualstudio.com/docs/setup/mac
fakeReporter.Message.Should().Be(
$"Cannot find the tools executable path. Please ensure /Users/name/executable/path is added to your PATH.{Environment.NewLine}" +
$"If you are using bash, You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" +
$"cat << EOF >> ~/.bash_profile{Environment.NewLine}" +
$"# Add .NET Core SDK tools{Environment.NewLine}" +
$"export PATH=\"$PATH:/Users/name/executable/path\"{Environment.NewLine}" +
$"EOF");
}
[Theory]
[InlineData("/Users/name/executable/path")]
[InlineData("~/executable/path")]
public void GivenEnvironmentAndReporterItPrintsNothingWhenenvironmentExists(string existingPath)
{
var fakeReporter = new FakeReporter();
var osxEnvironmentPath = new OSXEnvironmentPath(
@"~/executable/path",
@"/Users/name/executable/path",
fakeReporter,
new FakeEnvironmentProvider(
new Dictionary<string, string>
{
{"PATH", existingPath}
}),
FakeFile.Empty);
osxEnvironmentPath.PrintAddPathInstructionIfPathDoesNotExist();
fakeReporter.Message.Should().BeEmpty();
}
[Fact]
public void GivenAddPackageExecutablePathToUserPathJustRunItPrintsInstructionToLogout()
{
var fakeReporter = new FakeReporter();
var osxEnvironmentPath = new OSXEnvironmentPath(
@"~/executable/path",
@"/Users/name/executable/path",
fakeReporter,
new FakeEnvironmentProvider(
new Dictionary<string, string>
{
{"PATH", @""}
}),
FakeFile.Empty);
osxEnvironmentPath.AddPackageExecutablePathToUserPath();
osxEnvironmentPath.PrintAddPathInstructionIfPathDoesNotExist();
fakeReporter.Message.Should().Be(
"Since you just installed the .NET Core SDK, you will need to reopen terminal before running the tool you installed.");
}
}
}

View file

@ -0,0 +1,126 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using FluentAssertions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
namespace Microsoft.DotNet.ShellShimMaker.Tests
{
public class ShellShimMakerTests : TestBase
{
private readonly string _pathToPlaceShim;
public ShellShimMakerTests()
{
_pathToPlaceShim = Path.GetTempPath();
}
[Fact]
public void GivenAnExecutablePathItCanGenerateShimFile()
{
var outputDll = MakeHelloWorldExecutableDll();
var shellShimMaker = new ShellShimMaker(_pathToPlaceShim);
var shellCommandName = nameof(ShellShimMakerTests) + Path.GetRandomFileName();
shellShimMaker.CreateShim(
outputDll.FullName,
shellCommandName);
var stdOut = ExecuteInShell(shellCommandName);
stdOut.Should().Contain("Hello World");
}
[Fact]
public void GivenAnExecutablePathWithExistingSameNameShimItThrows()
{
var shellCommandName = nameof(ShellShimMakerTests) + Path.GetRandomFileName();
MakeNameConflictingCommand(_pathToPlaceShim, shellCommandName);
var shellShimMaker = new ShellShimMaker(_pathToPlaceShim);
Action a = () => shellShimMaker.EnsureCommandNameUniqueness(shellCommandName);
a.ShouldThrow<GracefulException>()
.And.Message
.Should().Contain(
$"Failed to install tool {shellCommandName}. A command with the same name already exists.");
}
[Fact]
public void GivenAnExecutablePathWithoutExistingSameNameShimItShouldNotThrow()
{
var shellCommandName = nameof(ShellShimMakerTests) + Path.GetRandomFileName();
var shellShimMaker = new ShellShimMaker(_pathToPlaceShim);
Action a = () => shellShimMaker.EnsureCommandNameUniqueness(shellCommandName);
a.ShouldNotThrow();
}
private static void MakeNameConflictingCommand(string pathToPlaceShim, string shellCommandName)
{
File.WriteAllText(Path.Combine(pathToPlaceShim, shellCommandName), string.Empty);
}
private string ExecuteInShell(string shellCommandName)
{
ProcessStartInfo processStartInfo;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
processStartInfo = new ProcessStartInfo
{
FileName = "CMD.exe",
Arguments = $"/C {shellCommandName}",
UseShellExecute = false
};
}
else
{
processStartInfo = new ProcessStartInfo
{
FileName = "sh",
Arguments = shellCommandName,
UseShellExecute = false
};
}
processStartInfo.WorkingDirectory = _pathToPlaceShim;
processStartInfo.EnvironmentVariables["PATH"] = Path.GetDirectoryName(new Muxer().MuxerPath);
processStartInfo.ExecuteAndCaptureOutput(out var stdOut, out var stdErr);
stdErr.Should().BeEmpty();
return stdOut ?? "";
}
private static FileInfo MakeHelloWorldExecutableDll()
{
const string testAppName = "TestAppSimple";
const string emptySpaceToTestSpaceInPath = " ";
TestAssetInstance testInstance = TestAssets.Get(testAppName)
.CreateInstance(testAppName + emptySpaceToTestSpaceInPath)
.UseCurrentRuntimeFrameworkVersion()
.WithRestoreFiles()
.WithBuildFiles();
var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug";
FileInfo outputDll = testInstance.Root.GetDirectory("bin", configuration)
.GetDirectories().Single()
.GetFile($"{testAppName}.dll");
return outputDll;
}
}
}

View file

@ -28,6 +28,8 @@ namespace Microsoft.DotNet.Tests
_testDirectory = TestAssets.CreateTestDirectory("Dotnet_first_time_experience_tests").FullName; _testDirectory = TestAssets.CreateTestDirectory("Dotnet_first_time_experience_tests").FullName;
var testNuGetHome = Path.Combine(_testDirectory, "nuget_home"); var testNuGetHome = Path.Combine(_testDirectory, "nuget_home");
var cliTestFallbackFolder = Path.Combine(testNuGetHome, ".dotnet", "NuGetFallbackFolder"); var cliTestFallbackFolder = Path.Combine(testNuGetHome, ".dotnet", "NuGetFallbackFolder");
var profiled = Path.Combine(_testDirectory, "profile.d");
var pathsd = Path.Combine(_testDirectory, "paths.d");
var command = new DotnetCommand() var command = new DotnetCommand()
.WithWorkingDirectory(_testDirectory); .WithWorkingDirectory(_testDirectory);
@ -35,6 +37,8 @@ namespace Microsoft.DotNet.Tests
command.Environment["USERPROFILE"] = testNuGetHome; command.Environment["USERPROFILE"] = testNuGetHome;
command.Environment["APPDATA"] = testNuGetHome; command.Environment["APPDATA"] = testNuGetHome;
command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = cliTestFallbackFolder; command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = cliTestFallbackFolder;
command.Environment["DOTNET_CLI_TEST_LINUX_PROFILED_PATH"] = profiled;
command.Environment["DOTNET_CLI_TEST_OSX_PATHSD_PATH"] = pathsd;
command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = ""; command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "";
command.Environment["SkipInvalidConfigurations"] = "true"; command.Environment["SkipInvalidConfigurations"] = "true";
@ -92,6 +96,8 @@ namespace Microsoft.DotNet.Tests
public void ItDoesNotCreateAFirstUseSentinelFileUnderTheDotDotNetFolderWhenInternalReportInstallSuccessIsInvoked() public void ItDoesNotCreateAFirstUseSentinelFileUnderTheDotDotNetFolderWhenInternalReportInstallSuccessIsInvoked()
{ {
var emptyHome = Path.Combine(_testDirectory, "empty_home"); var emptyHome = Path.Combine(_testDirectory, "empty_home");
var profiled = Path.Combine(_testDirectory, "profile.d");
var pathsd = Path.Combine(_testDirectory, "paths.d");
var command = new DotnetCommand() var command = new DotnetCommand()
.WithWorkingDirectory(_testDirectory); .WithWorkingDirectory(_testDirectory);
@ -100,6 +106,8 @@ namespace Microsoft.DotNet.Tests
command.Environment["APPDATA"] = emptyHome; command.Environment["APPDATA"] = emptyHome;
command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = _nugetFallbackFolder.FullName; command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = _nugetFallbackFolder.FullName;
command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = ""; command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "";
command.Environment["DOTNET_CLI_TEST_LINUX_PROFILED_PATH"] = profiled;
command.Environment["DOTNET_CLI_TEST_OSX_PATHSD_PATH"] = pathsd;
// Disable to prevent the creation of the .dotnet folder by optimizationdata. // Disable to prevent the creation of the .dotnet folder by optimizationdata.
command.Environment["DOTNET_DISABLE_MULTICOREJIT"] = "true"; command.Environment["DOTNET_DISABLE_MULTICOREJIT"] = "true";
command.Environment["SkipInvalidConfigurations"] = "true"; command.Environment["SkipInvalidConfigurations"] = "true";
@ -116,6 +124,8 @@ namespace Microsoft.DotNet.Tests
{ {
var newHome = Path.Combine(_testDirectory, "new_home"); var newHome = Path.Combine(_testDirectory, "new_home");
var newHomeFolder = new DirectoryInfo(Path.Combine(newHome, ".dotnet")); var newHomeFolder = new DirectoryInfo(Path.Combine(newHome, ".dotnet"));
var profiled = Path.Combine(_testDirectory, "profile.d");
var pathsd = Path.Combine(_testDirectory, "paths.d");
var command = new DotnetCommand() var command = new DotnetCommand()
.WithWorkingDirectory(_testDirectory); .WithWorkingDirectory(_testDirectory);
@ -123,6 +133,8 @@ namespace Microsoft.DotNet.Tests
command.Environment["USERPROFILE"] = newHome; command.Environment["USERPROFILE"] = newHome;
command.Environment["APPDATA"] = newHome; command.Environment["APPDATA"] = newHome;
command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = _nugetFallbackFolder.FullName; command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = _nugetFallbackFolder.FullName;
command.Environment["DOTNET_CLI_TEST_LINUX_PROFILED_PATH"] = profiled;
command.Environment["DOTNET_CLI_TEST_OSX_PATHSD_PATH"] = pathsd;
command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = ""; command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "";
command.Environment["SkipInvalidConfigurations"] = "true"; command.Environment["SkipInvalidConfigurations"] = "true";