Moving the expanding fallback folder to the dotnet folder hive. The folder will be expanded at sdk/NuGetFallbackFolder.

This commit is contained in:
Livar Cunha 2017-05-31 13:44:03 -07:00
parent 58e18a61b7
commit 529d7caa79
17 changed files with 171 additions and 48 deletions

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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() &&

View file

@ -12,5 +12,7 @@ namespace Microsoft.DotNet.Configurer
bool Exists();
void CreateIfNotExists();
bool UnauthorizedAccess { get; }
}
}

View file

@ -136,4 +136,14 @@ A command is running to initially populate your local package cache, to improve
<data name="FailedToPrimeCacheError" xml:space="preserve">
<value>Failed to prime the NuGet cache. {0} failed with: {1}</value>
</data>
<data name="UnauthorizedAccessMessage" xml:space="preserve">
<value>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.";
</value>
</data>
</root>

View file

@ -61,10 +61,10 @@ namespace Microsoft.DotNet.Configurer
var nuGetFallbackFolder = _cliFallbackFolderPathCalculator.CliFallbackFolderPath;
_nuGetConfig.AddCliFallbackFolder(nuGetFallbackFolder);
_nugetPackagesArchiver.ExtractArchive(nuGetFallbackFolder);
_nuGetConfig.AddCliFallbackFolder(nuGetFallbackFolder);
_nuGetCacheSentinel.CreateIfNotExists();
}

View file

@ -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 { }
}

View file

@ -25,4 +25,4 @@ A command is running to initially populate your local package cache, to improve
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View file

@ -42,5 +42,10 @@ namespace Microsoft.Extensions.EnvironmentAbstractions
return directoryFullName;
}
public void CreateDirectory(string path)
{
Directory.CreateDirectory(path);
}
}
}

View file

@ -14,5 +14,7 @@ namespace Microsoft.Extensions.EnvironmentAbstractions
IEnumerable<string> GetFiles(string path, string searchPattern);
string GetDirectoryFullName(string path);
void CreateDirectory(string path);
}
}

View file

@ -188,7 +188,8 @@ namespace Microsoft.DotNet.Cli
nugetCacheSentinel,
firstTimeUseNoticeSentinel,
environmentProvider,
Reporter.Output);
Reporter.Output
cliFallbackFolderPathCalculator.CliFallbackFolderPath);
dotnetConfigurer.Configure();
}

View file

@ -13,6 +13,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
{
public class GivenADotnetFirstTimeUseConfigurer
{
private const string CliFallbackFolderPath = "some path";
private Mock<INuGetCachePrimer> _nugetCachePrimerMock;
private Mock<INuGetCacheSentinel> _nugetCacheSentinelMock;
private Mock<IFirstTimeUseNoticeSentinel> _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();

View file

@ -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<string> 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; }

View file

@ -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

View file

@ -190,10 +190,13 @@ namespace Microsoft.DotNet.Cli.MSBuild.Tests
{
private readonly Func<bool> _exists;
public bool UnauthorizedAccess => true;
public MockNuGetCacheSentinel(Func<bool> exists = null)
{
_exists = exists ?? (() => true);
}
public void Dispose()
{
}

View file

@ -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]