Merge pull request #6209 from livarcocc/first_run_fallback_folder

First run fallback folder
This commit is contained in:
Livar 2017-04-03 23:23:29 -07:00 committed by GitHub
commit 34f7df0763
19 changed files with 249 additions and 303 deletions

View file

@ -13,7 +13,8 @@
<NuGetPackagesArchiveProject>$(IntermediateDirectory)/NuGetPackagesArchiveProject</NuGetPackagesArchiveProject> <NuGetPackagesArchiveProject>$(IntermediateDirectory)/NuGetPackagesArchiveProject</NuGetPackagesArchiveProject>
<NuGetPackagesArchiveFolder>$(IntermediateDirectory)/NuGetPackagesArchiveFolder</NuGetPackagesArchiveFolder> <NuGetPackagesArchiveFolder>$(IntermediateDirectory)/NuGetPackagesArchiveFolder</NuGetPackagesArchiveFolder>
<LZMANuGetConfigFilePath>$(NuGetPackagesArchiveProject)/Nuget.config</LZMANuGetConfigFilePath> <LZMANuGetConfigFilePath Condition=" '$(CLI_LZMA_PACKAGE_SOURCE)' != '' ">$(NuGetPackagesArchiveProject)/Nuget.config</LZMANuGetConfigFilePath>
<LZMANuGetConfigFilePath Condition=" '$(LZMANuGetConfigFilePath)' == '' ">$(RepoRoot)/NuGet.Config</LZMANuGetConfigFilePath>
<ToolsOutputDirectory>$(BaseOutputDirectory)/tools</ToolsOutputDirectory> <ToolsOutputDirectory>$(BaseOutputDirectory)/tools</ToolsOutputDirectory>
<ArchiverDll>$(ToolsOutputDirectory)/Archiver.dll</ArchiverDll> <ArchiverDll>$(ToolsOutputDirectory)/Archiver.dll</ArchiverDll>
<FinalArchive>$(SdkOutputDirectory)/nuGetPackagesArchive.lzma</FinalArchive> <FinalArchive>$(SdkOutputDirectory)/nuGetPackagesArchive.lzma</FinalArchive>
@ -96,10 +97,11 @@
<DotNetRestore ToolPath="$(OutputDirectory)" <DotNetRestore ToolPath="$(OutputDirectory)"
Packages="$(NuGetPackagesArchiveFolder)" Packages="$(NuGetPackagesArchiveFolder)"
ConfigFile="$(LZMANuGetConfigFilePath)"
SkipInvalidConfigurations="True" SkipInvalidConfigurations="True"
WorkingDirectory="$(NuGetPackagesArchiveProject)/Console" /> WorkingDirectory="$(NuGetPackagesArchiveProject)/Console" />
<Delete Files="$(IntermediateArchive);$(IntermediateArchive).zip" /> <Delete Files="$(IntermediateArchive);$(IntermediateArchive).zip;$(NuGetPackagesArchiveFolder)/**/*.nupkg" />
<Message Text="Publishing Archiver" /> <Message Text="Publishing Archiver" />

View file

@ -0,0 +1,29 @@
// 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
{
get
{
string profileDir = Environment.GetEnvironmentVariable(
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "USERPROFILE" : "HOME");
return Path.Combine(profileDir, ".dotnet", "NuGetFallbackFolder");
}
}
public string NuGetUserSettingsDirectory =>
NuGetEnvironment.GetFolderPath(NuGetFolderPath.UserSettingsDirectory);
}
}

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.Configurer
{
public interface INuGetConfig
{
void AddCliFallbackFolder(string fallbackFolderPath);
}
}

View file

@ -5,10 +5,10 @@ using System;
namespace Microsoft.DotNet.Configurer namespace Microsoft.DotNet.Configurer
{ {
public interface INuGetPackagesArchiver : IDisposable public interface INuGetPackagesArchiver
{ {
string NuGetPackagesArchive { get; } string NuGetPackagesArchive { get; }
string ExtractArchive(); void ExtractArchive(string archiveDestination);
} }
} }

View file

@ -12,6 +12,11 @@
<RepositoryUrl>git://github.com/dotnet/cli</RepositoryUrl> <RepositoryUrl>git://github.com/dotnet/cli</RepositoryUrl>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="NuGet.Common" Version="$(CLI_NuGet_Version)" />
<PackageReference Include="NuGet.Configuration" Version="$(CLI_NuGet_Version)" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj" /> <ProjectReference Include="..\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj" />
<ProjectReference Include="..\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" /> <ProjectReference Include="..\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" />

View file

@ -10,48 +10,44 @@ namespace Microsoft.DotNet.Configurer
{ {
public class NuGetCachePrimer : INuGetCachePrimer public class NuGetCachePrimer : INuGetCachePrimer
{ {
private static IReadOnlyList<IReadOnlyList<string>> _templatesUsedToPrimeCache = new List<IReadOnlyList<string>>()
{
new List<string>() { "console", "--debug:ephemeral-hive" },
};
private readonly ICommandFactory _commandFactory;
private readonly IDirectory _directory;
private readonly IFile _file; private readonly IFile _file;
private readonly INuGetPackagesArchiver _nugetPackagesArchiver; private readonly INuGetPackagesArchiver _nugetPackagesArchiver;
private readonly INuGetCacheSentinel _nuGetCacheSentinel; private readonly INuGetCacheSentinel _nuGetCacheSentinel;
private readonly INuGetConfig _nuGetConfig;
private readonly CliFallbackFolderPathCalculator _cliFallbackFolderPathCalculator;
public NuGetCachePrimer( public NuGetCachePrimer(
ICommandFactory commandFactory,
INuGetPackagesArchiver nugetPackagesArchiver, INuGetPackagesArchiver nugetPackagesArchiver,
INuGetCacheSentinel nuGetCacheSentinel) INuGetCacheSentinel nuGetCacheSentinel,
: this(commandFactory, INuGetConfig nuGetConfig,
nugetPackagesArchiver, CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator)
: this(nugetPackagesArchiver,
nuGetCacheSentinel, nuGetCacheSentinel,
FileSystemWrapper.Default.Directory, nuGetConfig,
cliFallbackFolderPathCalculator,
FileSystemWrapper.Default.File) FileSystemWrapper.Default.File)
{ {
} }
internal NuGetCachePrimer( internal NuGetCachePrimer(
ICommandFactory commandFactory,
INuGetPackagesArchiver nugetPackagesArchiver, INuGetPackagesArchiver nugetPackagesArchiver,
INuGetCacheSentinel nuGetCacheSentinel, INuGetCacheSentinel nuGetCacheSentinel,
IDirectory directory, INuGetConfig nuGetConfig,
CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator,
IFile file) IFile file)
{ {
_commandFactory = commandFactory;
_directory = directory;
_nugetPackagesArchiver = nugetPackagesArchiver; _nugetPackagesArchiver = nugetPackagesArchiver;
_nuGetCacheSentinel = nuGetCacheSentinel; _nuGetCacheSentinel = nuGetCacheSentinel;
_nuGetConfig = nuGetConfig;
_cliFallbackFolderPathCalculator = cliFallbackFolderPathCalculator;
_file = file; _file = file;
} }
@ -62,79 +58,18 @@ namespace Microsoft.DotNet.Configurer
return; return;
} }
var extractedPackagesArchiveDirectory = _nugetPackagesArchiver.ExtractArchive(); var nuGetFallbackFolder = _cliFallbackFolderPathCalculator.CliFallbackFolderPath;
PrimeCacheUsingArchive(extractedPackagesArchiveDirectory); _nuGetConfig.AddCliFallbackFolder(nuGetFallbackFolder);
_nugetPackagesArchiver.ExtractArchive(nuGetFallbackFolder);
_nuGetCacheSentinel.CreateIfNotExists();
} }
private bool SkipPrimingTheCache() private bool SkipPrimingTheCache()
{ {
return !_file.Exists(_nugetPackagesArchiver.NuGetPackagesArchive); return !_file.Exists(_nugetPackagesArchiver.NuGetPackagesArchive);
} }
private void PrimeCacheUsingArchive(string extractedPackagesArchiveDirectory)
{
bool succeeded = true;
foreach (IReadOnlyList<string> templateInfo in _templatesUsedToPrimeCache)
{
if (succeeded)
{
using (var temporaryDotnetNewDirectory = _directory.CreateTemporaryDirectory())
{
var workingDirectory = temporaryDotnetNewDirectory.DirectoryPath;
succeeded &= CreateTemporaryProject(workingDirectory, templateInfo);
if (succeeded)
{
succeeded &= RestoreTemporaryProject(extractedPackagesArchiveDirectory, workingDirectory);
}
}
}
}
if (succeeded)
{
_nuGetCacheSentinel.CreateIfNotExists();
}
}
private bool CreateTemporaryProject(string workingDirectory, IReadOnlyList<string> templateInfo)
{
return RunCommand(
"new",
templateInfo,
workingDirectory);
}
private bool RestoreTemporaryProject(string extractedPackagesArchiveDirectory, string workingDirectory)
{
return RunCommand(
"restore",
new[] { "-s", extractedPackagesArchiveDirectory },
workingDirectory);
}
private bool RunCommand(string commandToExecute, IEnumerable<string> args, string workingDirectory)
{
var command = _commandFactory
.Create(commandToExecute, args)
.WorkingDirectory(workingDirectory)
.CaptureStdOut()
.CaptureStdErr();
var commandResult = command.Execute();
if (commandResult.ExitCode != 0)
{
Reporter.Verbose.WriteLine(commandResult.StdErr);
Reporter.Error.WriteLine(
string.Format(LocalizableStrings.FailedToPrimeCacheError, commandToExecute, commandResult.ExitCode));
}
return commandResult.ExitCode == 0;
}
} }
} }

View file

@ -17,25 +17,13 @@ namespace Microsoft.DotNet.Configurer
private string _nugetCachePath; private string _nugetCachePath;
private string NuGetCachePath private string SentinelPath => Path.Combine(_nugetCachePath, SENTINEL);
{ private string InProgressSentinelPath => Path.Combine(_nugetCachePath, INPROGRESS_SENTINEL);
get
{
if (string.IsNullOrEmpty(_nugetCachePath))
{
_nugetCachePath = NuGetPathContext.Create(new NullSettings()).UserPackageFolder;
}
return _nugetCachePath;
}
}
private string SentinelPath => Path.Combine(NuGetCachePath, SENTINEL);
private string InProgressSentinelPath => Path.Combine(NuGetCachePath, INPROGRESS_SENTINEL);
private Stream InProgressSentinel { get; set; } private Stream InProgressSentinel { get; set; }
public NuGetCacheSentinel() : this(string.Empty, FileSystemWrapper.Default.File) public NuGetCacheSentinel(CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator) :
this(cliFallbackFolderPathCalculator.CliFallbackFolderPath, FileSystemWrapper.Default.File)
{ {
} }
@ -74,9 +62,9 @@ namespace Microsoft.DotNet.Configurer
{ {
try 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. // open an exclusive handle to the in-progress sentinel and mark it for delete on close.

View file

@ -0,0 +1,39 @@
// 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 NuGet.Common;
using NuGet.Configuration;
using System.Linq;
namespace Microsoft.DotNet.Configurer
{
public class NuGetConfig : INuGetConfig
{
public const string FallbackPackageFolders = "fallbackPackageFolders";
private ISettings _settings;
public NuGetConfig(CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator)
{
_settings = new Settings(cliFallbackFolderPathCalculator.NuGetUserSettingsDirectory);
}
internal NuGetConfig(ISettings settings)
{
_settings = settings;
}
public void AddCliFallbackFolder(string fallbackFolderPath)
{
if (!IsCliFallbackFolderSet(fallbackFolderPath))
{
_settings.SetValue(FallbackPackageFolders, "CliFallbackFolder", fallbackFolderPath);
}
}
private bool IsCliFallbackFolderSet(string fallbackFolderPath)
{
return _settings.GetSettingValues(FallbackPackageFolders).Any(s => s.Value == fallbackFolderPath);
}
}
}

View file

@ -10,33 +10,15 @@ namespace Microsoft.DotNet.Configurer
{ {
public class NuGetPackagesArchiver : INuGetPackagesArchiver public class NuGetPackagesArchiver : INuGetPackagesArchiver
{ {
private ITemporaryDirectory _temporaryDirectory;
public string NuGetPackagesArchive => public string NuGetPackagesArchive =>
Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "nuGetPackagesArchive.lzma")); Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "nuGetPackagesArchive.lzma"));
public NuGetPackagesArchiver() : this(FileSystemWrapper.Default.Directory) public void ExtractArchive(string archiveDestination)
{
}
internal NuGetPackagesArchiver(IDirectory directory)
{
_temporaryDirectory = directory.CreateTemporaryDirectory();
}
public string ExtractArchive()
{ {
var progress = new ConsoleProgressReport(); var progress = new ConsoleProgressReport();
var archive = new IndexedArchive(); var archive = new IndexedArchive();
archive.Extract(NuGetPackagesArchive, _temporaryDirectory.DirectoryPath, progress); archive.Extract(NuGetPackagesArchive, archiveDestination, progress);
return _temporaryDirectory.DirectoryPath;
}
public void Dispose()
{
_temporaryDirectory.Dispose();
} }
} }
} }

View file

@ -110,6 +110,7 @@ namespace Microsoft.DotNet.TestFramework
var content = @"<?xml version=""1.0"" encoding=""utf-8""?> var content = @"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration> <configuration>
<packageSources> <packageSources>
<add key=""dotnet-core"" value=""https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"" />
<add key=""test-packages"" value=""$fullpath$"" /> <add key=""test-packages"" value=""$fullpath$"" />
</packageSources> </packageSources>
</configuration>"; </configuration>";

View file

@ -79,7 +79,8 @@ namespace Microsoft.DotNet.Cli
var success = true; var success = true;
var command = string.Empty; var command = string.Empty;
var lastArg = 0; var lastArg = 0;
using (INuGetCacheSentinel nugetCacheSentinel = new NuGetCacheSentinel()) var cliFallbackFolderPathCalculator = new CliFallbackFolderPathCalculator();
using (INuGetCacheSentinel nugetCacheSentinel = new NuGetCacheSentinel(cliFallbackFolderPathCalculator))
{ {
for (; lastArg < args.Length; lastArg++) for (; lastArg < args.Length; lastArg++)
{ {
@ -111,7 +112,7 @@ namespace Microsoft.DotNet.Cli
} }
else else
{ {
ConfigureDotNetForFirstTimeUse(nugetCacheSentinel); ConfigureDotNetForFirstTimeUse(nugetCacheSentinel, cliFallbackFolderPathCalculator);
// It's the command, and we're done! // It's the command, and we're done!
command = args[lastArg]; command = args[lastArg];
@ -165,23 +166,27 @@ namespace Microsoft.DotNet.Cli
} }
private static void ConfigureDotNetForFirstTimeUse(INuGetCacheSentinel nugetCacheSentinel) private static void ConfigureDotNetForFirstTimeUse(
INuGetCacheSentinel nugetCacheSentinel,
CliFallbackFolderPathCalculator cliFallbackFolderPathCalculator)
{ {
using (PerfTrace.Current.CaptureTiming()) using (PerfTrace.Current.CaptureTiming())
{ {
using (var nugetPackagesArchiver = new NuGetPackagesArchiver()) var nugetPackagesArchiver = new NuGetPackagesArchiver();
{ var environmentProvider = new EnvironmentProvider();
var environmentProvider = new EnvironmentProvider(); var commandFactory = new DotNetCommandFactory(alwaysRunOutOfProc: true);
var commandFactory = new DotNetCommandFactory(alwaysRunOutOfProc: true); var nugetConfig = new NuGetConfig(cliFallbackFolderPathCalculator);
var nugetCachePrimer = var nugetCachePrimer = new NuGetCachePrimer(
new NuGetCachePrimer(commandFactory, nugetPackagesArchiver, nugetCacheSentinel); nugetPackagesArchiver,
var dotnetConfigurer = new DotnetFirstTimeUseConfigurer( nugetCacheSentinel,
nugetCachePrimer, nugetConfig,
nugetCacheSentinel, cliFallbackFolderPathCalculator);
environmentProvider); var dotnetConfigurer = new DotnetFirstTimeUseConfigurer(
nugetCachePrimer,
nugetCacheSentinel,
environmentProvider);
dotnetConfigurer.Configure(); dotnetConfigurer.Configure();
}
} }
} }

View file

@ -11,7 +11,7 @@ namespace Microsoft.DotNet.Tools.MSBuild
{ {
public sealed class MSBuildLogger : Logger public sealed class MSBuildLogger : Logger
{ {
private readonly INuGetCacheSentinel _sentinel = new NuGetCacheSentinel(); private readonly INuGetCacheSentinel _sentinel = new NuGetCacheSentinel(new CliFallbackFolderPathCalculator());
private readonly ITelemetry _telemetry; private readonly ITelemetry _telemetry;
public MSBuildLogger() public MSBuildLogger()

View file

@ -342,7 +342,8 @@ namespace Microsoft.DotNet.Tests
var testInstance = TestAssets.Get("AppWithFallbackFolderToolDependency") var testInstance = TestAssets.Get("AppWithFallbackFolderToolDependency")
.CreateInstance() .CreateInstance()
.WithSourceFiles(); .WithSourceFiles()
.WithNuGetConfig(new RepoDirectoriesProvider().TestPackages);
var testProjectDirectory = testInstance.Root.FullName; var testProjectDirectory = testInstance.Root.FullName;
var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder"); var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder");
@ -378,13 +379,14 @@ namespace Microsoft.DotNet.Tests
} }
[Fact] [Fact]
public void ItXXXWhenTheToolDllIsNotFound() public void ItShowsAnErrorWhenTheToolDllIsNotFound()
{ {
var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
var testInstance = TestAssets.Get("AppWithFallbackFolderToolDependency") var testInstance = TestAssets.Get("AppWithFallbackFolderToolDependency")
.CreateInstance() .CreateInstance()
.WithSourceFiles(); .WithSourceFiles()
.WithNuGetConfig(new RepoDirectoriesProvider().TestPackages);
var testProjectDirectory = testInstance.Root.FullName; var testProjectDirectory = testInstance.Root.FullName;
var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder"); var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder");
@ -415,9 +417,10 @@ namespace Microsoft.DotNet.Tests
private void PopulateFallbackFolder(string testProjectDirectory, string fallbackFolder) private void PopulateFallbackFolder(string testProjectDirectory, string fallbackFolder)
{ {
var nugetConfigPath = Path.Combine(testProjectDirectory, "NuGet.Config");
new RestoreCommand() new RestoreCommand()
.WithWorkingDirectory(testProjectDirectory) .WithWorkingDirectory(testProjectDirectory)
.Execute($"--packages {fallbackFolder}") .Execute($"--configfile {nugetConfigPath} --packages {fallbackFolder}")
.Should() .Should()
.Pass(); .Pass();

View file

@ -1,6 +1,7 @@
// 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.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
@ -21,13 +22,11 @@ namespace Microsoft.DotNet.Configurer.UnitTests
private const string PACKAGES_ARCHIVE_PATH = "some other path"; private const string PACKAGES_ARCHIVE_PATH = "some other path";
private IFileSystem _fileSystemMock; private IFileSystem _fileSystemMock;
private ITemporaryDirectoryMock _temporaryDirectoryMock;
private Mock<ICommandFactory> _commandFactoryMock;
private Mock<ICommand> _dotnetNewCommandMock;
private Mock<ICommand> _dotnetRestoreCommandMock;
private Mock<INuGetPackagesArchiver> _nugetPackagesArchiverMock; private Mock<INuGetPackagesArchiver> _nugetPackagesArchiverMock;
private Mock<INuGetCacheSentinel> _nugetCacheSentinel; private Mock<INuGetCacheSentinel> _nugetCacheSentinel;
private Mock<INuGetConfig> _nugetConfigMock;
private CliFallbackFolderPathCalculator _cliFallbackFolderPathCalculator;
public GivenANuGetCachePrimer() public GivenANuGetCachePrimer()
{ {
@ -35,175 +34,61 @@ namespace Microsoft.DotNet.Configurer.UnitTests
fileSystemMockBuilder.TemporaryFolder = TEMPORARY_FOLDER_PATH; fileSystemMockBuilder.TemporaryFolder = TEMPORARY_FOLDER_PATH;
fileSystemMockBuilder.AddFile(COMPRESSED_ARCHIVE_PATH); fileSystemMockBuilder.AddFile(COMPRESSED_ARCHIVE_PATH);
_fileSystemMock = fileSystemMockBuilder.Build(); _fileSystemMock = fileSystemMockBuilder.Build();
_temporaryDirectoryMock = (ITemporaryDirectoryMock)_fileSystemMock.Directory.CreateTemporaryDirectory();
_commandFactoryMock = SetupCommandFactoryMock();
_nugetPackagesArchiverMock = new Mock<INuGetPackagesArchiver>(); _nugetPackagesArchiverMock = new Mock<INuGetPackagesArchiver>();
_nugetPackagesArchiverMock.Setup(n => n.ExtractArchive()).Returns(PACKAGES_ARCHIVE_PATH);
_nugetPackagesArchiverMock.Setup(n => n.NuGetPackagesArchive).Returns(COMPRESSED_ARCHIVE_PATH); _nugetPackagesArchiverMock.Setup(n => n.NuGetPackagesArchive).Returns(COMPRESSED_ARCHIVE_PATH);
_nugetCacheSentinel = new Mock<INuGetCacheSentinel>(); _nugetCacheSentinel = new Mock<INuGetCacheSentinel>();
_nugetConfigMock = new Mock<INuGetConfig>();
_cliFallbackFolderPathCalculator = new CliFallbackFolderPathCalculator();
var nugetCachePrimer = new NuGetCachePrimer( var nugetCachePrimer = new NuGetCachePrimer(
_commandFactoryMock.Object,
_nugetPackagesArchiverMock.Object, _nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object, _nugetCacheSentinel.Object,
_fileSystemMock.Directory, _nugetConfigMock.Object,
_cliFallbackFolderPathCalculator,
_fileSystemMock.File); _fileSystemMock.File);
nugetCachePrimer.PrimeCache(); nugetCachePrimer.PrimeCache();
} }
private Mock<ICommandFactory> SetupCommandFactoryMock()
{
var commandFactoryMock = new Mock<ICommandFactory>();
_dotnetNewCommandMock = new Mock<ICommand>();
SetupCommandMock(_dotnetNewCommandMock);
commandFactoryMock
.Setup(c => c.Create("new", new[] { "console", "--debug:ephemeral-hive" }, null, Constants.DefaultConfiguration))
.Returns(_dotnetNewCommandMock.Object);
_dotnetRestoreCommandMock = new Mock<ICommand>();
SetupCommandMock(_dotnetRestoreCommandMock);
commandFactoryMock
.Setup(c => c.Create(
"restore",
It.IsAny<IEnumerable<string>>(),
null,
Constants.DefaultConfiguration))
.Returns(_dotnetRestoreCommandMock.Object);
return commandFactoryMock;
}
private void SetupCommandMock(Mock<ICommand> commandMock)
{
commandMock
.Setup(c => c.WorkingDirectory(TEMPORARY_FOLDER_PATH))
.Returns(commandMock.Object);
commandMock.Setup(c => c.CaptureStdOut()).Returns(commandMock.Object);
commandMock.Setup(c => c.CaptureStdErr()).Returns(commandMock.Object);
}
[Fact] [Fact]
public void It_does_not_prime_the_NuGet_cache_if_the_archive_is_not_found_so_that_we_do_not_need_to_generate_the_archive_for_stage1() public void It_does_not_prime_the_NuGet_cache_if_the_archive_is_not_found_so_that_we_do_not_need_to_generate_the_archive_for_stage1()
{ {
var fileSystemMockBuilder = FileSystemMockBuilder.Create(); var fileSystemMockBuilder = FileSystemMockBuilder.Create();
var fileSystemMock = fileSystemMockBuilder.Build(); var fileSystemMock = fileSystemMockBuilder.Build();
var commandFactoryMock = SetupCommandFactoryMock();
var nugetPackagesArchiverMock = new Mock<INuGetPackagesArchiver>(); var nugetPackagesArchiverMock = new Mock<INuGetPackagesArchiver>();
nugetPackagesArchiverMock.Setup(n => n.NuGetPackagesArchive).Returns(COMPRESSED_ARCHIVE_PATH); nugetPackagesArchiverMock.Setup(n => n.NuGetPackagesArchive).Returns(COMPRESSED_ARCHIVE_PATH);
var nugetCachePrimer = new NuGetCachePrimer( var nugetCachePrimer = new NuGetCachePrimer(
commandFactoryMock.Object,
nugetPackagesArchiverMock.Object, nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object, _nugetCacheSentinel.Object,
fileSystemMock.Directory, _nugetConfigMock.Object,
_cliFallbackFolderPathCalculator,
fileSystemMock.File); fileSystemMock.File);
nugetCachePrimer.PrimeCache(); nugetCachePrimer.PrimeCache();
nugetPackagesArchiverMock.Verify(n => n.ExtractArchive(), Times.Never); nugetPackagesArchiverMock.Verify(n => n.ExtractArchive(It.IsAny<string>()), Times.Never);
commandFactoryMock.Verify(c => c.Create(
It.IsAny<string>(),
It.IsAny<IEnumerable<string>>(),
null,
Constants.DefaultConfiguration), Times.Never);
} }
[Fact] [Fact]
public void It_disposes_the_temporary_directory_created_for_the_temporary_project_used_to_prime_the_cache() public void It_adds_the_fallback_folder_to_NuGet_Config()
{ {
_temporaryDirectoryMock.DisposedTemporaryDirectory.Should().BeTrue(); _nugetConfigMock.Verify(n =>
} n.AddCliFallbackFolder(_cliFallbackFolderPathCalculator.CliFallbackFolderPath),
[Fact]
public void It_runs_dotnet_new_using_the_temporary_folder()
{
_dotnetNewCommandMock.Verify(c => c.WorkingDirectory(TEMPORARY_FOLDER_PATH), Times.Exactly(1));
}
[Fact]
public void It_runs_dotnet_new_capturing_stdout()
{
_dotnetNewCommandMock.Verify(c => c.CaptureStdOut(), Times.Exactly(1));
}
[Fact]
public void It_runs_dotnet_new_capturing_stderr()
{
_dotnetNewCommandMock.Verify(c => c.CaptureStdErr(), Times.Exactly(1));
}
[Fact]
public void It_actually_runs_dotnet_new()
{
_dotnetNewCommandMock.Verify(c => c.Execute(), Times.Exactly(1));
}
[Fact]
public void It_uses_the_packages_archive_with_dotnet_restore()
{
_commandFactoryMock.Verify(
c => c.Create(
"restore",
new[] { "-s", $"{PACKAGES_ARCHIVE_PATH}" },
null,
Constants.DefaultConfiguration),
Times.Exactly(1)); Times.Exactly(1));
} }
[Fact] [Fact]
public void It_does_not_run_restore_if_dotnet_new_fails() public void It_extracts_the_archive_to_the_fallback_folder()
{ {
var commandFactoryMock = SetupCommandFactoryMock(); _nugetPackagesArchiverMock.Verify(n =>
_dotnetNewCommandMock.Setup(c => c.Execute()).Returns(new CommandResult(null, -1, null, null)); n.ExtractArchive(_cliFallbackFolderPathCalculator.CliFallbackFolderPath),
Times.Exactly(1));
var nugetCachePrimer = new NuGetCachePrimer(
commandFactoryMock.Object,
_nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object,
_fileSystemMock.Directory,
_fileSystemMock.File);
nugetCachePrimer.PrimeCache();
commandFactoryMock.Verify(
c => c.Create(
"restore",
It.IsAny<IEnumerable<string>>(),
It.IsAny<NuGetFramework>(),
It.IsAny<string>()),
Times.Never);
}
[Fact]
public void It_runs_dotnet_restore_using_the_temporary_folder()
{
_dotnetRestoreCommandMock.Verify(c => c.WorkingDirectory(TEMPORARY_FOLDER_PATH), Times.Exactly(1));
}
[Fact]
public void It_runs_dotnet_restore_capturing_stdout()
{
_dotnetRestoreCommandMock.Verify(c => c.CaptureStdOut(), Times.Exactly(1));
}
[Fact]
public void It_runs_dotnet_restore_capturing_stderr()
{
_dotnetRestoreCommandMock.Verify(c => c.CaptureStdErr(), Times.Exactly(1));
}
[Fact]
public void It_actually_runs_dotnet_restore()
{
_dotnetRestoreCommandMock.Verify(c => c.Execute(), Times.Exactly(1));
} }
[Fact] [Fact]
@ -213,20 +98,22 @@ namespace Microsoft.DotNet.Configurer.UnitTests
} }
[Fact] [Fact]
public void It_does_not_create_a_sentinel_when_restore_fails() public void It_does_not_create_a_sentinel_when_extracting_the_archive_fails()
{ {
var nugetCacheSentinel = new Mock<INuGetCacheSentinel>(); var nugetCacheSentinel = new Mock<INuGetCacheSentinel>();
_dotnetRestoreCommandMock.Setup(c => c.Execute()).Returns(new CommandResult(null, -1, null, null)); var nugetPackagesArchiveMock = new Mock<INuGetPackagesArchiver>();
nugetPackagesArchiveMock.Setup(n => n.ExtractArchive(It.IsAny<string>())).Throws<Exception>();
var nugetCachePrimer = new NuGetCachePrimer( var nugetCachePrimer = new NuGetCachePrimer(
_commandFactoryMock.Object, nugetPackagesArchiveMock.Object,
_nugetPackagesArchiverMock.Object,
nugetCacheSentinel.Object, nugetCacheSentinel.Object,
_fileSystemMock.Directory, _nugetConfigMock.Object,
_cliFallbackFolderPathCalculator,
_fileSystemMock.File); _fileSystemMock.File);
nugetCachePrimer.PrimeCache(); Action action = () => nugetCachePrimer.PrimeCache();
action.ShouldThrow<Exception>();
nugetCacheSentinel.Verify(n => n.CreateIfNotExists(), Times.Never); nugetCacheSentinel.Verify(n => n.CreateIfNotExists(), Times.Never);
} }
} }

View file

@ -0,0 +1,53 @@
// 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.Collections.Generic;
using FluentAssertions;
using Moq;
using NuGet.Configuration;
using Xunit;
namespace Microsoft.DotNet.Configurer.UnitTests
{
public class GivenANuGetConfig
{
private const string PathToFallbackFolderAlreadySet = "some path to fallback folder";
private Mock<ISettings> _settingsMock;
private INuGetConfig _nugetConfig;
public GivenANuGetConfig()
{
_settingsMock = new Mock<ISettings>();
_settingsMock
.Setup(s => s.GetSettingValues(NuGetConfig.FallbackPackageFolders, false))
.Returns(new List<SettingValue>()
{
new SettingValue("CliFallbackFolder", PathToFallbackFolderAlreadySet, false)
});
_nugetConfig = new NuGetConfig(_settingsMock.Object);
}
[Fact]
public void ItAddsACliFallbackFolderIfOneIsNotPresentAlready()
{
const string FallbackFolderNotAlreadySet = "some path not already set";
_nugetConfig.AddCliFallbackFolder(FallbackFolderNotAlreadySet);
_settingsMock.Verify(s =>
s.SetValue(NuGetConfig.FallbackPackageFolders, "CliFallbackFolder", FallbackFolderNotAlreadySet),
Times.Exactly(1));
}
[Fact]
public void ItDoesNotAddTheCliFallbackFolderIfItIsAlreadyPresent()
{
_nugetConfig.AddCliFallbackFolder(PathToFallbackFolderAlreadySet);
_settingsMock.Verify(s =>
s.SetValue(NuGetConfig.FallbackPackageFolders, "CliFallbackFolder", PathToFallbackFolderAlreadySet),
Times.Never);
}
}
}

View file

@ -9,6 +9,7 @@
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign> <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageTargetFallback>$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback> <PackageTargetFallback>$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback>
<NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -18,7 +19,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NETStandard.Library" Version="1.6.0" />
<PackageReference Include="FluentAssertions" Version="4.18.0" /> <PackageReference Include="FluentAssertions" Version="4.18.0" />
<PackageReference Include="xunit" Version="2.2.0-beta4-build3444" /> <PackageReference Include="xunit" Version="2.2.0-beta4-build3444" />
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="$(PlatformAbstractionsVersion)" /> <PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="$(PlatformAbstractionsVersion)" />

View file

@ -60,6 +60,8 @@ namespace Microsoft.DotNet.New.Tests
string projectFolder, string projectFolder,
string packagesDirectory) string packagesDirectory)
{ {
var repoRootNuGetConfig = Path.Combine(RepoDirectoriesProvider.RepoRoot, "NuGet.Config");
new NewCommand() new NewCommand()
.WithWorkingDirectory(projectFolder) .WithWorkingDirectory(projectFolder)
.Execute($"{projectType} --debug:ephemeral-hive") .Execute($"{projectType} --debug:ephemeral-hive")
@ -67,7 +69,7 @@ namespace Microsoft.DotNet.New.Tests
new RestoreCommand() new RestoreCommand()
.WithWorkingDirectory(projectFolder) .WithWorkingDirectory(projectFolder)
.Execute($"--packages {packagesDirectory}") .Execute($"--configfile {repoRootNuGetConfig} --packages {packagesDirectory}")
.Should().Pass(); .Should().Pass();
} }
@ -80,6 +82,7 @@ namespace Microsoft.DotNet.New.Tests
var packagesDirectory = Path.Combine(rootPath, "packages"); var packagesDirectory = Path.Combine(rootPath, "packages");
var projectName = "Project"; var projectName = "Project";
var expectedVersion = GetFrameworkPackageVersion(); var expectedVersion = GetFrameworkPackageVersion();
var repoRootNuGetConfig = Path.Combine(RepoDirectoriesProvider.RepoRoot, "NuGet.Config");
new NewCommand() new NewCommand()
.WithWorkingDirectory(rootPath) .WithWorkingDirectory(rootPath)
@ -88,7 +91,7 @@ namespace Microsoft.DotNet.New.Tests
new RestoreCommand() new RestoreCommand()
.WithWorkingDirectory(rootPath) .WithWorkingDirectory(rootPath)
.Execute($"--packages {packagesDirectory}") .Execute($"--configfile {repoRootNuGetConfig} --packages {packagesDirectory}")
.Should().Pass(); .Should().Pass();
new DirectoryInfo(Path.Combine(packagesDirectory, packageName)) new DirectoryInfo(Path.Combine(packagesDirectory, packageName))

View file

@ -14,6 +14,8 @@ namespace Microsoft.DotNet.Restore.Tests
{ {
public class GivenThatIWantToRestoreApp : TestBase public class GivenThatIWantToRestoreApp : TestBase
{ {
private static string RepoRootNuGetConfig = Path.Combine(RepoDirectoriesProvider.RepoRoot, "NuGet.Config");
[Fact] [Fact]
public void ItRestoresAppToSpecificDirectory() public void ItRestoresAppToSpecificDirectory()
{ {
@ -29,7 +31,7 @@ namespace Microsoft.DotNet.Restore.Tests
.Should() .Should()
.Pass(); .Pass();
string args = $"--packages \"{dir}\""; string args = $"--configfile {RepoRootNuGetConfig} --packages \"{dir}\"";
new RestoreCommand() new RestoreCommand()
.WithWorkingDirectory(rootPath) .WithWorkingDirectory(rootPath)
.ExecuteWithCapturedOutput(args) .ExecuteWithCapturedOutput(args)
@ -56,7 +58,7 @@ namespace Microsoft.DotNet.Restore.Tests
.Should() .Should()
.Pass(); .Pass();
string args = $"--packages \"{dir}\""; string args = $"--configfile {RepoRootNuGetConfig} --packages \"{dir}\"";
new RestoreCommand() new RestoreCommand()
.WithWorkingDirectory(rootPath) .WithWorkingDirectory(rootPath)
.ExecuteWithCapturedOutput(args) .ExecuteWithCapturedOutput(args)
@ -76,7 +78,7 @@ namespace Microsoft.DotNet.Restore.Tests
string dir = "pkgs"; string dir = "pkgs";
string fullPath = Path.GetFullPath(Path.Combine(rootPath, dir)); string fullPath = Path.GetFullPath(Path.Combine(rootPath, dir));
string args = $"--packages \"{dir}\""; string args = $"--configfile {RepoRootNuGetConfig} --packages \"{dir}\"";
new RestoreCommand() new RestoreCommand()
.WithWorkingDirectory(rootPath) .WithWorkingDirectory(rootPath)
.ExecuteWithCapturedOutput(args) .ExecuteWithCapturedOutput(args)

View file

@ -19,23 +19,25 @@ namespace Microsoft.DotNet.Tests
{ {
private static CommandResult _firstDotnetNonVerbUseCommandResult; private static CommandResult _firstDotnetNonVerbUseCommandResult;
private static CommandResult _firstDotnetVerbUseCommandResult; private static CommandResult _firstDotnetVerbUseCommandResult;
private static DirectoryInfo _nugetCacheFolder; private static DirectoryInfo _nugetFallbackFolder;
static GivenThatTheUserIsRunningDotNetForTheFirstTime() static GivenThatTheUserIsRunningDotNetForTheFirstTime()
{ {
var testDirectory = TestAssets.CreateTestDirectory("Dotnet_first_time_experience_tests"); var testDirectory = TestAssets.CreateTestDirectory("Dotnet_first_time_experience_tests");
var testNugetCache = Path.Combine(testDirectory.FullName, "nuget_cache"); var testNuGetHome = Path.Combine(testDirectory.FullName, "nuget_home");
var command = new DotnetCommand() var command = new DotnetCommand()
.WithWorkingDirectory(testDirectory); .WithWorkingDirectory(testDirectory);
command.Environment["NUGET_PACKAGES"] = testNugetCache; command.Environment["HOME"] = testNuGetHome;
command.Environment["USERPROFILE"] = testNuGetHome;
command.Environment["APPDATA"] = testNuGetHome;
command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = ""; command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "";
command.Environment["SkipInvalidConfigurations"] = "true"; command.Environment["SkipInvalidConfigurations"] = "true";
_firstDotnetNonVerbUseCommandResult = command.ExecuteWithCapturedOutput("--info"); _firstDotnetNonVerbUseCommandResult = command.ExecuteWithCapturedOutput("--info");
_firstDotnetVerbUseCommandResult = command.ExecuteWithCapturedOutput("new --debug:ephemeral-hive"); _firstDotnetVerbUseCommandResult = command.ExecuteWithCapturedOutput("new --debug:ephemeral-hive");
_nugetCacheFolder = new DirectoryInfo(testNugetCache); _nugetFallbackFolder = new DirectoryInfo(Path.Combine(testNuGetHome, ".dotnet", "NuGetFallbackFolder"));
} }
[Fact] [Fact]
@ -82,7 +84,7 @@ A command is running to initially populate your local package cache, to improve
[Fact] [Fact]
public void ItCreatesASentinelFileUnderTheNuGetCacheFolder() public void ItCreatesASentinelFileUnderTheNuGetCacheFolder()
{ {
_nugetCacheFolder _nugetFallbackFolder
.Should() .Should()
.HaveFile($"{GetDotnetVersion()}.dotnetSentinel"); .HaveFile($"{GetDotnetVersion()}.dotnetSentinel");
} }
@ -115,11 +117,11 @@ A command is running to initially populate your local package cache, to improve
"microsoft.visualstudio.web.browserlink", "microsoft.visualstudio.web.browserlink",
}; };
_nugetCacheFolder _nugetFallbackFolder
.Should() .Should()
.HaveDirectories(expectedDirectories); .HaveDirectories(expectedDirectories);
_nugetCacheFolder _nugetFallbackFolder
.Should() .Should()
.NotHaveDirectories(unexpectedDirectories); .NotHaveDirectories(unexpectedDirectories);
} }