Adding the code to extract the archive in the first use of dotnet an

d added the first time use welcome text as well as some E2E tests.
This commit is contained in:
Livar Cunha 2016-06-09 20:52:49 -07:00
parent 5f220a1677
commit 69f43beccd
11 changed files with 222 additions and 42 deletions

View file

@ -338,14 +338,9 @@ namespace Microsoft.DotNet.Cli.Build
.Execute()
.EnsureSuccessful();
var packagesToArchive = new List<string> { "-a", intermediateArchive };
var nuGetPackagesArchiveDirectory = new DirectoryInfo(nuGetPackagesArchiveFolder);
foreach (var directory in nuGetPackagesArchiveDirectory.GetDirectories())
{
packagesToArchive.Add(directory.FullName);
}
Cmd(archiver, packagesToArchive)
Cmd(archiver,
"-a", intermediateArchive,
nuGetPackagesArchiveFolder)
.Execute();
File.Copy(intermediateArchive, finalArchive);

View file

@ -15,6 +15,8 @@ namespace Microsoft.DotNet.Cli.Utils
/// </summary>
public static string VersionFile => Path.GetFullPath(Path.Combine(typeof(DotnetFiles).GetTypeInfo().Assembly.Location, "..", ".version"));
public static string NuGetPackagesArchive => Path.GetFullPath(Path.Combine(typeof(DotnetFiles).GetTypeInfo().Assembly.Location, "..", "nuGetPackagesArchive.lzma"));
/// <summary>
/// Reads the version file and adds runtime specific information
/// </summary>

View file

@ -22,11 +22,34 @@ namespace Microsoft.DotNet.Configurer
{
if(ShouldPrimeNugetCache())
{
Reporter.Output.WriteLine("Configuring dotnet CLI for first time use.");
PrintFirstTimeUseNotice();
_nugetCachePrimer.PrimeCache();
}
}
private void PrintFirstTimeUseNotice()
{
Reporter.Output.WriteLine();
Reporter.Output.WriteLine("Welcome to .NET Core!");
Reporter.Output.WriteLine("---------------------");
Reporter.Output.WriteLine("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.");
Reporter.Output.WriteLine("Telemetry");
Reporter.Output.WriteLine("--------------");
Reporter.Output.WriteLine("The .NET Core tools collect usage data in order to improve your experience. " +
"The data is anonymous and does not include commandline arguments. " +
"The data is collected by Microsoft and shared with the community.");
Reporter.Output.WriteLine();
Reporter.Output.WriteLine("You can opt out of telemetry by setting a DOTNET_CLI_TELEMETRY_OPTOUT " +
"environment variable to 1 using your favorite shell.");
Reporter.Output.WriteLine("You can read more about .NET Core tools telemetry @ https://aka.ms/dotnet-cli-telemetry.");
Reporter.Output.WriteLine("Configuring...");
Reporter.Output.WriteLine("-------------------");
Reporter.Output.WriteLine("A command is running to initially populate your local package cache, to improve restore" +
"speed and enable offline access. This command will take up to a minute to complete and will only happen once.");
}
private bool ShouldPrimeNugetCache()
{
return !_nugetCacheSentinel.Exists();

View file

@ -1,10 +1,14 @@
// 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;
namespace Microsoft.DotNet.Configurer
{
public interface INuGetPackagesArchiver
public interface INuGetPackagesArchiver : IDisposable
{
string NuGetPackagesArchive { get; }
string ExtractArchive();
}
}

View file

@ -13,6 +13,7 @@ namespace Microsoft.DotNet.Configurer
private const string NUGET_SOURCE_PARAMETER = "-s";
private readonly ICommandFactory _commandFactory;
private readonly IDirectory _directory;
private readonly IFile _file;
private readonly INuGetPackagesArchiver _nugetPackagesArchiver;
private readonly INuGetCacheSentinel _nuGetCacheSentinel;
@ -20,7 +21,11 @@ namespace Microsoft.DotNet.Configurer
ICommandFactory commandFactory,
INuGetPackagesArchiver nugetPackagesArchiver,
INuGetCacheSentinel nuGetCacheSentinel)
: this(commandFactory, nugetPackagesArchiver, nuGetCacheSentinel, FileSystemWrapper.Default.Directory)
: this(commandFactory,
nugetPackagesArchiver,
nuGetCacheSentinel,
FileSystemWrapper.Default.Directory,
FileSystemWrapper.Default.File)
{
}
@ -28,21 +33,33 @@ namespace Microsoft.DotNet.Configurer
ICommandFactory commandFactory,
INuGetPackagesArchiver nugetPackagesArchiver,
INuGetCacheSentinel nuGetCacheSentinel,
IDirectory directory)
IDirectory directory,
IFile file)
{
_commandFactory = commandFactory;
_directory = directory;
_nugetPackagesArchiver = nugetPackagesArchiver;
_nuGetCacheSentinel = nuGetCacheSentinel;
_file = file;
}
public void PrimeCache()
{
if(SkipPrimingTheCache())
{
return;
}
var pathToPackagesArchive = _nugetPackagesArchiver.ExtractArchive();
PrimeCacheUsingArchive(pathToPackagesArchive);
}
private bool SkipPrimingTheCache()
{
return !_file.Exists(_nugetPackagesArchiver.NuGetPackagesArchive);
}
private void PrimeCacheUsingArchive(string pathToPackagesArchive)
{
using (var temporaryDotnetNewDirectory = _directory.CreateTemporaryDirectory())

View file

@ -1,20 +1,40 @@
// 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 Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Archive;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.Configurer
{
public class NuGetPackagesArchiver : INuGetPackagesArchiver
{
private ITemporaryDirectory _temporaryDirectory;
public string NuGetPackagesArchive => DotnetFiles.NuGetPackagesArchive;
public NuGetPackagesArchiver() : this(FileSystemWrapper.Default.Directory)
{
}
internal NuGetPackagesArchiver(IDirectory directory)
{
_temporaryDirectory = directory.CreateTemporaryDirectory();
}
public string ExtractArchive()
{
// -- ExtractArchive
// find archive
// extract archive to temporary folder
// Path.GetTempPath();
// Path.GetRandomFileName();
// Consider putting this inside an abstraction that will delete the folder automatically once it is done.
var progress = new ConsoleProgressReport();
var archive = new IndexedArchive();
return @"C:\Users\licavalc\git\temp\feed";
archive.Extract(NuGetPackagesArchive, _temporaryDirectory.DirectoryPath, progress);
return _temporaryDirectory.DirectoryPath;
}
public void Dispose()
{
_temporaryDirectory.Dispose();
}
}
}

View file

@ -13,14 +13,14 @@
},
"Microsoft.DotNet.ProjectModel": {
"target": "project"
},
"Microsoft.DotNet.Archive": {
"target": "project"
}
},
"frameworks": {
"netcoreapp1.0": {
"netstandard1.6": {
"imports": [
"dnxcore50",
"netstandardapp1.5",
"portable-net45+win8",
"portable-net45+wp80+win8+wpa81+dnxcore50"
]
}

View file

@ -57,13 +57,7 @@ namespace Microsoft.DotNet.Cli
{
using (PerfTrace.Current.CaptureTiming())
{
var nugetCacheSentinel = new NuGetCacheSentinel();
var nugetPackagesArchiver = new NuGetPackagesArchiver();
var commandFactory = new DotNetCommandFactory();
var nugetCachePrimer = new NuGetCachePrimer(commandFactory, nugetPackagesArchiver, nugetCacheSentinel);
var dotnetConfigurer = new DotnetFirstTimeUseConfigurer(nugetCachePrimer, nugetCacheSentinel);
dotnetConfigurer.Configure();
ConfigureDotNetForFirstTimeUse();
return ProcessArgs(args, new Telemetry());
}
@ -166,6 +160,18 @@ namespace Microsoft.DotNet.Cli
}
private static void ConfigureDotNetForFirstTimeUse()
{
using (var nugetPackagesArchiver = new NuGetPackagesArchiver())
{
var nugetCacheSentinel = new NuGetCacheSentinel();
var commandFactory = new DotNetCommandFactory();
var nugetCachePrimer = new NuGetCachePrimer(commandFactory, nugetPackagesArchiver, nugetCacheSentinel);
var dotnetConfigurer = new DotnetFirstTimeUseConfigurer(nugetCachePrimer, nugetCacheSentinel);
dotnetConfigurer.Configure();
}
}
private static void InitializeProcess()
{

View file

@ -16,6 +16,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
{
public class GivenANuGetCachePrimer
{
private const string COMPRESSED_ARCHIVE_PATH = "a path to somewhere";
private const string TEMPORARY_FOLDER_PATH = "some path";
private const string PACKAGES_ARCHIVE_PATH = "some other path";
@ -32,6 +33,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
{
var fileSystemMockBuilder = FileSystemMockBuilder.Create();
fileSystemMockBuilder.TemporaryFolder = TEMPORARY_FOLDER_PATH;
fileSystemMockBuilder.AddFile(COMPRESSED_ARCHIVE_PATH);
_fileSystemMock = fileSystemMockBuilder.Build();
_temporaryDirectoryMock = (ITemporaryDirectoryMock)_fileSystemMock.Directory.CreateTemporaryDirectory();
@ -39,6 +41,7 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_nugetPackagesArchiverMock = new Mock<INuGetPackagesArchiver>();
_nugetPackagesArchiverMock.Setup(n => n.ExtractArchive()).Returns(PACKAGES_ARCHIVE_PATH);
_nugetPackagesArchiverMock.Setup(n => n.NuGetPackagesArchive).Returns(COMPRESSED_ARCHIVE_PATH);
_nugetCacheSentinel = new Mock<INuGetCacheSentinel>();
@ -46,7 +49,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_commandFactoryMock.Object,
_nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object,
_fileSystemMock.Directory);
_fileSystemMock.Directory,
_fileSystemMock.File);
nugetCachePrimer.PrimeCache();
}
@ -83,6 +87,34 @@ namespace Microsoft.DotNet.Configurer.UnitTests
commandMock.Setup(c => c.CaptureStdErr()).Returns(commandMock.Object);
}
[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()
{
var fileSystemMockBuilder = FileSystemMockBuilder.Create();
var fileSystemMock = fileSystemMockBuilder.Build();
var commandFactoryMock = SetupCommandFactoryMock();
var nugetPackagesArchiverMock = new Mock<INuGetPackagesArchiver>();
nugetPackagesArchiverMock.Setup(n => n.NuGetPackagesArchive).Returns(COMPRESSED_ARCHIVE_PATH);
var nugetCachePrimer = new NuGetCachePrimer(
commandFactoryMock.Object,
nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object,
fileSystemMock.Directory,
fileSystemMock.File);
nugetCachePrimer.PrimeCache();
nugetPackagesArchiverMock.Verify(n => n.ExtractArchive(), Times.Never);
commandFactoryMock.Verify(c => c.Create(
It.IsAny<string>(),
It.IsAny<IEnumerable<string>>(),
null,
Constants.DefaultConfiguration), Times.Never);
}
[Fact]
public void It_disposes_the_temporary_directory_created_for_the_temporary_project_used_to_prime_the_cache()
{
@ -135,7 +167,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
commandFactoryMock.Object,
_nugetPackagesArchiverMock.Object,
_nugetCacheSentinel.Object,
_fileSystemMock.Directory);
_fileSystemMock.Directory,
_fileSystemMock.File);
nugetCachePrimer.PrimeCache();
@ -188,7 +221,8 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_commandFactoryMock.Object,
_nugetPackagesArchiverMock.Object,
nugetCacheSentinel.Object,
_fileSystemMock.Directory);
_fileSystemMock.Directory,
_fileSystemMock.File);
nugetCachePrimer.PrimeCache();

View file

@ -143,14 +143,16 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
[Fact]
public void CrossPublishingSucceedsAndHasExpectedArtifacts()
{
var testNugetCache = "packages_cross_publish_test";
TestInstance instance = TestAssetsManager.CreateTestInstance(Path.Combine("PortableTests"));
var testProject = Path.Combine(instance.TestRoot, "StandaloneApp", "project.json");
var workingDirectory = Path.GetDirectoryName(testProject);
var testNugetCache = Path.Combine(workingDirectory, "packages_cross_publish_test");
var restoreCommand = new RestoreCommand();
restoreCommand.WorkingDirectory = Path.GetDirectoryName(testProject);
restoreCommand.WorkingDirectory = workingDirectory;
restoreCommand.Environment["NUGET_PACKAGES"] = testNugetCache;
restoreCommand.Execute().Should().Pass();

View file

@ -0,0 +1,77 @@
// 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.Collections.Generic;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using FluentAssertions;
namespace Microsoft.DotNet.Tests
{
public class GivenThatTheUserIsRunningDotNetForTheFirstTime : TestBase
{
private static CommandResult _firstDotnetUseCommandResult;
private static DirectoryInfo _nugetCacheFolder;
static GivenThatTheUserIsRunningDotNetForTheFirstTime()
{
var testDirectory = TestAssetsManager.CreateTestDirectory("Dotnet_first_time_experience_tests");
var testNugetCache = Path.Combine(testDirectory.Path, "nuget_cache");
var command = new DotnetCommand()
.WithWorkingDirectory(testDirectory.Path);
command.Environment["NUGET_PACKAGES"] = testNugetCache;
_firstDotnetUseCommandResult = command.ExecuteWithCapturedOutput("new");
_nugetCacheFolder = new DirectoryInfo(testNugetCache);
}
[Fact]
public void Using_dotnet_for_the_first_time_succeeds()
{
_firstDotnetUseCommandResult.Should().Pass();
}
[Fact]
public void It_shows_the_appropriate_message_to_the_user()
{
const string firstTimeUseWelcomeMessage = @"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.
Telemetry
--------------
The .NET Core tools collect usage data in order to improve your experience. The data is anonymous and does not include commandline arguments. The data is collected by Microsoft and shared with the community.
You can opt out of telemetry by setting a DOTNET_CLI_TELEMETRY_OPTOUT environment variable to 1 using your favorite shell.
You can read more about .NET Core tools telemetry @ https://aka.ms/dotnet-cli-telemetry.
Configuring...
-------------------
A command is running to initially populate your local package cache, to improve restorespeed and enable offline access. This command will take up to a minute to complete and will only happen once.";
_firstDotnetUseCommandResult.StdOut.Should().StartWith(firstTimeUseWelcomeMessage);
}
[Fact]
public void It_restores_the_nuget_packages_to_the_nuget_cache_folder()
{
_nugetCacheFolder.Should().HaveFile($"{GetDotnetVersion()}.dotnetSentinel");
}
[Fact]
public void It_creates_a_sentinel_file_under_the_nuget_cache_folder()
{
_nugetCacheFolder.Should().HaveDirectory("Microsoft.NETCore.App");
}
private string GetDotnetVersion()
{
return new DotnetCommand().ExecuteWithCapturedOutput("--version").StdOut
.TrimEnd(Environment.NewLine.ToCharArray());
}
}
}