diff --git a/src/NuGetizer.Tasks/CreatePackage.cs b/src/NuGetizer.Tasks/CreatePackage.cs index b587b697..f81ed0e9 100644 --- a/src/NuGetizer.Tasks/CreatePackage.cs +++ b/src/NuGetizer.Tasks/CreatePackage.cs @@ -51,6 +51,8 @@ public override bool Execute() OutputPackage = new TaskItem(TargetPath); Manifest.CopyMetadataTo(OutputPackage); + if (emitSpec) + OutputPackage.SetMetadata("Nuspec", NuspecFile); return !Log.HasLoggedErrors; } diff --git a/src/NuGetizer.Tasks/NuGetizer.Shared.targets b/src/NuGetizer.Tasks/NuGetizer.Shared.targets index 427bd3e6..e3a7f8f8 100644 --- a/src/NuGetizer.Tasks/NuGetizer.Shared.targets +++ b/src/NuGetizer.Tasks/NuGetizer.Shared.targets @@ -237,7 +237,10 @@ Copyright (c) .NET Foundation. All rights reserved. - + + + diff --git a/src/NuGetizer.Tasks/dotnet-nugetize.targets b/src/NuGetizer.Tasks/dotnet-nugetize.targets index 9cc79f80..a4783f8f 100644 --- a/src/NuGetizer.Tasks/dotnet-nugetize.targets +++ b/src/NuGetizer.Tasks/dotnet-nugetize.targets @@ -14,13 +14,11 @@ Copyright (c) .NET Foundation. All rights reserved. - - <_AbsoluteNuspecFile Condition="$([System.IO.Path]::IsPathRooted($(NuspecFile)))">$(NuspecFile) - <_AbsoluteNuspecFile Condition="'$(_NuspecFile)' == ''">$(MSBuildProjectDirectory.TrimEnd('\'))\$(NuspecFile) - <_AbsoluteNuspecFile>$([System.IO.Path]::GetFullPath('$(_AbsoluteNuspecFile)')) - - + + + + diff --git a/src/NuGetizer.Tests/Builder.NuGetizer.cs b/src/NuGetizer.Tests/Builder.NuGetizer.cs index 172388b8..b4ff5abe 100644 --- a/src/NuGetizer.Tests/Builder.NuGetizer.cs +++ b/src/NuGetizer.Tests/Builder.NuGetizer.cs @@ -25,7 +25,8 @@ public static TargetResult BuildProject( string projectContent = null, string target = "GetPackageContents", ITestOutputHelper output = null, - LoggerVerbosity? verbosity = null) + LoggerVerbosity? verbosity = null, + params (string name, string contents)[] files) { using var sha = new SHA1Managed(); var hash = Base62.Encode(Math.Abs(BitConverter.ToInt64( @@ -40,6 +41,11 @@ public static TargetResult BuildProject( doc.Save(Path.Combine(scenarioDir, "library.csproj")); + foreach (var file in files) + { + File.WriteAllText(Path.Combine(scenarioDir, file.name), file.contents); + } + var openLog = OpenBuildLogAttribute.IsActive; try { diff --git a/src/NuGetizer.Tests/given_packinference.cs b/src/NuGetizer.Tests/given_packinference.cs new file mode 100644 index 00000000..52efdfe6 --- /dev/null +++ b/src/NuGetizer.Tests/given_packinference.cs @@ -0,0 +1,253 @@ +using System.Linq; +using System.Xml.Linq; +using Xunit; +using Xunit.Abstractions; + +namespace NuGetizer +{ + public class given_packinference + { + ITestOutputHelper output; + + public given_packinference(ITestOutputHelper output) => this.output = output; + + [Fact] + public void when_none_has_PackagePath_then_packs() + { + var result = Builder.BuildProject(@" + + + Library + netstandard2.0 + + + + +", + "GetPackageContents", output); + + result.AssertSuccess(output); + Assert.Contains(result.Items, item => item.Matches(new + { + PackagePath = @"build\netstandard2.0\Library.props", + })); + } + + [Fact] + public void when_none_has_Kind_then_packs() + { + var result = Builder.BuildProject(@" + + + Library + netstandard2.0 + + + + +", + "GetPackageContents", output); + + result.AssertSuccess(output); + Assert.Contains(result.Items, item => item.Matches(new + { + Filename = "Library", + Extension = ".props", + })); + } + + [Fact] + public void when_none_has_Kind_FrameworkSpecific_then_packs() + { + var result = Builder.BuildProject(@" + + + Library + netstandard2.0 + + + + +", + "GetPackageContents", output); + + result.AssertSuccess(output); + Assert.Contains(result.Items, item => item.Matches(new + { + PackagePath = @"build\netstandard2.0\Library.props", + })); + } + + [Fact] + public void when_PackContent_false_but_content_has_PackagePath_then_packs() + { + var result = Builder.BuildProject(@" + + + Library + netstandard2.0 + false + + + + +", + "GetPackageContents", output); + + result.AssertSuccess(output); + Assert.Contains(result.Items, item => item.Matches(new + { + PackagePath = @"build\netstandard2.0\Library.props", + })); + } + + [Fact] + public void when_PackContent_false_but_content_has_Pack_then_packs() + { + var result = Builder.BuildProject(@" + + + Library + netstandard2.0 + false + + + + +", + "GetPackageContents", output); + + result.AssertSuccess(output); + Assert.Contains(result.Items, item => item.Matches(new + { + Filename = "Library", + Extension = ".props", + })); + } + + [Fact] + public void when_PackContent_false_but_content_has_Kind_then_packs() + { + var result = Builder.BuildProject(@" + + + Library + netstandard2.0 + false + + + + +", + "GetPackageContents", output); + + result.AssertSuccess(output); + Assert.Contains(result.Items, item => item.Matches(new + { + Filename = "Library", + Extension = ".props", + })); + } + + [Fact] + public void when_content_has_buildaction_then_spec_has_attribute() + { + var result = Builder.BuildProject(@" + + + Library + true + false + netstandard2.0 + + + + +", + "Pack", output); + + result.AssertSuccess(output); + + Assert.Single(result.Items); + Assert.NotEmpty(result.Items[0].GetMetadata("Nuspec")); + + var nuspec = XDocument.Load(result.Items[0].GetMetadata("Nuspec")); + + // Nuspec should contain: + // + Assert.Equal("None", nuspec + .Descendants("{http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd}files") + .Select(x => x.Attribute("buildAction")?.Value) + .FirstOrDefault()); + } + + [Fact] + public void when_content_has_copytooutput_then_spec_has_attribute() + { + var result = Builder.BuildProject(@" + + + Library + true + false + netstandard2.0 + + + + +", + "Pack", output); + + result.AssertSuccess(output); + + Assert.Single(result.Items); + Assert.NotEmpty(result.Items[0].GetMetadata("Nuspec")); + + var nuspec = XDocument.Load(result.Items[0].GetMetadata("Nuspec")); + + // Nuspec should contain: + // + Assert.Equal("true", nuspec + .Descendants("{http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd}files") + .Select(x => x.Attribute("copyToOutput")?.Value) + .FirstOrDefault()); + } + + [Fact] + public void when_content_has_copytooutput_flatten_then_spec_has_attributes() + { + var result = Builder.BuildProject(@" + + + Library + true + false + netstandard2.0 + + + + +", + "Pack", output); + + result.AssertSuccess(output); + + Assert.Single(result.Items); + Assert.NotEmpty(result.Items[0].GetMetadata("Nuspec")); + + var nuspec = XDocument.Load(result.Items[0].GetMetadata("Nuspec")); + + // Nuspec should contain: + // + Assert.Equal("true", nuspec + .Descendants("{http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd}files") + .Select(x => x.Attribute("copyToOutput")?.Value) + .FirstOrDefault()); + + Assert.Equal("true", nuspec + .Descendants("{http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd}files") + .Select(x => x.Attribute("flatten")?.Value) + .FirstOrDefault()); + } + } +} diff --git a/src/dotnet-nugetize/Program.cs b/src/dotnet-nugetize/Program.cs index 90d1dd7b..dcc098a9 100644 --- a/src/dotnet-nugetize/Program.cs +++ b/src/dotnet-nugetize/Program.cs @@ -53,7 +53,7 @@ static int Execute(bool binlog, bool debug) var foundPackage = false; foreach (var metadata in items.Root.Descendants("PackageMetadata") - .Distinct(AnonymousEqualityComparer.Create( + .Distinct(AnonymousComparer.Create( (x, y) => x.Element("PackageId")?.Value == y.Element("PackageId")?.Value, x => x.Element("PackageId")?.Value.GetHashCode() ?? 0))) { @@ -102,12 +102,12 @@ static int Execute(bool binlog, bool debug) .Where(x => x.Element("PackagePath") != null && x.Element("PackageId")?.Value == packageId) - .Select(x => x.Element("PackagePath").Value) - .Distinct() - .OrderBy(x => Path.GetDirectoryName(x)) - .ThenBy(x => x); + //.Select(x => x.Element("PackagePath").Value) + .Distinct(AnonymousComparer.Create(x => x.Element("PackagePath").Value)) + .OrderBy(x => Path.GetDirectoryName(x.Element("PackagePath").Value)) + .ThenBy(x => x.Element("PackagePath").Value); - RenderContents(contents.ToList(), 0, 0, ""); + Render(contents.ToList(), 0, 0, ""); Console.WriteLine(); } @@ -123,12 +123,12 @@ static int Execute(bool binlog, bool debug) return 0; } - static int RenderContents(IList files, int index, int level, string path) + static int Render(IList files, int index, int level, string path) { while (index < files.Count) - { - var file = files[index]; + var element = files[index]; + var file = element.Element("PackagePath").Value; var dir = Path.GetDirectoryName(file); var paths = dir.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); @@ -143,7 +143,7 @@ static int RenderContents(IList files, int index, int level, string path ColorConsole.Write("/".Gray()); ColorConsole.WriteLine(paths[level].Green(), "/".Gray()); - index = RenderContents(files, index, level + 1, string.Join(Path.DirectorySeparatorChar, paths[..(level + 1)])); + index = Render(files, index, level + 1, string.Join(Path.DirectorySeparatorChar, paths[..(level + 1)])); } else { @@ -151,7 +151,20 @@ static int RenderContents(IList files, int index, int level, string path if (level == 0) ColorConsole.Write("/".Gray()); - ColorConsole.WriteLine(Path.GetFileName(file).White()); + var attributes = new List(); + if (element.Element("BuildAction")?.Value is string buildAction) + attributes.Add("buildAction=" + buildAction); + if (element.Element("CopyToOutput")?.Value is string copyToOutput) + attributes.Add("copyToOutput=" + copyToOutput); + if (element.Element("Flatten")?.Value is string flatten) + attributes.Add("flatten=" + flatten); + + ColorConsole.Write(Path.GetFileName(file).White()); + if (attributes.Count > 0) + ColorConsole.Write((" (" + string.Join(',', attributes) + ")").Gray()); + + Console.WriteLine(); + index++; } } @@ -183,10 +196,13 @@ static bool Execute(string program, string arguments, bool debug = false) return proc.ExitCode == 0; } - static class AnonymousEqualityComparer + static class AnonymousComparer { public static IEqualityComparer Create(Func equals, Func getHashCode) => new AnonymousEqualityComparer(equals, getHashCode); + + public static IEqualityComparer Create(Func value) + => new AnonymousEqualityComparer((x, y) => Equals(value(x), value(y)), x => value(x).GetHashCode()); } class AnonymousEqualityComparer : IEqualityComparer