diff --git a/src/NvGet.Tools.Updater/Readme.md b/src/NvGet.Tools.Updater/Readme.md
index 6fdbd4f..8ea9ae5 100644
--- a/src/NvGet.Tools.Updater/Readme.md
+++ b/src/NvGet.Tools.Updater/Readme.md
@@ -94,3 +94,15 @@ properties.json example:
]
```
In this case the `UnoVersion` property will be updated to the latest version of `Uno.UI` found in the solution.
+
+## Supported types of updates
+
+The nuget updater supports updating:
+- `.csproj`, `Directory.Build.props`, `Directory.Build.targets` and `Directory.Packages.props`
+ For this type of files, the tool will update:
+ - `PackageReference` and `PackageVersion` items
+ - MSBuild properties using named this way `UnoWinUIVersion` or `UnoExtensionsNavigationVersion`
+- `.nuspec`
+ For this type of files, the tool will update `reference` entries.
+- `global.json`
+ For this type of files, the tool will update `msbuild-sdk` entries
diff --git a/src/NvGet/Contracts/FileType.cs b/src/NvGet/Contracts/FileType.cs
index 3baa575..9cd1db2 100644
--- a/src/NvGet/Contracts/FileType.cs
+++ b/src/NvGet/Contracts/FileType.cs
@@ -38,9 +38,14 @@ public enum FileType
///
CentralPackageManagement = 32,
+ ///
+ /// global.json files.
+ ///
+ GlobalJson = 64,
+
///
/// All the supported file types.
///
- All = Nuspec | Csproj | DirectoryProps | DirectoryTargets | CentralPackageManagement,
+ All = Nuspec | Csproj | DirectoryProps | DirectoryTargets | CentralPackageManagement | GlobalJson,
}
}
diff --git a/src/NvGet/Extensions/DocumentReference.cs b/src/NvGet/Extensions/DocumentReference.cs
new file mode 100644
index 0000000..e276d34
--- /dev/null
+++ b/src/NvGet/Extensions/DocumentReference.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NvGet.Entities;
+using NuGet.Packaging.Core;
+using NuGet.Versioning;
+using Uno.Extensions;
+
+#if WINDOWS_UWP
+using System.Text.RegularExpressions;
+using Windows.Data.Xml.Dom;
+using Windows.Storage;
+using XmlDocument = Windows.Data.Xml.Dom.XmlDocument;
+using XmlElement = Windows.Data.Xml.Dom.XmlElement;
+using XmlNode = Windows.Data.Xml.Dom.IXmlNode;
+#else
+using XmlDocument = System.Xml.XmlDocument;
+using XmlElement = System.Xml.XmlElement;
+using XmlNode = System.Xml.XmlNode;
+#endif
+
+namespace NvGet.Extensions
+{
+ public abstract class DocumentReference
+ {
+ public abstract Task Save(CancellationToken ct, string path);
+ }
+}
diff --git a/src/NvGet/Extensions/FileTypeExtensions.cs b/src/NvGet/Extensions/FileTypeExtensions.cs
index 3265022..95c39dc 100644
--- a/src/NvGet/Extensions/FileTypeExtensions.cs
+++ b/src/NvGet/Extensions/FileTypeExtensions.cs
@@ -8,21 +8,16 @@ public static class FileTypeExtensions
{
public static string GetDescription(this FileType target)
{
- switch(target)
+ return target switch
{
- case FileType.Nuspec:
- return ".nuspec";
- case FileType.Csproj:
- return ".csproj";
- case FileType.DirectoryProps:
- return "Directory.Build.targets";
- case FileType.DirectoryTargets:
- return "Directory.Build.props";
- case FileType.CentralPackageManagement:
- return "Directory.Packages.props";
- default:
- return default;
- }
+ FileType.Nuspec => ".nuspec",
+ FileType.Csproj => ".csproj",
+ FileType.DirectoryProps => "Directory.Build.targets",
+ FileType.DirectoryTargets => "Directory.Build.props",
+ FileType.CentralPackageManagement => "Directory.Packages.props",
+ FileType.GlobalJson => "global.json",
+ _ => default,
+ };
}
public static bool HasAnyFlag(this FileType target, params FileType[] others)
diff --git a/src/NvGet/Extensions/JsonDocumentReference.cs b/src/NvGet/Extensions/JsonDocumentReference.cs
new file mode 100644
index 0000000..4b3c6c8
--- /dev/null
+++ b/src/NvGet/Extensions/JsonDocumentReference.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NvGet.Entities;
+using NuGet.Packaging.Core;
+using NuGet.Versioning;
+using Uno.Extensions;
+
+#if WINDOWS_UWP
+using System.Text.RegularExpressions;
+using Windows.Data.Xml.Dom;
+using Windows.Storage;
+using XmlDocument = Windows.Data.Xml.Dom.XmlDocument;
+using XmlElement = Windows.Data.Xml.Dom.XmlElement;
+using XmlNode = Windows.Data.Xml.Dom.IXmlNode;
+#else
+using XmlDocument = System.Xml.XmlDocument;
+using XmlElement = System.Xml.XmlElement;
+using XmlNode = System.Xml.XmlNode;
+#endif
+
+namespace NvGet.Extensions
+{
+ public class JsonDocumentReference : DocumentReference
+ {
+ public JsonDocumentReference(string contents)
+ {
+ Contents = contents;
+ }
+
+ public string Contents { get; set; }
+
+ public override async Task Save(CancellationToken ct, string path)
+ {
+ System.IO.File.WriteAllText(path, Contents);
+ }
+ }
+}
diff --git a/src/NvGet/Extensions/XmlDocumentExtensions.cs b/src/NvGet/Extensions/XmlDocumentExtensions.cs
index 98e323d..d122b02 100644
--- a/src/NvGet/Extensions/XmlDocumentExtensions.cs
+++ b/src/NvGet/Extensions/XmlDocumentExtensions.cs
@@ -88,6 +88,35 @@ public static PackageIdentity[] GetPackageReferences(this XmlDocument document)
}
}
+ // find all nodes inside a PropertyGroup node that for which the name is ending by Version
+ var propertyGroupVersionReferences = document
+ .SelectElements("PropertyGroup")
+ .SelectMany(pg => pg.SelectNodes("*").OfType())
+ .Where(e => e.LocalName.EndsWith("Version", StringComparison.OrdinalIgnoreCase));
+
+ foreach(var versionProperty in propertyGroupVersionReferences)
+ {
+ var originalTrimmedName = versionProperty
+ .LocalName
+ .TrimEnd("Version");
+
+ var nameParts =
+ originalTrimmedName
+ .Select((c, i) =>
+ i > 0
+ && char.IsUpper(c)
+ && !char.IsUpper(originalTrimmedName[i - 1])
+ ? "." + c
+ : c.ToString());
+
+ var packageName = string.Concat(nameParts).ToLowerInvariant();
+
+ if(NuGetVersion.TryParse(versionProperty.InnerText, out var nugetVersion))
+ {
+ references.Add(CreatePackageIdentity(packageName, versionProperty.InnerText));
+ }
+ }
+
return references
.Trim()
.ToArray();
@@ -121,21 +150,28 @@ private static PackageIdentity CreatePackageIdentity(string id, string version)
///
///
///
- public static async Task> OpenFiles(
+ public static async Task> OpenFiles(
this IEnumerable references,
CancellationToken ct
)
{
var files = references
.SelectMany(r => r.Files)
- .SelectMany(g => g.Value)
+ .SelectMany(g => g.Value.Select(file => (fileType: g.Key, file: file)))
.Distinct();
- var documents = new Dictionary();
+ var documents = new Dictionary();
foreach(var file in files)
{
- documents.Add(file, await file.LoadDocument(ct));
+ if(file.fileType == Contracts.FileType.GlobalJson)
+ {
+ documents.Add(file.file, new JsonDocumentReference(System.IO.File.ReadAllText(file.file)));
+ }
+ else
+ {
+ documents.Add(file.file, new XmlDocumentReference(await file.file.LoadDocument(ct)));
+ }
}
return documents;
diff --git a/src/NvGet/Extensions/XmlDocumentReference.cs b/src/NvGet/Extensions/XmlDocumentReference.cs
new file mode 100644
index 0000000..937e477
--- /dev/null
+++ b/src/NvGet/Extensions/XmlDocumentReference.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NvGet.Entities;
+using NuGet.Packaging.Core;
+using NuGet.Versioning;
+using Uno.Extensions;
+
+#if WINDOWS_UWP
+using System.Text.RegularExpressions;
+using Windows.Data.Xml.Dom;
+using Windows.Storage;
+using XmlDocument = Windows.Data.Xml.Dom.XmlDocument;
+using XmlElement = Windows.Data.Xml.Dom.XmlElement;
+using XmlNode = Windows.Data.Xml.Dom.IXmlNode;
+#else
+using XmlDocument = System.Xml.XmlDocument;
+using XmlElement = System.Xml.XmlElement;
+using XmlNode = System.Xml.XmlNode;
+#endif
+
+namespace NvGet.Extensions
+{
+ public class XmlDocumentReference : DocumentReference
+ {
+ public XmlDocumentReference(XmlDocument document)
+ {
+ Document = document;
+ }
+
+ public XmlDocument Document { get; }
+
+ public override async Task Save(CancellationToken ct, string path)
+ {
+ await Document.Save(ct, path);
+ }
+ }
+}
diff --git a/src/NvGet/Helpers/GlobalJson.cs b/src/NvGet/Helpers/GlobalJson.cs
new file mode 100644
index 0000000..81a0226
--- /dev/null
+++ b/src/NvGet/Helpers/GlobalJson.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Common;
+using NuGet.Packaging.Core;
+using NvGet.Contracts;
+using NvGet.Entities;
+using NvGet.Extensions;
+using NuGet.Versioning;
+using Uno.Extensions;
+using Newtonsoft.Json;
+
+namespace NvGet.Helpers
+{
+ public class GlobalJson
+ {
+ [JsonProperty("msbuild-sdks")]
+ public Dictionary MSBuildSdks { get; set; }
+ }
+}
diff --git a/src/NvGet/Helpers/SolutionHelper.cs b/src/NvGet/Helpers/SolutionHelper.cs
index 23054db..a3d3244 100644
--- a/src/NvGet/Helpers/SolutionHelper.cs
+++ b/src/NvGet/Helpers/SolutionHelper.cs
@@ -12,6 +12,7 @@
using NvGet.Extensions;
using NuGet.Versioning;
using Uno.Extensions;
+using Newtonsoft.Json;
namespace NvGet.Helpers
{
@@ -72,6 +73,16 @@ public static async Task GetPackageReferences(
}
}
+ if(fileType.HasFlag(FileType.GlobalJson))
+ {
+ const FileType currentTarget = FileType.GlobalJson;
+
+ foreach(var file in await GetDirectoryFiles(ct, solutionPath, currentTarget, log))
+ {
+ packages.AddRange(await GetGlobalJsonFileReferences(ct, file, currentTarget, updateProperties));
+ }
+ }
+
if(fileType.HasFlag(FileType.Nuspec))
{
foreach(var f in await GetNuspecFiles(ct, solutionPath, log))
@@ -129,7 +140,16 @@ private static async Task GetDirectoryFiles(CancellationToken ct, stri
else
{
var solutionFolder = Path.GetDirectoryName(solutionPath);
- file = Path.Combine(solutionFolder, target.GetDescription());
+
+ if(target is FileType.DirectoryProps or FileType.DirectoryTargets or FileType.GlobalJson or FileType.CentralPackageManagement)
+ {
+ var matchingFiles = await FileHelper.GetFiles(ct, solutionFolder, nameFilter: target.GetDescription());
+ return matchingFiles.ToArray();
+ }
+ else
+ {
+ file = Path.Combine(solutionFolder, target.GetDescription());
+ }
}
if(file.HasValue() && await FileHelper.Exists(file))
@@ -188,5 +208,27 @@ private static async Task GetFileReferences(CancellationToke
.Select(g => new PackageReference(g.Key, new NuGetVersion(g.FirstOrDefault().Version), file, target))
.ToArray();
}
+
+ private static async Task GetGlobalJsonFileReferences(CancellationToken ct, string file, FileType target, ICollection<(string PropertyName, string PackageId)> updateProperties)
+ {
+ if(file.IsNullOrEmpty())
+ {
+ return Array.Empty();
+ }
+
+ // Parse the global.json file to find all the sdks
+ var json = await FileHelper.ReadFileContent(ct, file);
+ var globalJson = JsonConvert.DeserializeObject(json);
+
+ var references = globalJson
+ ?.MSBuildSdks
+ ?.Select(s => new PackageIdentity(s.Key, new NuGetVersion(s.Value)))
+ .ToArray() ?? Array.Empty();
+
+ return references
+ .GroupBy(r => r.Id)
+ .Select(g => new PackageReference(g.Key, new NuGetVersion(g.FirstOrDefault().Version), file, target))
+ .ToArray();
+ }
}
}
diff --git a/src/NvGet/Tools/Updater/Extensions/XmlDocumentExtensions.cs b/src/NvGet/Tools/Updater/Extensions/XmlDocumentExtensions.cs
index 67e5d05..d2a0c65 100644
--- a/src/NvGet/Tools/Updater/Extensions/XmlDocumentExtensions.cs
+++ b/src/NvGet/Tools/Updater/Extensions/XmlDocumentExtensions.cs
@@ -1,7 +1,11 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Xml;
+using Newtonsoft.Json;
+using NuGet.Versioning;
using NvGet.Extensions;
+using NvGet.Helpers;
using NvGet.Tools.Updater.Log;
using Uno.Extensions;
@@ -92,6 +96,23 @@ UpdateOperation operation
}
}
+ var propertyGroupVersionReferences = document
+ .SelectElements("PropertyGroup")
+ .SelectMany(pg => pg.SelectNodes(packageId.Replace(".", "") + "Version").OfType());
+
+ foreach(var versionProperty in propertyGroupVersionReferences)
+ {
+ if(NuGetVersion.TryParse(versionProperty.InnerText, out var previousVersion))
+ {
+ var currentOperation = operation.WithPreviousVersion(versionProperty.InnerText);
+
+ if(currentOperation.ShouldProceed())
+ {
+ versionProperty.InnerText = currentOperation.UpdatedVersion.ToString();
+ }
+ }
+ }
+
return operations;
}
@@ -139,31 +160,57 @@ private static void SetAttributeOrChild(this XmlElement element, string name, st
///
///
public static IEnumerable UpdateDependencies(
- this XmlDocument document,
+ this DocumentReference document,
UpdateOperation operation
)
{
- var operations = new List();
-
- foreach(var node in document.SelectElements("dependency", $"[@id='{operation.PackageId}']"))
+ if(document is XmlDocumentReference xmlDocReference)
{
- var versionNodeValue = node.GetAttribute("version");
+ var operations = new List();
- // only nodes with explicit version, skip expansion.
- if(!versionNodeValue.Contains("{", System.StringComparison.OrdinalIgnoreCase))
+ foreach(var node in xmlDocReference.Document.SelectElements("dependency", $"[@id='{operation.PackageId}']"))
{
- var currentOperation = operation.WithPreviousVersion(versionNodeValue);
+ var versionNodeValue = node.GetAttribute("version");
- if(currentOperation.ShouldProceed())
+ // only nodes with explicit version, skip expansion.
+ if(!versionNodeValue.Contains("{", System.StringComparison.OrdinalIgnoreCase))
{
- node.SetAttribute("version", currentOperation.UpdatedVersion.ToString());
+ var currentOperation = operation.WithPreviousVersion(versionNodeValue);
+
+ if(currentOperation.ShouldProceed())
+ {
+ node.SetAttribute("version", currentOperation.UpdatedVersion.ToString());
+ }
+
+ operations.Add(currentOperation);
}
+ }
+
+ return operations;
+ }
+ else if(document is JsonDocumentReference jsonDocReference)
+ {
+ var operations = new List();
+
+ var globalJson = JsonConvert.DeserializeObject(jsonDocReference.Contents);
+
+ if(globalJson.MSBuildSdks.TryGetValue(operation.PackageId, out var value))
+ {
+ globalJson.MSBuildSdks[operation.PackageId] = operation.UpdatedVersion.ToString();
+
+ var currentOperation = operation.WithPreviousVersion(value);
operations.Add(currentOperation);
}
- }
- return operations;
+ jsonDocReference.Contents = JsonConvert.SerializeObject(globalJson);
+
+ return operations;
+ }
+ else
+ {
+ throw new NotSupportedException();
+ }
}
}
}
diff --git a/src/NvGet/Tools/Updater/NuGetUpdater.cs b/src/NvGet/Tools/Updater/NuGetUpdater.cs
index 0cc21e1..0d1e71b 100644
--- a/src/NvGet/Tools/Updater/NuGetUpdater.cs
+++ b/src/NvGet/Tools/Updater/NuGetUpdater.cs
@@ -144,7 +144,7 @@ private async Task UpdateFiles(
CancellationToken ct,
UpdateOperation operation,
Dictionary targetFiles,
- Dictionary documents
+ Dictionary documents
)
{
var operations = new List();
@@ -166,14 +166,19 @@ Dictionary documents
var currentOperation = operation.WithFilePath(path);
- if(fileType.HasFlag(FileType.Nuspec))
+ if(fileType.HasFlag(FileType.Nuspec) && document is XmlDocumentReference xmlDocReference)
{
- updates = document.UpdateDependencies(currentOperation);
+ updates = xmlDocReference.UpdateDependencies(currentOperation);
}
- else if(fileType.HasAnyFlag(FileType.DirectoryProps, FileType.DirectoryTargets, FileType.Csproj, FileType.CentralPackageManagement))
+ else if(fileType.HasFlag(FileType.GlobalJson) && document is JsonDocumentReference jsonDocReference)
{
- updates = document.UpdatePackageReferences(currentOperation);
- var propertyUpdates = document.UpdateUpdateProperties(currentOperation, _parameters.UpdateProperties);
+ updates = jsonDocReference.UpdateDependencies(currentOperation);
+ }
+ else if(fileType.HasAnyFlag(FileType.DirectoryProps, FileType.DirectoryTargets, FileType.Csproj, FileType.CentralPackageManagement)
+ && document is XmlDocumentReference xmlDocReference2)
+ {
+ updates = xmlDocReference2.Document.UpdatePackageReferences(currentOperation);
+ var propertyUpdates = xmlDocReference2.Document.UpdateUpdateProperties(currentOperation, _parameters.UpdateProperties);
updates = updates.Concat(propertyUpdates);
}