From da51b8a4e235bbd552dc77357e921e71ec631848 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Wed, 6 May 2026 16:50:38 -0300 Subject: [PATCH] Support central package version management Allow SmallSharp package directives to work when ManagePackageVersionsCentrally is enabled by omitting Version metadata for centrally managed package references and warning when inline versions are present. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/SmallSharp/EmitTargets.cs | 45 +++++++++++++++++++++++++------ src/SmallSharp/Sdk.targets | 23 ++++++++++++++-- src/SmallSharp/SmallSharp.targets | 13 +++++---- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/SmallSharp/EmitTargets.cs b/src/SmallSharp/EmitTargets.cs index c3b68e1..09e893d 100644 --- a/src/SmallSharp/EmitTargets.cs +++ b/src/SmallSharp/EmitTargets.cs @@ -14,7 +14,7 @@ namespace SmallSharp; public class EmitTargets : Task { static readonly Regex sdkExpr = new(@"^#:sdk\s+(?[^@]+?)(@(?.+))?$"); - static readonly Regex packageExpr = new(@"^#:package\s+(?[^@]+)@(?.+)$"); + static readonly Regex packageExpr = new(@"^#:package\s+(?[^@\s]+)(@(?.+))?$"); static readonly Regex propertyExpr = new(@"^#:property\s+(?[^=]+)=(?.+)$"); [Required] @@ -32,6 +32,8 @@ public class EmitTargets : Task [Required] public required bool UsingSDK { get; set; } + public bool ManagePackageVersionsCentrally { get; set; } + public ITaskItem[] PackageReferences { get; set; } = []; [Output] @@ -62,18 +64,44 @@ public override bool Execute() var properties = new List(); var sdks = new List(); - foreach (var line in contents) + for (var i = 0; i < contents.Length; i++) { + var line = contents[i]; if (packageExpr.Match(line) is { Success: true } match) { var id = match.Groups["id"].Value.Trim(); var version = match.Groups["version"].Value.Trim(); + var hasVersion = !string.IsNullOrEmpty(version); - packages.Add(NewTaskItem(id, [("Version", version)])); + if (ManagePackageVersionsCentrally && hasVersion && !UsingSDK) + { + Log.LogWarning( + null, + "SCS05", + null, + filePath, + i + 1, + 0, + 0, + 0, + "Package reference '{0}' declares version '{1}' via #:package while ManagePackageVersionsCentrally=true; SmallSharp will omit Version metadata and use the central package version.", + id, + version); + } - items.Add(new XElement("PackageReference", - new XAttribute("Include", id), - new XAttribute("Version", version))); + if (!ManagePackageVersionsCentrally && hasVersion) + { + packages.Add(NewTaskItem(id, [("Version", version)])); + items.Add(new XElement("PackageReference", + new XAttribute("Include", id), + new XAttribute("Version", version))); + } + else + { + packages.Add(new TaskItem(id)); + items.Add(new XElement("PackageReference", + new XAttribute("Include", id))); + } } else if (sdkExpr.Match(line) is { Success: true } sdkMatch) { @@ -130,7 +158,7 @@ public override bool Execute() new XElement("PropertyGroup", [new XElement("SmallSharpProjectExtensionPropsImported", "true")]))); - // Determine if a restore is needed: if any discovered #:package (id+version) is not already + // Determine if a restore is needed: if any discovered #:package is not already // present in the incoming PackageReferences list. foreach (var pkg in packages) { @@ -138,7 +166,8 @@ public override bool Execute() var version = pkg.GetMetadata("Version"); var exists = PackageReferences?.Any(r => string.Equals(r.ItemSpec, id, StringComparison.OrdinalIgnoreCase) && - string.Equals(r.GetMetadata("Version"), version, StringComparison.OrdinalIgnoreCase)) == true; + (string.IsNullOrEmpty(version) || + string.Equals(r.GetMetadata("Version"), version, StringComparison.OrdinalIgnoreCase))) == true; if (!exists) { diff --git a/src/SmallSharp/Sdk.targets b/src/SmallSharp/Sdk.targets index a40c2f7..9ffff10 100644 --- a/src/SmallSharp/Sdk.targets +++ b/src/SmallSharp/Sdk.targets @@ -26,11 +26,30 @@ <_PkgReference Include="$([MSBuild]::ValueOrDefault('%(_PkgLines.Identity)', '').Substring(10))" /> - - $([MSBuild]::ValueOrDefault('%(_PkgReference.Identity)', '').Split('@')[1]) + <_PkgReferenceWithVersion Include="@(_PkgReference)" + Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(_PkgReference.Identity)', '@'))"> + $([System.Text.RegularExpressions.Regex]::Replace('%(_PkgReference.Identity)', '@.*$', '')) + $([System.Text.RegularExpressions.Regex]::Replace('%(_PkgReference.Identity)', '^[^@]+@', '')) + + + <_PkgReferenceWithoutVersion Include="@(_PkgReference)" + Condition="!$([System.Text.RegularExpressions.Regex]::IsMatch('%(_PkgReference.Identity)', '@'))" /> + + + + + + + %(_PkgReferenceWithVersion.PackageVersion) + + \ No newline at end of file diff --git a/src/SmallSharp/SmallSharp.targets b/src/SmallSharp/SmallSharp.targets index 63c2a9c..dc3f12a 100644 --- a/src/SmallSharp/SmallSharp.targets +++ b/src/SmallSharp/SmallSharp.targets @@ -51,8 +51,6 @@ - @@ -195,11 +193,12 @@ Inputs="@(Compile);$(ActiveDebugProfile);$(ActiveFile);Properties\launchSettings.json" Outputs="$(SmallSharpPackagesProps);$(SmallSharpPackagesTargets)"> + UsingSDK="$(UsingSmallSharpSDK)" + ManagePackageVersionsCentrally="$([MSBuild]::ValueOrDefault('$(ManagePackageVersionsCentrally)', 'false'))" + PackageReferences="@(PackageReferences)" + PropsFile="$(SmallSharpPackagesProps)" + TargetsFile="$(SmallSharpPackagesTargets)" + BaseIntermediateOutputPath="$(BaseIntermediateOutputPath)">