Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create tracking file when user-profile nuget.config does not exist #4338

Merged
merged 7 commits into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public static class NuGetConstants

public static readonly string FeedName = "nuget.org";

internal const string V3TrackFile = "nugetorgadd.trk";

public static readonly string DefaultConfigContent = @"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<packageSources>
Expand Down
37 changes: 34 additions & 3 deletions src/NuGet.Core/NuGet.Configuration/Settings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ public static ISettings LoadDefaultSettings(
}

/// <summary>
/// Loads Specific NuGet.Config file. The method only loads specific config file
/// Loads Specific NuGet.Config file. The method only loads specific config file
/// which is file <paramref name="configFileName"/>from <paramref name="root"/>.
/// </summary>
public static ISettings LoadSpecificSettings(string root, string configFileName)
Expand Down Expand Up @@ -545,11 +545,42 @@ internal static IEnumerable<SettingsFile> LoadUserSpecificSettings(
yield break;
}

var defaultSettingsFilePath = Path.Combine(userSettingsDir, DefaultSettingsFileName);
string defaultSettingsFilePath = Path.Combine(userSettingsDir, DefaultSettingsFileName);
bool settingsFileExists = File.Exists(defaultSettingsFilePath);

// If the default user config NuGet.Config does not exist, we need to create it.
if (!settingsFileExists)
{
if (!Directory.Exists(userSettingsDir))
{
Directory.CreateDirectory(userSettingsDir);
}

// Write tracking file, so that if the customer removes nuget.org as a package source
// it does not come back one more time.
File.WriteAllText(defaultSettingsFilePath, NuGetConstants.DefaultConfigContent);
string trackFilePath = Path.Combine(userSettingsDir, NuGetConstants.V3TrackFile);
File.Create(trackFilePath).Dispose();
}

// ReadSettings will try to create the default config file if it doesn't exist
SettingsFile userSpecificSettings = ReadSettings(rootDirectory, defaultSettingsFilePath, settingsLoadingContext: settingsLoadingContext);

// Handle when some other product created nuget.config using an old version of NuGet.Core.dll or NuGet.Configuration.dll that did not
// automatically add nuget.org as a package source.
if (settingsFileExists && userSpecificSettings.IsEmpty())
{
string trackFilePath = Path.Combine(Path.GetDirectoryName(defaultSettingsFilePath), NuGetConstants.V3TrackFile);

if (!File.Exists(trackFilePath))
{
File.Create(trackFilePath).Dispose();

SourceItem defaultSource = new(NuGetConstants.FeedName, NuGetConstants.V3FeedUrl, protocolVersion: "3");
userSpecificSettings.AddOrUpdate(ConfigurationConstants.PackageSources, defaultSource);
userSpecificSettings.SaveToDisk();
}
}

yield return userSpecificSettings;

// For backwards compatibility, we first return default user specific the non-default configs and then the additional files from the nested `config` directory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1814,7 +1814,7 @@ public void DisabledMachineWideSourceByDefaultWithNull(bool useStaticMethod)
List<PackageSource> sources = LoadPackageSources(useStaticMethod, settings);

// Assert
Assert.Equal(0, sources.Count);
Assert.Equal(1, sources.Count);
}
}

Expand Down
118 changes: 75 additions & 43 deletions test/NuGet.Core.Tests/NuGet.Configuration.Test/SettingsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2021,63 +2021,95 @@ public void LoadDefaultSettings_WithUserSpecifiedConfigFile_IgnoresOtherSettings
}

[Fact]
public void LoadSettings_EmptyUserWideConfigFile_DoNotAddNuGetOrg()
public void LoadSettings_UserSettingsFolderDoesNotExist_DefaultNuGetConfigAndTrackingFilesCreated()
{
using (var mockBaseDirectory = TestDirectory.Create())
{
// Arrange
var config = @"<?xml version=""1.0"" encoding=""utf-8""?>
// Arrange
using TestDirectory mockSolutionDirectory = TestDirectory.Create();
// Settings.LoadSettings' useTestingGlobalPath will use a subdirectory, instead of machine configuration, to allow for testing.
string mockUserProfileDirectory = Path.Combine(mockSolutionDirectory, "TestingGlobalPath");

// Act
ISettings settings = Settings.LoadSettings(
root: mockSolutionDirectory,
configFileName: null,
machineWideSettings: null,
loadUserWideSettings: true,
useTestingGlobalPath: true);

// Assert

// Check that the config file has the expected contents
string actual = SettingsTestUtils.RemoveWhitespace(File.ReadAllText(Path.Combine(mockUserProfileDirectory, "NuGet.Config")));
string expected = SettingsTestUtils.RemoveWhitespace(NuGetConstants.DefaultConfigContent);
actual.Should().Be(expected);

// Check that the tracking file exists, so that nuget.org won't be re-added if the customer removes it.
Assert.True(File.Exists(Path.Combine(mockUserProfileDirectory, NuGetConstants.V3TrackFile)));
}

[Fact]
public void LoadSettings_UserNuGetConfigIsEmptyWithoutTrackingFile_NuGetOrgSourceAddedAndTrackingFileCreated()
{
// Arrange
using TestDirectory mockSolutionDirectory = TestDirectory.Create();
// Settings.LoadSettings' useTestingGlobalPath will use a subdirectory, instead of machine configuration, to allow for testing.
string mockUserProfileDirectory = Path.Combine(mockSolutionDirectory, "TestingGlobalPath");

string emptyConfig = @"<?xml version=""1.0"" encoding=""utf-8""?>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Literals should be implicit types

<configuration>
</configuration>";

var nugetConfigPath = "NuGet.Config";
SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, Path.Combine(mockBaseDirectory, "TestingGlobalPath"), config);
string nugetConfigPath = "NuGet.Config";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Literals should be implicit types

SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, mockUserProfileDirectory, emptyConfig);

// Act
var settings = Settings.LoadSettings(
root: mockBaseDirectory,
configFileName: null,
machineWideSettings: null,
loadUserWideSettings: true,
useTestingGlobalPath: true);
// Act
ISettings settings = Settings.LoadSettings(
root: mockSolutionDirectory,
configFileName: null,
machineWideSettings: null,
loadUserWideSettings: true,
useTestingGlobalPath: true);

// Assert
var actual = SettingsTestUtils.RemoveWhitespace(File.ReadAllText(Path.Combine(mockBaseDirectory, "TestingGlobalPath", "NuGet.Config")));
var expected = SettingsTestUtils.RemoveWhitespace(config);
// Assert
// Check that the config file has the expected contents
string actual = SettingsTestUtils.RemoveWhitespace(File.ReadAllText(Path.Combine(mockUserProfileDirectory, "NuGet.Config")));
string expected = SettingsTestUtils.RemoveWhitespace(NuGetConstants.DefaultConfigContent);
actual.Should().Be(expected);

actual.Should().Be(expected);
}
// Check that the tracking file exists, so that nuget.org won't be re-added if the customer removes it.
Assert.True(File.Exists(Path.Combine(mockUserProfileDirectory, NuGetConstants.V3TrackFile)));
}

[Fact]
public void LoadSettings_NonExistingUserWideConfigFile_CreateUserWideConfigFileWithNuGetOrg()
public void LoadSettings_UserNuGetConfigIsEmptyAndTrackingFileExists_ConfigFileNotModified()
{
using (var mockBaseDirectory = TestDirectory.Create())
{
// Arrange
var nugetConfigPath = Path.Combine(mockBaseDirectory, "TestingGlobalPath", "NuGet.Config");
File.Exists(nugetConfigPath).Should().BeFalse();

// Act
var settings = Settings.LoadSettings(
root: mockBaseDirectory,
configFileName: null,
machineWideSettings: null,
loadUserWideSettings: true,
useTestingGlobalPath: true);
// Arrange
using TestDirectory mockSolutionDirectory = TestDirectory.Create();
// Settings.LoadSettings' useTestingGlobalPath will use a subdirectory, instead of machine configuration, to allow for testing.
string mockUserProfileDirectory = Path.Combine(mockSolutionDirectory, "TestingGlobalPath");

// Assert
File.Exists(nugetConfigPath).Should().BeTrue();
var actual = SettingsTestUtils.RemoveWhitespace(File.ReadAllText(nugetConfigPath));
var expected = SettingsTestUtils.RemoveWhitespace(@"<?xml version=""1.0"" encoding=""utf-8""?>
string emptyConfig = @"<?xml version=""1.0"" encoding=""utf-8""?>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Literals should be implicit types

<configuration>
<packageSources>
<add key=""nuget.org"" value=""https://api.nuget.org/v3/index.json"" protocolVersion=""3"" />
</packageSources>
</configuration>");
</configuration>";

actual.Should().Be(expected);
}
string nugetConfigPath = "NuGet.Config";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Literals should be implicit types

SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, mockUserProfileDirectory, emptyConfig);

File.WriteAllText(Path.Combine(mockUserProfileDirectory, NuGetConstants.V3TrackFile), string.Empty);

// Act
ISettings settings = Settings.LoadSettings(
root: mockSolutionDirectory,
configFileName: null,
machineWideSettings: null,
loadUserWideSettings: true,
useTestingGlobalPath: true);

// Assert
// Check that the config file has the expected contents
string actual = SettingsTestUtils.RemoveWhitespace(File.ReadAllText(Path.Combine(mockUserProfileDirectory, "NuGet.Config")));
string expected = SettingsTestUtils.RemoveWhitespace(emptyConfig);
actual.Should().Be(expected);
}

[Theory]
Expand Down