diff --git a/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageDownloadTests.cs b/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageDownloadTests.cs new file mode 100644 index 000000000..51dad6c92 --- /dev/null +++ b/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageDownloadTests.cs @@ -0,0 +1,161 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using NSubstitute; +using NuGet.Versioning; +using NuKeeper.Abstractions.Logging; +using NuKeeper.Abstractions.RepositoryInspection; +using NuKeeper.Inspection.RepositoryInspection; +using NUnit.Framework; + +namespace NuKeeper.Inspection.Tests.RepositoryInspection +{ + [TestFixture] + public class DirectoryBuildTargetsReaderPackageDownloadTests + { + const string PackagesFileWithSinglePackage = + @""; + + private const string PackagesFileWithTwoPackages = @" + +"; + + [Test] + public void EmptyPackagesListShouldBeParsed() + { + const string emptyContents = + @""; + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(emptyContents), TempPath()); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages, Is.Empty); + } + + [Test] + public void SinglePackageShouldBeRead() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithSinglePackage), TempPath()); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages, Is.Not.Empty); + } + + [Test] + public void SinglePackageShouldBePopulated() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithSinglePackage), TempPath()); + + var package = packages.FirstOrDefault(); + PackageAssert.IsPopulated(package); + } + + [Test] + public void SinglePackageFromVerboseFormatShouldBePopulated() + { + const string verboseFormatVersion = + @"all1.2.3.4"; + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(verboseFormatVersion), TempPath()); + + var package = packages.FirstOrDefault(); + PackageAssert.IsPopulated(package); + } + + [Test] + public void SinglePackageShouldBeCorrect() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithSinglePackage), TempPath()); + + var package = packages.FirstOrDefault(); + + Assert.That(package, Is.Not.Null); + Assert.That(package.Id, Is.EqualTo("foo")); + Assert.That(package.Version, Is.EqualTo(new NuGetVersion("1.2.3.4"))); + Assert.That(package.Path.PackageReferenceType, Is.EqualTo(PackageReferenceType.DirectoryBuildTargets)); + } + + [Test] + public void TwoPackagesShouldBePopulated() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithTwoPackages), TempPath()) + .ToList(); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages.Count, Is.EqualTo(2)); + + PackageAssert.IsPopulated(packages[0]); + PackageAssert.IsPopulated(packages[1]); + } + + [Test] + public void TwoPackagesShouldBeRead() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithTwoPackages), TempPath()) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(2)); + + Assert.That(packages[0].Id, Is.EqualTo("foo")); + Assert.That(packages[0].Version, Is.EqualTo(new NuGetVersion("1.2.3.4"))); + + Assert.That(packages[1].Id, Is.EqualTo("bar")); + Assert.That(packages[1].Version, Is.EqualTo(new NuGetVersion("2.3.4.5"))); + } + + [Test] + public void ResultIsReiterable() + { + var path = TempPath(); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithTwoPackages), path); + + foreach (var package in packages) + { + PackageAssert.IsPopulated(package); + } + + Assert.That(packages.Select(p => p.Path), Is.All.EqualTo(path)); + } + + [Test] + public void WhenOnePackageCannotBeRead_TheOthersAreStillRead() + { + var badVersion = PackagesFileWithTwoPackages.Replace("1.2.3.4", "notaversion", StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(badVersion), TempPath()) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + PackageAssert.IsPopulated(packages[0]); + } + + private static PackagePath TempPath() + { + return new PackagePath( + OsSpecifics.GenerateBaseDirectory(), + Path.Combine("src", "Directory.Build.Props"), + PackageReferenceType.DirectoryBuildTargets); + } + + private static DirectoryBuildTargetsReader MakeReader() + { + return new DirectoryBuildTargetsReader(Substitute.For()); + } + + private static Stream StreamFromString(string contents) + { + return new MemoryStream(Encoding.UTF8.GetBytes(contents)); + } + } +} \ No newline at end of file diff --git a/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderTests.cs b/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageReferenceTests.cs similarity index 98% rename from NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderTests.cs rename to NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageReferenceTests.cs index ad4fbedcb..45277940b 100644 --- a/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderTests.cs +++ b/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageReferenceTests.cs @@ -12,7 +12,7 @@ namespace NuKeeper.Inspection.Tests.RepositoryInspection { [TestFixture] - public class DirectoryBuildTargetsReaderTests + public class DirectoryBuildTargetsReaderPackageReferenceTests { const string PackagesFileWithSinglePackage = @""; diff --git a/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageVersionTests.cs b/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageVersionTests.cs new file mode 100644 index 000000000..4c998f3ea --- /dev/null +++ b/NuKeeper.Inspection.Tests/RepositoryInspection/DirectoryBuildTargetsReaderPackageVersionTests.cs @@ -0,0 +1,161 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using NSubstitute; +using NuGet.Versioning; +using NuKeeper.Abstractions.Logging; +using NuKeeper.Abstractions.RepositoryInspection; +using NuKeeper.Inspection.RepositoryInspection; +using NUnit.Framework; + +namespace NuKeeper.Inspection.Tests.RepositoryInspection +{ + [TestFixture] + public class DirectoryBuildTargetsReaderPackageVersionTests + { + const string PackagesFileWithSinglePackage = + @""; + + private const string PackagesFileWithTwoPackages = @" + +"; + + [Test] + public void EmptyPackagesListShouldBeParsed() + { + const string emptyContents = + @""; + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(emptyContents), TempPath()); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages, Is.Empty); + } + + [Test] + public void SinglePackageShouldBeRead() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithSinglePackage), TempPath()); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages, Is.Not.Empty); + } + + [Test] + public void SinglePackageShouldBePopulated() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithSinglePackage), TempPath()); + + var package = packages.FirstOrDefault(); + PackageAssert.IsPopulated(package); + } + + [Test] + public void SinglePackageFromVerboseFormatShouldBePopulated() + { + const string verboseFormatVersion = + @"all1.2.3.4"; + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(verboseFormatVersion), TempPath()); + + var package = packages.FirstOrDefault(); + PackageAssert.IsPopulated(package); + } + + [Test] + public void SinglePackageShouldBeCorrect() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithSinglePackage), TempPath()); + + var package = packages.FirstOrDefault(); + + Assert.That(package, Is.Not.Null); + Assert.That(package.Id, Is.EqualTo("foo")); + Assert.That(package.Version, Is.EqualTo(new NuGetVersion("1.2.3.4"))); + Assert.That(package.Path.PackageReferenceType, Is.EqualTo(PackageReferenceType.DirectoryBuildTargets)); + } + + [Test] + public void TwoPackagesShouldBePopulated() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithTwoPackages), TempPath()) + .ToList(); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages.Count, Is.EqualTo(2)); + + PackageAssert.IsPopulated(packages[0]); + PackageAssert.IsPopulated(packages[1]); + } + + [Test] + public void TwoPackagesShouldBeRead() + { + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithTwoPackages), TempPath()) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(2)); + + Assert.That(packages[0].Id, Is.EqualTo("foo")); + Assert.That(packages[0].Version, Is.EqualTo(new NuGetVersion("1.2.3.4"))); + + Assert.That(packages[1].Id, Is.EqualTo("bar")); + Assert.That(packages[1].Version, Is.EqualTo(new NuGetVersion("2.3.4.5"))); + } + + [Test] + public void ResultIsReiterable() + { + var path = TempPath(); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(PackagesFileWithTwoPackages), path); + + foreach (var package in packages) + { + PackageAssert.IsPopulated(package); + } + + Assert.That(packages.Select(p => p.Path), Is.All.EqualTo(path)); + } + + [Test] + public void WhenOnePackageCannotBeRead_TheOthersAreStillRead() + { + var badVersion = PackagesFileWithTwoPackages.Replace("1.2.3.4", "notaversion", StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(badVersion), TempPath()) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + PackageAssert.IsPopulated(packages[0]); + } + + private static PackagePath TempPath() + { + return new PackagePath( + OsSpecifics.GenerateBaseDirectory(), + Path.Combine("src", "Directory.Packages.Props"), + PackageReferenceType.DirectoryBuildTargets); + } + + private static DirectoryBuildTargetsReader MakeReader() + { + return new DirectoryBuildTargetsReader(Substitute.For()); + } + + private static Stream StreamFromString(string contents) + { + return new MemoryStream(Encoding.UTF8.GetBytes(contents)); + } + } +} \ No newline at end of file diff --git a/NuKeeper.Inspection.Tests/RepositoryInspection/ProjectFileReaderTests.cs b/NuKeeper.Inspection.Tests/RepositoryInspection/ProjectFileReaderTests.cs index a064a9e45..a8b54e979 100644 --- a/NuKeeper.Inspection.Tests/RepositoryInspection/ProjectFileReaderTests.cs +++ b/NuKeeper.Inspection.Tests/RepositoryInspection/ProjectFileReaderTests.cs @@ -127,7 +127,7 @@ public void ProjectWithEmptyPackageListCanBeRead() } [Test] - public void SinglePackageCanBeRead() + public void SinglePackageCanBeReadPackageReferences() { const string packagesText = @""; @@ -140,6 +140,34 @@ public void SinglePackageCanBeRead() Assert.That(packages, Is.Not.Empty); } + [Test] + public void SinglePackageCanBeReadPackageDownloads() + { + const string packagesText = @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages, Is.Not.Empty); + } + + [Test] + public void SinglePackageCanBeReadPackageVersions() + { + const string packagesText = @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages, Is.Not.Empty); + } + [Test] public void SinglePackageIsPopulated() { @@ -199,7 +227,7 @@ public void RelativeProjectReferencesIsPopulated() } [Test] - public void SinglePackageIsCorectlyRead() + public void SinglePackageReferenceIsCorrectlyRead() { const string packagesText = @""; @@ -216,7 +244,41 @@ public void SinglePackageIsCorectlyRead() } [Test] - public void SinglePackageFullFrameworkProjectIsCorectlyRead() + public void SinglePackageDownloadIsCorrectlyRead() + { + const string packagesText = @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile); + + var package = packages.FirstOrDefault(); + + Assert.That(package.Id, Is.EqualTo("foo")); + Assert.That(package.Version, Is.EqualTo(new NuGetVersion("1.2.3"))); + Assert.That(package.Path.PackageReferenceType, Is.EqualTo(PackageReferenceType.DirectoryBuildTargets)); + } + + [Test] + public void SinglePackageIsCorrectlyRead() + { + const string packagesText = @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile); + + var package = packages.FirstOrDefault(); + + Assert.That(package.Id, Is.EqualTo("foo")); + Assert.That(package.Version, Is.EqualTo(new NuGetVersion("1.2.3"))); + Assert.That(package.Path.PackageReferenceType, Is.EqualTo(PackageReferenceType.DirectoryBuildTargets)); + } + + [Test] + public void SinglePackageFullFrameworkProjectIsCorrectlyRead() { var reader = MakeReader(); var packages = reader.Read(StreamFromString(Vs2017ProjectFileFullFrameworkWithPackages), _sampleDirectory, _sampleFile); @@ -229,7 +291,7 @@ public void SinglePackageFullFrameworkProjectIsCorectlyRead() } [Test] - public void WhenTwoPackagesAreRead_TheyArePopulated() + public void WhenTwoPackageReferencesAreRead_TheyArePopulated() { const string packagesText = @" @@ -248,7 +310,45 @@ public void WhenTwoPackagesAreRead_TheyArePopulated() } [Test] - public void WhenTwoPackagesAreRead_ValuesAreCorrect() + public void WhenTwoPackageDownloadsAreRead_TheyArePopulated() + { + const string packagesText = + @" + "; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages.Count, Is.EqualTo(2)); + PackageAssert.IsPopulated(packages[0]); + PackageAssert.IsPopulated(packages[1]); + } + + [Test] + public void WhenTwoPackageVersionsAreRead_TheyArePopulated() + { + const string packagesText = + @" + "; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages, Is.Not.Null); + Assert.That(packages.Count, Is.EqualTo(2)); + PackageAssert.IsPopulated(packages[0]); + PackageAssert.IsPopulated(packages[1]); + } + + [Test] + public void WhenTwoPackageReferencesAreRead_ValuesAreCorrect() { const string packagesText = @" @@ -267,6 +367,46 @@ public void WhenTwoPackagesAreRead_ValuesAreCorrect() Assert.That(packages[1].Version, Is.EqualTo(new NuGetVersion("2.3.4"))); } + [Test] + public void WhenTwoPackageDownloadsAreRead_ValuesAreCorrect() + { + const string packagesText = + @" + "; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages[0].Id, Is.EqualTo("foo")); + Assert.That(packages[0].Version, Is.EqualTo(new NuGetVersion("1.2.3"))); + + Assert.That(packages[1].Id, Is.EqualTo("bar")); + Assert.That(packages[1].Version, Is.EqualTo(new NuGetVersion("2.3.4"))); + } + + [Test] + public void WhenTwoPackageVersionsAreRead_ValuesAreCorrect() + { + const string packagesText = + @" + "; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages[0].Id, Is.EqualTo("foo")); + Assert.That(packages[0].Version, Is.EqualTo(new NuGetVersion("1.2.3"))); + + Assert.That(packages[1].Id, Is.EqualTo("bar")); + Assert.That(packages[1].Version, Is.EqualTo(new NuGetVersion("2.3.4"))); + } + [Test] public void ResultIsReiterable() { @@ -283,7 +423,7 @@ public void ResultIsReiterable() } [Test] - public void WhenOnePackageCannotBeRead_TheOthersAreStillRead() + public void WhenOnePackageReferenceCannotBeRead_TheOthersAreStillRead() { const string packagesText = @" @@ -300,7 +440,41 @@ public void WhenOnePackageCannotBeRead_TheOthersAreStillRead() } [Test] - public void PackageWithoutVersionShouldBeSkipped() + public void WhenOnePackageDownloadCannotBeRead_TheOthersAreStillRead() + { + const string packagesText = + @" + "; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + PackageAssert.IsPopulated(packages[0]); + } + + [Test] + public void WhenOnePackageVersionCannotBeRead_TheOthersAreStillRead() + { + const string packagesText = + @" + "; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", packagesText, StringComparison.OrdinalIgnoreCase); + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + PackageAssert.IsPopulated(packages[0]); + } + + [Test] + public void PackageReferenceWithoutVersionShouldBeSkipped() { const string noVersion = @""; @@ -316,7 +490,39 @@ public void PackageWithoutVersionShouldBeSkipped() } [Test] - public void PackageWithWildCardVersionShouldBeSkipped() + public void PackageDownloadWithoutVersionShouldBeSkipped() + { + const string noVersion = + @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages, Is.Empty); + } + + [Test] + public void PackageVersionWithoutVersionShouldBeSkipped() + { + const string noVersion = + @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages, Is.Empty); + } + + [Test] + public void PackageReferenceWithWildCardVersionShouldBeSkipped() { const string noVersion = @""; @@ -332,7 +538,23 @@ public void PackageWithWildCardVersionShouldBeSkipped() } [Test] - public void PackageWithBetaVersionShouldBeRead() + public void PackageVersionWithWildCardVersionShouldBeSkipped() + { + const string noVersion = + @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages, Is.Empty); + } + + [Test] + public void PackageReferenceWithBetaVersionShouldBeRead() { const string noVersion = @""; @@ -349,7 +571,41 @@ public void PackageWithBetaVersionShouldBeRead() } [Test] - public void PackageWithMetadataShouldBeRead() + public void PackageDownloadWithBetaVersionShouldBeRead() + { + const string noVersion = + @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + Assert.That(packages.First().IsPrerelease, Is.True); + } + + [Test] + public void PackageVersionWithBetaVersionShouldBeRead() + { + const string noVersion = + @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + Assert.That(packages.First().IsPrerelease, Is.True); + } + + [Test] + public void PackageReferenceWithMetadataShouldBeRead() { const string noVersion = @""; @@ -366,7 +622,41 @@ public void PackageWithMetadataShouldBeRead() } [Test] - public void PackageWithAssetsVersionShouldBeRead() + public void PackageDownloadWithMetadataShouldBeRead() + { + const string noVersion = + @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + Assert.That(packages.First().IsPrerelease, Is.False); + } + + [Test] + public void PackageVersionWithMetadataShouldBeRead() + { + const string noVersion = + @""; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + Assert.That(packages.First().IsPrerelease, Is.False); + } + + [Test] + public void PackageReferenceWithAssetsVersionShouldBeRead() { const string noVersion = @"15.0.26606all"; @@ -382,6 +672,40 @@ public void PackageWithAssetsVersionShouldBeRead() PackageAssert.IsPopulated(packages[0]); } + [Test] + public void PackageDownloadWithAssetsVersionShouldBeRead() + { + const string noVersion = + @"[15.0.26606]all"; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + PackageAssert.IsPopulated(packages[0]); + } + + [Test] + public void PackageVersionWithAssetsVersionShouldBeRead() + { + const string noVersion = + @"15.0.26606all"; + + var projectFile = Vs2017ProjectFileTemplateWithPackages.Replace("{{Packages}}", noVersion, StringComparison.OrdinalIgnoreCase); + + + var reader = MakeReader(); + var packages = reader.Read(StreamFromString(projectFile), _sampleDirectory, _sampleFile) + .ToList(); + + Assert.That(packages.Count, Is.EqualTo(1)); + PackageAssert.IsPopulated(packages[0]); + } + private static ProjectFileReader MakeReader() { return new ProjectFileReader(Substitute.For()); diff --git a/NuKeeper.Inspection/RepositoryInspection/DirectoryBuildTargetsReader.cs b/NuKeeper.Inspection/RepositoryInspection/DirectoryBuildTargetsReader.cs index 3b2b2df18..8c0a52024 100644 --- a/NuKeeper.Inspection/RepositoryInspection/DirectoryBuildTargetsReader.cs +++ b/NuKeeper.Inspection/RepositoryInspection/DirectoryBuildTargetsReader.cs @@ -38,7 +38,7 @@ public IReadOnlyCollection ReadFile(string baseDirectory, stri public IReadOnlyCollection GetFilePatterns() { - return new[] { "Directory.Build.props", "Directory.Build.targets", "Packages.props" }; + return new[] { "Directory.Build.props", "Directory.Packages.props", "Directory.Build.targets", "Packages.props" }; } public IReadOnlyCollection Read(Stream fileContents, PackagePath path) @@ -51,9 +51,13 @@ public IReadOnlyCollection Read(Stream fileContents, PackagePa return Array.Empty(); } - var packageNodeList = packagesNode.Elements("PackageReference"); + var packageRefs = packagesNode.Elements("PackageReference"); + var packageDownloads = packagesNode.Elements("PackageDownload"); + var packageVersions = packagesNode.Elements("PackageVersion"); - return packageNodeList + return packageRefs + .Concat(packageDownloads) + .Concat(packageVersions) .Select(el => XmlToPackage(el, path)) .Where(el => el != null) .ToList(); @@ -66,9 +70,13 @@ private PackageInProject XmlToPackage(XElement el, PackagePath path) { id = el.Attribute("Update")?.Value; } - var version = el.Attribute("Version")?.Value ?? el.Element("Version")?.Value; - + var version = GetVersion(el); return _packageInProjectReader.Read(id, version, path, null); } + + private static string GetVersion(XElement el) + { + return el.Attribute("Version")?.Value ?? el.Element("Version")?.Value; + } } } diff --git a/NuKeeper.Inspection/RepositoryInspection/ProjectFileReader.cs b/NuKeeper.Inspection/RepositoryInspection/ProjectFileReader.cs index 2ee8c22d5..cd88e3fbc 100644 --- a/NuKeeper.Inspection/RepositoryInspection/ProjectFileReader.cs +++ b/NuKeeper.Inspection/RepositoryInspection/ProjectFileReader.cs @@ -55,6 +55,8 @@ public IReadOnlyCollection Read(Stream fileContents, string ba return Array.Empty(); } + var projectFileResults = new List(); + var itemGroups = project .Elements(ns + "ItemGroup") .ToList(); @@ -65,11 +67,27 @@ public IReadOnlyCollection Read(Stream fileContents, string ba .ToList(); var packageRefs = itemGroups.SelectMany(ig => ig.Elements(ns + "PackageReference")); - - return packageRefs + projectFileResults.AddRange( + packageRefs .Select(el => XmlToPackage(ns, el, path, projectRefs)) .Where(el => el != null) - .ToList(); + ); + + projectFileResults.AddRange( + itemGroups + .SelectMany(ig => ig.Elements(ns + "PackageDownload")) + .Select(el => XmlToPackage(ns, el, new PackagePath(baseDirectory, relativePath, PackageReferenceType.DirectoryBuildTargets), null)) + .Where(el => el != null) + ); + + projectFileResults.AddRange( + itemGroups + .SelectMany(ig => ig.Elements(ns + "PackageVersion")) + .Select(el => XmlToPackage(ns, el, new PackagePath(baseDirectory, relativePath, PackageReferenceType.DirectoryBuildTargets), null)) + .Where(el => el != null) + ); + + return projectFileResults; } private static string MakeProjectPath(XElement el, string currentPath) @@ -94,9 +112,13 @@ private PackageInProject XmlToPackage(XNamespace ns, XElement el, PackagePath path, IEnumerable projectReferences) { var id = el.Attribute("Include")?.Value; - var version = el.Attribute("Version")?.Value ?? el.Element(ns + "Version")?.Value; - + var version = GetVersion(el, ns); return _packageInProjectReader.Read(id, version, path, projectReferences); } + + private static string GetVersion(XElement el, XNamespace ns) + { + return el.Attribute("Version")?.Value ?? el.Element(ns + "Version")?.Value; + } } } diff --git a/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageDownloadTests.cs b/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageDownloadTests.cs new file mode 100644 index 000000000..4e49ed741 --- /dev/null +++ b/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageDownloadTests.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using NuGet.Versioning; +using NuKeeper.Abstractions.NuGet; +using NuKeeper.Abstractions.RepositoryInspection; +using NuKeeper.Update.Process; +using NUnit.Framework; + +namespace NuKeeper.Integration.Tests.NuGet.Process +{ + [TestFixture] + public class UpdateDirectoryBuildTargetsCommandPackageDownloadTests : TestWithFailureLogging + { + private readonly string _testFileWithUpdate = + @""; + + private readonly string _testFileWithInclude = + @""; + + [Test] + public async Task ShouldUpdateValidFileWithUpdateAttribute() + { + await ExecuteValidUpdateTest(_testFileWithUpdate, ""); + } + + [Test] + public async Task ShouldUpdateValidFileWithIncludeAttribute() + { + await ExecuteValidUpdateTest(_testFileWithInclude, ""); + } + + [Test] + public async Task ShouldUpdateValidFileWithIncludeAndVerboseVersion() + { + await ExecuteValidUpdateTest( + @"[{packageVersion}]", + @"[{packageVersion}]"); + } + + private async Task ExecuteValidUpdateTest(string testProjectContents, string expectedPackageString, [CallerMemberName] string memberName = "") + { + const string oldPackageVersion = "5.2.31"; + const string newPackageVersion = "5.3.4"; + + var testFolder = memberName; + var testFile = "Directory.Build.props"; + var workDirectory = Path.Combine(TestContext.CurrentContext.WorkDirectory, testFolder); + Directory.CreateDirectory(workDirectory); + var projectContents = testProjectContents.Replace("{packageVersion}", oldPackageVersion, StringComparison.OrdinalIgnoreCase); + var projectPath = Path.Combine(workDirectory, testFile); + await File.WriteAllTextAsync(projectPath, projectContents); + + var command = new UpdateDirectoryBuildTargetsCommand(NukeeperLogger); + + var package = new PackageInProject("foo", oldPackageVersion, + new PackagePath(workDirectory, testFile, PackageReferenceType.DirectoryBuildTargets)); + + await command.Invoke(package, new NuGetVersion(newPackageVersion), null, NuGetSources.GlobalFeed); + + var contents = await File.ReadAllTextAsync(projectPath); + Assert.That(contents, Does.Contain(expectedPackageString.Replace("{packageVersion}", newPackageVersion, StringComparison.OrdinalIgnoreCase))); + Assert.That(contents, Does.Not.Contain(expectedPackageString.Replace("{packageVersion}", oldPackageVersion, StringComparison.OrdinalIgnoreCase))); + } + } +} \ No newline at end of file diff --git a/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandTests.cs b/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageReferenceTests.cs similarity index 96% rename from NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandTests.cs rename to NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageReferenceTests.cs index 9363c4992..e48163093 100644 --- a/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandTests.cs +++ b/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageReferenceTests.cs @@ -11,7 +11,7 @@ namespace NuKeeper.Integration.Tests.NuGet.Process { [TestFixture] - public class UpdateDirectoryBuildTargetsCommandTests : TestWithFailureLogging + public class UpdateDirectoryBuildTargetsCommandPackageReferenceTests : TestWithFailureLogging { private readonly string _testFileWithUpdate = @""; diff --git a/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageVersionTests.cs b/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageVersionTests.cs new file mode 100644 index 000000000..22323fdd1 --- /dev/null +++ b/NuKeeper.Integration.Tests/NuGet/Process/UpdateDirectoryBuildTargetsCommandPackageVersionTests.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using NuGet.Versioning; +using NuKeeper.Abstractions.NuGet; +using NuKeeper.Abstractions.RepositoryInspection; +using NuKeeper.Update.Process; +using NUnit.Framework; + +namespace NuKeeper.Integration.Tests.NuGet.Process +{ + [TestFixture] + public class UpdateDirectoryBuildTargetsCommandPackageVersionTests : TestWithFailureLogging + { + private readonly string _testFileWithUpdate = + @""; + + private readonly string _testFileWithInclude = + @""; + + [Test] + public async Task ShouldUpdateValidFileWithUpdateAttribute() + { + await ExecuteValidUpdateTest(_testFileWithUpdate, ""); + } + + [Test] + public async Task ShouldUpdateValidFileWithIncludeAttribute() + { + await ExecuteValidUpdateTest(_testFileWithInclude, ""); + } + + [Test] + public async Task ShouldUpdateValidFileWithIncludeAndVerboseVersion() + { + await ExecuteValidUpdateTest( + @"{packageVersion}", + @"{packageVersion}"); + } + + private async Task ExecuteValidUpdateTest(string testProjectContents, string expectedPackageString, [CallerMemberName] string memberName = "") + { + const string oldPackageVersion = "5.2.31"; + const string newPackageVersion = "5.3.4"; + + var testFolder = memberName; + var testFile = "Directory.Build.props"; + var workDirectory = Path.Combine(TestContext.CurrentContext.WorkDirectory, testFolder); + Directory.CreateDirectory(workDirectory); + var projectContents = testProjectContents.Replace("{packageVersion}", oldPackageVersion, StringComparison.OrdinalIgnoreCase); + var projectPath = Path.Combine(workDirectory, testFile); + await File.WriteAllTextAsync(projectPath, projectContents); + + var command = new UpdateDirectoryBuildTargetsCommand(NukeeperLogger); + + var package = new PackageInProject("foo", oldPackageVersion, + new PackagePath(workDirectory, testFile, PackageReferenceType.DirectoryBuildTargets)); + + await command.Invoke(package, new NuGetVersion(newPackageVersion), null, NuGetSources.GlobalFeed); + + var contents = await File.ReadAllTextAsync(projectPath); + Assert.That(contents, Does.Contain(expectedPackageString.Replace("{packageVersion}", newPackageVersion, StringComparison.OrdinalIgnoreCase))); + Assert.That(contents, Does.Not.Contain(expectedPackageString.Replace("{packageVersion}", oldPackageVersion, StringComparison.OrdinalIgnoreCase))); + } + } +} \ No newline at end of file diff --git a/NuKeeper.Update/Process/UpdateDirectoryBuildTargetsCommand.cs b/NuKeeper.Update/Process/UpdateDirectoryBuildTargetsCommand.cs index 3f395a6de..6fbf73ff3 100644 --- a/NuKeeper.Update/Process/UpdateDirectoryBuildTargetsCommand.cs +++ b/NuKeeper.Update/Process/UpdateDirectoryBuildTargetsCommand.cs @@ -1,4 +1,6 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -56,27 +58,40 @@ private void UpdateFile(Stream fileContents, NuGetVersion newVersion, return; } - var packageNodeList = packagesNode.Elements("PackageReference") - .Where(x => - (x.Attributes("Include").Any(a => a.Value.Equals(currentPackage.Id, StringComparison.InvariantCultureIgnoreCase)) - || x.Attributes("Update").Any(a => a.Value.Equals(currentPackage.Id,StringComparison.InvariantCultureIgnoreCase)))); + var packageRefs = IncludesOrUpdates(currentPackage, packagesNode.Elements("PackageReference")); + UpdateVersionTo(currentPackage, packageRefs, newVersion.ToString()); + var packageVersions = IncludesOrUpdates(currentPackage, packagesNode.Elements("PackageVersion")); + UpdateVersionTo(currentPackage, packageVersions, newVersion.ToString()); + var packageDownloads = IncludesOrUpdates(currentPackage, packagesNode.Elements("PackageDownload")); + UpdateVersionTo(currentPackage, packageDownloads, $"[{newVersion}]"); - foreach (var dependencyToUpdate in packageNodeList) + xml.Save(fileContents); + } + + private void UpdateVersionTo(PackageInProject currentPackage, IEnumerable elements, string newVersion) + { + foreach (var dependencyToUpdate in elements) { _logger.Detailed( $"Updating directory-level dependencies: {currentPackage.Id} in path {currentPackage.Path.FullName}"); var attribute = dependencyToUpdate.Attribute("Version"); if (attribute != null) { - attribute.Value = newVersion.ToString(); + attribute.Value = newVersion; } else { - dependencyToUpdate.Element("Version").Value = newVersion.ToString(); + dependencyToUpdate.Element("Version").Value = newVersion; } } + } - xml.Save(fileContents); + private static IEnumerable IncludesOrUpdates(PackageInProject currentPackage, IEnumerable elements) + { + return elements.Where(el => + el.Attributes("Include").Any(a => a.Value.Equals(currentPackage.Id, StringComparison.InvariantCultureIgnoreCase)) + || el.Attributes("Update").Any(a => a.Value.Equals(currentPackage.Id, StringComparison.InvariantCultureIgnoreCase)) + ); } } }