diff --git a/packaging/deb/postinst b/packaging/deb/postinst index f92c16afa..3ef09330a 100755 --- a/packaging/deb/postinst +++ b/packaging/deb/postinst @@ -2,7 +2,7 @@ echo "This software may collect information about you and your use of the software, and send that to Microsoft." echo "Please visit http://aka.ms/dotnet-cli-eula for more information." -# Run 'dotnet new' as the user to trigger the first time experience to initialize the cache +# Run 'dotnet new' to trigger the first time experience to initialize the cache echo "Welcome to .NET Core! --------------------- Learn more about .NET Core @ https://aka.ms/dotnet-docs. Use dotnet --help to see available commands or go to https://aka.ms/dotnet-cli-docs. @@ -15,4 +15,4 @@ The data collected is anonymous and will be published in an aggregated form for The .NET Core Tools telemetry feature is enabled by default. You can opt-out of the telemetry feature by setting an environment variable DOTNET_CLI_TELEMETRY_OPTOUT (for example, 'export' on macOS/Linux, 'set' on Windows) to true (for example, 'true', 1). You can read more about .NET Core tools telemetry at https://aka.ms/dotnet-cli-telemetry." -su - $SUDO_USER -c "dotnet new > /dev/null 2>&1 || true" +dotnet new > /dev/null 2>&1 || true diff --git a/packaging/osx/clisdk/scripts/postinstall b/packaging/osx/clisdk/scripts/postinstall index 54ea36c0d..4d69748e9 100755 --- a/packaging/osx/clisdk/scripts/postinstall +++ b/packaging/osx/clisdk/scripts/postinstall @@ -11,8 +11,7 @@ INSTALL_DESTINATION=$2 # A temporary fix for the permissions issue(s) chmod -R 755 $INSTALL_DESTINATION -# Run 'dotnet new' as user to trigger the first time experience to initialize the cache -INSTALLER_USER=$(stat -f '%Su' $HOME) -su - $INSTALLER_USER -c "$INSTALL_DESTINATION/dotnet new > /dev/null 2>&1 || true" +# Run 'dotnet new' to trigger the first time experience to initialize the cache +$INSTALL_DESTINATION/dotnet new > /dev/null 2>&1 || true exit 0 diff --git a/src/Microsoft.DotNet.Configurer/CliFallbackFolderPathCalculator.cs b/src/Microsoft.DotNet.Configurer/CliFallbackFolderPathCalculator.cs index 354d23ab4..8dece0fb7 100644 --- a/src/Microsoft.DotNet.Configurer/CliFallbackFolderPathCalculator.cs +++ b/src/Microsoft.DotNet.Configurer/CliFallbackFolderPathCalculator.cs @@ -12,16 +12,9 @@ namespace Microsoft.DotNet.Configurer { public class CliFallbackFolderPathCalculator { - public string CliFallbackFolderPath - { - get - { - string profileDir = Environment.GetEnvironmentVariable( - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME"); - - return Path.Combine(profileDir, ".dotnet", "NuGetFallbackFolder"); - } - } + public string CliFallbackFolderPath => + Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_FALLBACKFOLDER") ?? + Path.Combine(new DirectoryInfo(AppContext.BaseDirectory).Parent.FullName, "NuGetFallbackFolder"); public string NuGetUserSettingsDirectory => NuGetEnvironment.GetFolderPath(NuGetFolderPath.UserSettingsDirectory); diff --git a/src/Microsoft.DotNet.Configurer/DotnetFirstTimeUseConfigurer.cs b/src/Microsoft.DotNet.Configurer/DotnetFirstTimeUseConfigurer.cs index b2d6f4fd4..836462da3 100644 --- a/src/Microsoft.DotNet.Configurer/DotnetFirstTimeUseConfigurer.cs +++ b/src/Microsoft.DotNet.Configurer/DotnetFirstTimeUseConfigurer.cs @@ -14,19 +14,22 @@ namespace Microsoft.DotNet.Configurer private INuGetCachePrimer _nugetCachePrimer; private INuGetCacheSentinel _nugetCacheSentinel; private IFirstTimeUseNoticeSentinel _firstTimeUseNoticeSentinel; + private string _cliFallbackFolderPath; public DotnetFirstTimeUseConfigurer( INuGetCachePrimer nugetCachePrimer, INuGetCacheSentinel nugetCacheSentinel, IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IEnvironmentProvider environmentProvider, - IReporter reporter) + IReporter reporter, + string cliFallbackFolderPath) { _nugetCachePrimer = nugetCachePrimer; _nugetCacheSentinel = nugetCacheSentinel; _firstTimeUseNoticeSentinel = firstTimeUseNoticeSentinel; _environmentProvider = environmentProvider; _reporter = reporter; + _cliFallbackFolderPath = cliFallbackFolderPath; } public void Configure() @@ -41,6 +44,10 @@ namespace Microsoft.DotNet.Configurer PrintNugetCachePrimeMessage(); _nugetCachePrimer.PrimeCache(); } + else if (_nugetCacheSentinel.UnauthorizedAccess) + { + PrintUnauthorizedAccessMessage(); + } } private bool ShouldPrintFirstTimeUseNotice() @@ -55,14 +62,20 @@ namespace Microsoft.DotNet.Configurer private void PrintFirstTimeUseNotice() { - string firstTimeUseWelcomeMessage = LocalizableStrings.FirstTimeWelcomeMessage; - _reporter.WriteLine(); - _reporter.WriteLine(firstTimeUseWelcomeMessage); + _reporter.WriteLine(LocalizableStrings.FirstTimeWelcomeMessage); _firstTimeUseNoticeSentinel.CreateIfNotExists(); } + private void PrintUnauthorizedAccessMessage() + { + _reporter.WriteLine(); + _reporter.WriteLine(string.Format( + LocalizableStrings.UnauthorizedAccessMessage, + _cliFallbackFolderPath)); + } + private bool ShouldPrimeNugetCache() { return ShouldRunFirstRunExperience() && diff --git a/src/Microsoft.DotNet.Configurer/INuGetCacheSentinel.cs b/src/Microsoft.DotNet.Configurer/INuGetCacheSentinel.cs index 0eaa8d91d..9564145e8 100644 --- a/src/Microsoft.DotNet.Configurer/INuGetCacheSentinel.cs +++ b/src/Microsoft.DotNet.Configurer/INuGetCacheSentinel.cs @@ -12,5 +12,7 @@ namespace Microsoft.DotNet.Configurer bool Exists(); void CreateIfNotExists(); + + bool UnauthorizedAccess { get; } } } diff --git a/src/Microsoft.DotNet.Configurer/LocalizableStrings.resx b/src/Microsoft.DotNet.Configurer/LocalizableStrings.resx index 3a7ee20e6..57a874b2f 100644 --- a/src/Microsoft.DotNet.Configurer/LocalizableStrings.resx +++ b/src/Microsoft.DotNet.Configurer/LocalizableStrings.resx @@ -136,4 +136,14 @@ A command is running to initially populate your local package cache, to improve Failed to prime the NuGet cache. {0} failed with: {1} + + Permission denied to modify the '{0}' folder. + +Here are some options to fix this error: +--------------------- +1. Re-run this command with elevated access. +2. Disabled the first run experience by setting the environment variable DOTNET_SKIP_FIRST_TIME_EXPERIENCE to true. +3. Copy the .NET Core SDK to a non-protected location and use it from there."; + + diff --git a/src/Microsoft.DotNet.Configurer/NuGetCachePrimer.cs b/src/Microsoft.DotNet.Configurer/NuGetCachePrimer.cs index e69a4f96d..669d3be0d 100644 --- a/src/Microsoft.DotNet.Configurer/NuGetCachePrimer.cs +++ b/src/Microsoft.DotNet.Configurer/NuGetCachePrimer.cs @@ -61,10 +61,10 @@ namespace Microsoft.DotNet.Configurer var nuGetFallbackFolder = _cliFallbackFolderPathCalculator.CliFallbackFolderPath; - _nuGetConfig.AddCliFallbackFolder(nuGetFallbackFolder); - _nugetPackagesArchiver.ExtractArchive(nuGetFallbackFolder); + _nuGetConfig.AddCliFallbackFolder(nuGetFallbackFolder); + _nuGetCacheSentinel.CreateIfNotExists(); } diff --git a/src/Microsoft.DotNet.Configurer/NuGetCacheSentinel.cs b/src/Microsoft.DotNet.Configurer/NuGetCacheSentinel.cs index fccb50c1e..def087615 100644 --- a/src/Microsoft.DotNet.Configurer/NuGetCacheSentinel.cs +++ b/src/Microsoft.DotNet.Configurer/NuGetCacheSentinel.cs @@ -1,6 +1,7 @@ // 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 Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.EnvironmentAbstractions; @@ -13,8 +14,12 @@ namespace Microsoft.DotNet.Configurer public static readonly string SENTINEL = $"{Product.Version}.dotnetSentinel"; public static readonly string INPROGRESS_SENTINEL = $"{Product.Version}.inprogress.dotnetSentinel"; + public bool UnauthorizedAccess { get; private set; } + private readonly IFile _file; + private readonly IDirectory _directory; + private string _nugetCachePath; private string SentinelPath => Path.Combine(_nugetCachePath, SENTINEL); @@ -23,14 +28,17 @@ namespace Microsoft.DotNet.Configurer private Stream InProgressSentinel { get; set; } public NuGetCacheSentinel(CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator) : - this(cliFallbackFolderPathCalculator.CliFallbackFolderPath, FileSystemWrapper.Default.File) + this(cliFallbackFolderPathCalculator.CliFallbackFolderPath, + FileSystemWrapper.Default.File, + FileSystemWrapper.Default.Directory) { } - internal NuGetCacheSentinel(string nugetCachePath, IFile file) + internal NuGetCacheSentinel(string nugetCachePath, IFile file, IDirectory directory) { - _file = file; _nugetCachePath = nugetCachePath; + _file = file; + _directory = directory; SetInProgressSentinel(); } @@ -62,9 +70,9 @@ namespace Microsoft.DotNet.Configurer { try { - if (!Directory.Exists(_nugetCachePath)) + if (!_directory.Exists(_nugetCachePath)) { - Directory.CreateDirectory(_nugetCachePath); + _directory.CreateDirectory(_nugetCachePath); } // open an exclusive handle to the in-progress sentinel and mark it for delete on close. @@ -80,6 +88,10 @@ namespace Microsoft.DotNet.Configurer 1, FileOptions.DeleteOnClose); } + catch (UnauthorizedAccessException) + { + UnauthorizedAccess = true; + } catch { } } diff --git a/src/Microsoft.DotNet.Configurer/xlf/LocalizableStrings.xlf b/src/Microsoft.DotNet.Configurer/xlf/LocalizableStrings.xlf index 45687abde..64e3c6463 100644 --- a/src/Microsoft.DotNet.Configurer/xlf/LocalizableStrings.xlf +++ b/src/Microsoft.DotNet.Configurer/xlf/LocalizableStrings.xlf @@ -25,4 +25,4 @@ A command is running to initially populate your local package cache, to improve - \ No newline at end of file + diff --git a/src/Microsoft.DotNet.InternalAbstractions/DirectoryWrapper.cs b/src/Microsoft.DotNet.InternalAbstractions/DirectoryWrapper.cs index 53005a456..d0c26bd70 100644 --- a/src/Microsoft.DotNet.InternalAbstractions/DirectoryWrapper.cs +++ b/src/Microsoft.DotNet.InternalAbstractions/DirectoryWrapper.cs @@ -42,5 +42,10 @@ namespace Microsoft.Extensions.EnvironmentAbstractions return directoryFullName; } + + public void CreateDirectory(string path) + { + Directory.CreateDirectory(path); + } } } diff --git a/src/Microsoft.DotNet.InternalAbstractions/IDirectory.cs b/src/Microsoft.DotNet.InternalAbstractions/IDirectory.cs index 61087e088..8590bab5a 100644 --- a/src/Microsoft.DotNet.InternalAbstractions/IDirectory.cs +++ b/src/Microsoft.DotNet.InternalAbstractions/IDirectory.cs @@ -14,5 +14,7 @@ namespace Microsoft.Extensions.EnvironmentAbstractions IEnumerable GetFiles(string path, string searchPattern); string GetDirectoryFullName(string path); + + void CreateDirectory(string path); } } diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index 108ba7e92..c4a94c2f9 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -188,7 +188,8 @@ namespace Microsoft.DotNet.Cli nugetCacheSentinel, firstTimeUseNoticeSentinel, environmentProvider, - Reporter.Output); + Reporter.Output + cliFallbackFolderPathCalculator.CliFallbackFolderPath); dotnetConfigurer.Configure(); } diff --git a/test/Microsoft.DotNet.Configurer.UnitTests/GivenADotnetFirstTimeUseConfigurer.cs b/test/Microsoft.DotNet.Configurer.UnitTests/GivenADotnetFirstTimeUseConfigurer.cs index 6a6271bc6..9b951da34 100644 --- a/test/Microsoft.DotNet.Configurer.UnitTests/GivenADotnetFirstTimeUseConfigurer.cs +++ b/test/Microsoft.DotNet.Configurer.UnitTests/GivenADotnetFirstTimeUseConfigurer.cs @@ -13,6 +13,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests { public class GivenADotnetFirstTimeUseConfigurer { + private const string CliFallbackFolderPath = "some path"; + private Mock _nugetCachePrimerMock; private Mock _nugetCacheSentinelMock; private Mock _firstTimeUseNoticeSentinelMock; @@ -45,7 +47,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -66,7 +69,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -87,7 +91,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -105,7 +110,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -123,7 +129,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -140,7 +147,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -157,7 +165,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -177,7 +186,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -194,7 +204,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); @@ -212,7 +223,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests _nugetCacheSentinelMock.Object, _firstTimeUseNoticeSentinelMock.Object, _environmentProviderMock.Object, - _reporterMock.Object); + _reporterMock.Object, + CliFallbackFolderPath); dotnetFirstTimeUseConfigurer.Configure(); diff --git a/test/Microsoft.DotNet.Configurer.UnitTests/GivenANuGetCacheSentinel.cs b/test/Microsoft.DotNet.Configurer.UnitTests/GivenANuGetCacheSentinel.cs index 992679f60..97397d79d 100644 --- a/test/Microsoft.DotNet.Configurer.UnitTests/GivenANuGetCacheSentinel.cs +++ b/test/Microsoft.DotNet.Configurer.UnitTests/GivenANuGetCacheSentinel.cs @@ -2,12 +2,14 @@ // 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 FluentAssertions; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Configurer; using Microsoft.Extensions.DependencyModel.Tests; using Microsoft.Extensions.EnvironmentAbstractions; +using Moq; using Xunit; namespace Microsoft.DotNet.Configurer.UnitTests @@ -26,18 +28,44 @@ namespace Microsoft.DotNet.Configurer.UnitTests [Fact] public void As_soon_as_it_gets_created_it_tries_to_get_handle_of_the_InProgress_sentinel() { + var fileSystemMock = _fileSystemMockBuilder.Build(); var fileMock = new FileMock(); - var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory); fileMock.OpenFileWithRightParamsCalled.Should().BeTrue(); } [Fact] - public void It_returns_true_to_the_in_progress_sentinel_already_exists_when_it_fails_to_get_a_handle_to_it() + public void It_sets_UnauthorizedAccess_to_false_when_no_UnauthorizedAccessException_happens() + { + var fileSystemMock = _fileSystemMockBuilder.Build(); + var fileMock = new FileMock(); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory); + + nugetCacheSentinel.UnauthorizedAccess.Should().BeFalse(); + } + + [Fact] + public void It_sets_UnauthorizedAccess_to_true_when_an_UnauthorizedAccessException_happens() { + var fileMock = new FileMock(); + var directoryMock = new DirectoryMock(); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, directoryMock); + + nugetCacheSentinel.UnauthorizedAccess.Should().BeTrue(); + } + + [Fact] + public void It_returns_true_to_the_in_progress_sentinel_already_exists_when_it_fails_to_get_a_handle_to_it() + { + var fileSystemMock = _fileSystemMockBuilder.Build(); var fileMock = new FileMock(); fileMock.InProgressSentinel = null; - var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory); nugetCacheSentinel.InProgressSentinelAlreadyExists().Should().BeTrue(); } @@ -45,9 +73,11 @@ namespace Microsoft.DotNet.Configurer.UnitTests [Fact] public void It_returns_false_to_the_in_progress_sentinel_already_exists_when_it_succeeds_in_getting_a_handle_to_it() { + var fileSystemMock = _fileSystemMockBuilder.Build(); var fileMock = new FileMock(); fileMock.InProgressSentinel = new MemoryStream(); - var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory); nugetCacheSentinel.InProgressSentinelAlreadyExists().Should().BeFalse(); } @@ -55,10 +85,12 @@ namespace Microsoft.DotNet.Configurer.UnitTests [Fact] public void It_disposes_of_the_handle_to_the_InProgressSentinel_when_NuGetCacheSentinel_is_disposed() { + var fileSystemMock = _fileSystemMockBuilder.Build(); var mockStream = new MockStream(); var fileMock = new FileMock(); fileMock.InProgressSentinel = mockStream; - using (var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock)) + using (var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory)) {} mockStream.IsDisposed.Should().BeTrue(); @@ -77,7 +109,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests var fileSystemMock = _fileSystemMockBuilder.Build(); - var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory); nugetCacheSentinel.Exists().Should().BeTrue(); } @@ -87,7 +120,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests { var fileSystemMock = _fileSystemMockBuilder.Build(); - var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory); nugetCacheSentinel.Exists().Should().BeFalse(); } @@ -96,7 +130,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests public void It_creates_the_sentinel_in_the_nuget_cache_path_if_it_does_not_exist_already() { var fileSystemMock = _fileSystemMockBuilder.Build(); - var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory); nugetCacheSentinel.Exists().Should().BeFalse(); @@ -114,7 +149,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests var fileSystemMock = _fileSystemMockBuilder.Build(); - var nugetCacheSentinel = new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File); + var nugetCacheSentinel = + new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory); nugetCacheSentinel.Exists().Should().BeTrue(); @@ -123,6 +159,34 @@ namespace Microsoft.DotNet.Configurer.UnitTests fileSystemMock.File.ReadAllText(sentinel).Should().Be(contentToValidateSentinalWasNotReplaced); } + private class DirectoryMock : IDirectory + { + public bool Exists(string path) + { + return false; + } + + public ITemporaryDirectory CreateTemporaryDirectory() + { + throw new NotImplementedException(); + } + + public IEnumerable GetFiles(string path, string searchPattern) + { + throw new NotImplementedException(); + } + + public string GetDirectoryFullName(string path) + { + throw new NotImplementedException(); + } + + public void CreateDirectory(string path) + { + throw new UnauthorizedAccessException(); + } + } + private class FileMock : IFile { public bool OpenFileWithRightParamsCalled { get; private set; } diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Mock/FileSystemMockBuilder.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Mock/FileSystemMockBuilder.cs index 46db578c1..cda8c704b 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Mock/FileSystemMockBuilder.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Mock/FileSystemMockBuilder.cs @@ -138,6 +138,11 @@ namespace Microsoft.Extensions.DependencyModel.Tests { return _files.Keys.Any(k => k.StartsWith(path)); } + + public void CreateDirectory(string path) + { + _files.Add(path, path); + } } private class TemporaryDirectoryMock : ITemporaryDirectoryMock diff --git a/test/dotnet-msbuild.Tests/GivenDotnetMSBuildBuildsProjects.cs b/test/dotnet-msbuild.Tests/GivenDotnetMSBuildBuildsProjects.cs index e169e1469..2212a6ddf 100644 --- a/test/dotnet-msbuild.Tests/GivenDotnetMSBuildBuildsProjects.cs +++ b/test/dotnet-msbuild.Tests/GivenDotnetMSBuildBuildsProjects.cs @@ -190,10 +190,13 @@ namespace Microsoft.DotNet.Cli.MSBuild.Tests { private readonly Func _exists; + public bool UnauthorizedAccess => true; + public MockNuGetCacheSentinel(Func exists = null) { _exists = exists ?? (() => true); } + public void Dispose() { } diff --git a/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs b/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs index f69b1ce8b..026053261 100644 --- a/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs +++ b/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs @@ -25,19 +25,21 @@ namespace Microsoft.DotNet.Tests { var testDirectory = TestAssets.CreateTestDirectory("Dotnet_first_time_experience_tests"); var testNuGetHome = Path.Combine(testDirectory.FullName, "nuget_home"); + var cliTestFallbackFolder = Path.Combine(testNuGetHome, ".dotnet", "NuGetFallbackFolder"); var command = new DotnetCommand() .WithWorkingDirectory(testDirectory); command.Environment["HOME"] = testNuGetHome; command.Environment["USERPROFILE"] = testNuGetHome; command.Environment["APPDATA"] = testNuGetHome; + command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = cliTestFallbackFolder; command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = ""; command.Environment["SkipInvalidConfigurations"] = "true"; _firstDotnetNonVerbUseCommandResult = command.ExecuteWithCapturedOutput("--info"); _firstDotnetVerbUseCommandResult = command.ExecuteWithCapturedOutput("new --debug:ephemeral-hive"); - _nugetFallbackFolder = new DirectoryInfo(Path.Combine(testNuGetHome, ".dotnet", "NuGetFallbackFolder")); + _nugetFallbackFolder = new DirectoryInfo(cliTestFallbackFolder); } [Fact]