Making a change that will cause the first run notice to always show up in the first run of the CLI, even when it is installed by native installers.

This commit is contained in:
Livar Cunha 2017-07-25 22:30:36 -07:00
parent 5d07534663
commit 20f0dac6b2
7 changed files with 191 additions and 13 deletions

View file

@ -45,10 +45,12 @@ namespace Microsoft.DotNet.Configurer
{
PrintUnauthorizedAccessMessage();
}
else
{
PrintNugetCachePrimeMessage();
PrintNugetCachePrimeMessage();
_nugetCachePrimer.PrimeCache();
_nugetCachePrimer.PrimeCache();
}
}
}
@ -81,6 +83,8 @@ namespace Microsoft.DotNet.Configurer
private bool ShouldPrimeNugetCache()
{
return ShouldRunFirstRunExperience() &&
!_nugetCacheSentinel.Exists() &&
!_nugetCacheSentinel.InProgressSentinelAlreadyExists() &&
!_nugetCachePrimer.SkipPrimingTheCache();
}
@ -96,9 +100,7 @@ namespace Microsoft.DotNet.Configurer
var skipFirstTimeExperience =
_environmentProvider.GetEnvironmentVariableAsBool("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", false);
return !skipFirstTimeExperience &&
!_nugetCacheSentinel.Exists() &&
!_nugetCacheSentinel.InProgressSentinelAlreadyExists();
return !skipFirstTimeExperience;
}
}
}

View file

@ -0,0 +1,26 @@
// 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.IO;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Configuration;
namespace Microsoft.DotNet.Configurer
{
public class NoOpFirstTimeUseNoticeSentinel : IFirstTimeUseNoticeSentinel
{
public bool Exists()
{
return true;
}
public void CreateIfNotExists()
{
}
public void Dispose()
{
}
}
}

View file

@ -45,7 +45,7 @@ namespace Microsoft.DotNet.Configurer
public bool InProgressSentinelAlreadyExists()
{
return CouldNotGetAHandleToTheInProgressSentinel();
return CouldNotGetAHandleToTheInProgressSentinel() && !UnauthorizedAccess;
}
public bool Exists()

View file

@ -81,8 +81,10 @@ namespace Microsoft.DotNet.Cli
var lastArg = 0;
var cliFallbackFolderPathCalculator = new CliFallbackFolderPathCalculator();
using (INuGetCacheSentinel nugetCacheSentinel = new NuGetCacheSentinel(cliFallbackFolderPathCalculator))
using (IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel = new FirstTimeUseNoticeSentinel(cliFallbackFolderPathCalculator))
using (IFirstTimeUseNoticeSentinel disposableFirstTimeUseNoticeSentinel =
new FirstTimeUseNoticeSentinel(cliFallbackFolderPathCalculator))
{
IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel = disposableFirstTimeUseNoticeSentinel;
for (; lastArg < args.Length; lastArg++)
{
if (IsArg(args[lastArg], "d", "diagnostics"))
@ -113,10 +115,19 @@ namespace Microsoft.DotNet.Cli
}
else
{
ConfigureDotNetForFirstTimeUse(nugetCacheSentinel, firstTimeUseNoticeSentinel, cliFallbackFolderPathCalculator);
// It's the command, and we're done!
command = args[lastArg];
if (IsDotnetBeingInvokedFromNativeInstaller(command))
{
firstTimeUseNoticeSentinel = new NoOpFirstTimeUseNoticeSentinel();
}
ConfigureDotNetForFirstTimeUse(
nugetCacheSentinel,
firstTimeUseNoticeSentinel,
cliFallbackFolderPathCalculator);
break;
}
}
@ -164,7 +175,11 @@ namespace Microsoft.DotNet.Cli
}
return exitCode;
}
private static bool IsDotnetBeingInvokedFromNativeInstaller(string command)
{
return command == "internal-reportinstallsuccess";
}
private static void ConfigureDotNetForFirstTimeUse(

View file

@ -233,5 +233,73 @@ namespace Microsoft.DotNet.Configurer.UnitTests
_nugetCachePrimerMock.Verify(r => r.PrimeCache(), Times.Once);
_reporterMock.Verify(r => r.Write(It.IsAny<string>()), Times.Never);
}
[Fact]
public void It_prints_the_first_time_use_notice_if_the_cache_sentinel_exists_but_the_first_notice_sentinel_does_not()
{
_nugetCacheSentinelMock.Setup(n => n.Exists()).Returns(true);
_firstTimeUseNoticeSentinelMock.Setup(n => n.Exists()).Returns(false);
var dotnetFirstTimeUseConfigurer = new DotnetFirstTimeUseConfigurer(
_nugetCachePrimerMock.Object,
_nugetCacheSentinelMock.Object,
_firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object,
_reporterMock.Object,
CliFallbackFolderPath);
dotnetFirstTimeUseConfigurer.Configure();
_reporterMock.Verify(r =>
r.WriteLine(It.Is<string>(str => str == LocalizableStrings.FirstTimeWelcomeMessage)));
_reporterMock.Verify(
r => r.WriteLine(It.Is<string>(str => str == LocalizableStrings.NugetCachePrimeMessage)),
Times.Never);
_reporterMock.Verify(r => r.Write(It.IsAny<string>()), Times.Never);
}
[Fact]
public void It_prints_the_unauthorized_notice_if_the_cache_sentinel_reports_Unauthorized()
{
_nugetCacheSentinelMock.Setup(n => n.UnauthorizedAccess).Returns(true);
var dotnetFirstTimeUseConfigurer = new DotnetFirstTimeUseConfigurer(
_nugetCachePrimerMock.Object,
_nugetCacheSentinelMock.Object,
_firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object,
_reporterMock.Object,
CliFallbackFolderPath);
dotnetFirstTimeUseConfigurer.Configure();
_reporterMock.Verify(r =>
r.WriteLine(It.Is<string>(str => str == LocalizableStrings.FirstTimeWelcomeMessage)));
_reporterMock.Verify(r =>
r.WriteLine(It.Is<string>(str =>
str == string.Format(LocalizableStrings.UnauthorizedAccessMessage, CliFallbackFolderPath))));
_reporterMock.Verify(
r => r.WriteLine(It.Is<string>(str => str == LocalizableStrings.NugetCachePrimeMessage)),
Times.Never);
_reporterMock.Verify(r => r.Write(It.IsAny<string>()), Times.Never);
}
[Fact]
public void It_does_not_prime_the_cache_if_the_cache_sentinel_reports_Unauthorized()
{
_nugetCacheSentinelMock.Setup(n => n.UnauthorizedAccess).Returns(true);
var dotnetFirstTimeUseConfigurer = new DotnetFirstTimeUseConfigurer(
_nugetCachePrimerMock.Object,
_nugetCacheSentinelMock.Object,
_firstTimeUseNoticeSentinelMock.Object,
_environmentProviderMock.Object,
_reporterMock.Object,
CliFallbackFolderPath);
dotnetFirstTimeUseConfigurer.Configure();
_nugetCachePrimerMock.Verify(r => r.PrimeCache(), Times.Never);
}
}
}

View file

@ -70,6 +70,18 @@ namespace Microsoft.DotNet.Configurer.UnitTests
nugetCacheSentinel.InProgressSentinelAlreadyExists().Should().BeTrue();
}
[Fact]
public void It_returns_false_to_the_in_progress_sentinel_already_exists_when_it_fails_to_get_a_handle_to_it_but_it_failed_because_it_was_unauthorized()
{
var fileMock = new FileMock();
var directoryMock = new DirectoryMock();
fileMock.InProgressSentinel = null;
var nugetCacheSentinel =
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, directoryMock);
nugetCacheSentinel.InProgressSentinelAlreadyExists().Should().BeFalse();
}
[Fact]
public void It_returns_false_to_the_in_progress_sentinel_already_exists_when_it_succeeds_in_getting_a_handle_to_it()
{

View file

@ -20,15 +20,17 @@ namespace Microsoft.DotNet.Tests
private static CommandResult _firstDotnetNonVerbUseCommandResult;
private static CommandResult _firstDotnetVerbUseCommandResult;
private static DirectoryInfo _nugetFallbackFolder;
private static DirectoryInfo _dotDotnetFolder;
private static string _testDirectory;
static GivenThatTheUserIsRunningDotNetForTheFirstTime()
{
var testDirectory = TestAssets.CreateTestDirectory("Dotnet_first_time_experience_tests");
var testNuGetHome = Path.Combine(testDirectory.FullName, "nuget_home");
_testDirectory = TestAssets.CreateTestDirectory("Dotnet_first_time_experience_tests").FullName;
var testNuGetHome = Path.Combine(_testDirectory, "nuget_home");
var cliTestFallbackFolder = Path.Combine(testNuGetHome, ".dotnet", "NuGetFallbackFolder");
var command = new DotnetCommand()
.WithWorkingDirectory(testDirectory);
.WithWorkingDirectory(_testDirectory);
command.Environment["HOME"] = testNuGetHome;
command.Environment["USERPROFILE"] = testNuGetHome;
command.Environment["APPDATA"] = testNuGetHome;
@ -40,6 +42,7 @@ namespace Microsoft.DotNet.Tests
_firstDotnetVerbUseCommandResult = command.ExecuteWithCapturedOutput("new --debug:ephemeral-hive");
_nugetFallbackFolder = new DirectoryInfo(cliTestFallbackFolder);
_dotDotnetFolder = new DirectoryInfo(Path.Combine(testNuGetHome, ".dotnet"));
}
[Fact]
@ -77,6 +80,58 @@ namespace Microsoft.DotNet.Tests
.HaveFile($"{GetDotnetVersion()}.dotnetSentinel");
}
[Fact]
public void ItCreatesAFirstUseSentinelFileUnderTheDotDotNetFolder()
{
_dotDotnetFolder
.Should()
.HaveFile($"{GetDotnetVersion()}.dotnetFirstUseSentinel");
}
[Fact]
public void ItDoesNotCreateAFirstUseSentinelFileUnderTheDotDotNetFolderWhenInternalReportInstallSuccessIsInvoked()
{
var newHome = Path.Combine(_testDirectory, "new_home");
var newHomeFolder = new DirectoryInfo(Path.Combine(newHome, ".dotnet"));
var command = new DotnetCommand()
.WithWorkingDirectory(_testDirectory);
command.Environment["HOME"] = newHome;
command.Environment["USERPROFILE"] = newHome;
command.Environment["APPDATA"] = newHome;
command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = _nugetFallbackFolder.FullName;
command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "";
command.Environment["SkipInvalidConfigurations"] = "true";
command.ExecuteWithCapturedOutput("internal-reportinstallsuccess test").Should().Pass();
newHomeFolder.Should().NotHaveFile($"{GetDotnetVersion()}.dotnetFirstUseSentinel");
}
[Fact]
public void ItShowsTheTelemetryNoticeWhenInvokingACommandAfterInternalReportInstallSuccessHasBeenInvoked()
{
var newHome = Path.Combine(_testDirectory, "new_home");
var newHomeFolder = new DirectoryInfo(Path.Combine(newHome, ".dotnet"));
var command = new DotnetCommand()
.WithWorkingDirectory(_testDirectory);
command.Environment["HOME"] = newHome;
command.Environment["USERPROFILE"] = newHome;
command.Environment["APPDATA"] = newHome;
command.Environment["DOTNET_CLI_TEST_FALLBACKFOLDER"] = _nugetFallbackFolder.FullName;
command.Environment["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "";
command.Environment["SkipInvalidConfigurations"] = "true";
command.ExecuteWithCapturedOutput("internal-reportinstallsuccess test").Should().Pass();
var result = command.ExecuteWithCapturedOutput("new --debug:ephemeral-hive");
result.StdOut
.Should()
.ContainVisuallySameFragment(Configurer.LocalizableStrings.FirstTimeWelcomeMessage);
}
[Fact]
public void ItRestoresTheNuGetPackagesToTheNuGetCacheFolder()
{