Skip to content

Commit

Permalink
Merge pull request #71 from nventive/dev/jela/global-json
Browse files Browse the repository at this point in the history
Add support for global.json and `*Version` properties updates
  • Loading branch information
jeromelaban authored Apr 4, 2024
2 parents 211e712 + cddbb6b commit e4fb36c
Show file tree
Hide file tree
Showing 11 changed files with 315 additions and 39 deletions.
12 changes: 12 additions & 0 deletions src/NvGet.Tools.Updater/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 6 additions & 1 deletion src/NvGet/Contracts/FileType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@ public enum FileType
/// </summary>
CentralPackageManagement = 32,

/// <summary>
/// global.json files.
/// </summary>
GlobalJson = 64,

/// <summary>
/// All the supported file types.
/// </summary>
All = Nuspec | Csproj | DirectoryProps | DirectoryTargets | CentralPackageManagement,
All = Nuspec | Csproj | DirectoryProps | DirectoryTargets | CentralPackageManagement | GlobalJson,
}
}
30 changes: 30 additions & 0 deletions src/NvGet/Extensions/DocumentReference.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
23 changes: 9 additions & 14 deletions src/NvGet/Extensions/FileTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
40 changes: 40 additions & 0 deletions src/NvGet/Extensions/JsonDocumentReference.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
44 changes: 40 additions & 4 deletions src/NvGet/Extensions/XmlDocumentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<XmlElement>())
.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();
Expand Down Expand Up @@ -121,21 +150,28 @@ private static PackageIdentity CreatePackageIdentity(string id, string version)
/// <param name="references"></param>
/// <param name="ct"></param>
/// <returns></returns>
public static async Task<Dictionary<string, XmlDocument>> OpenFiles(
public static async Task<Dictionary<string, DocumentReference>> OpenFiles(
this IEnumerable<PackageReference> 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<string, XmlDocument>();
var documents = new Dictionary<string, DocumentReference>();

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;
Expand Down
40 changes: 40 additions & 0 deletions src/NvGet/Extensions/XmlDocumentReference.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
24 changes: 24 additions & 0 deletions src/NvGet/Helpers/GlobalJson.cs
Original file line number Diff line number Diff line change
@@ -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<string, string> MSBuildSdks { get; set; }
}
}
44 changes: 43 additions & 1 deletion src/NvGet/Helpers/SolutionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using NvGet.Extensions;
using NuGet.Versioning;
using Uno.Extensions;
using Newtonsoft.Json;

namespace NvGet.Helpers
{
Expand Down Expand Up @@ -72,6 +73,16 @@ public static async Task<PackageReference[]> 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))
Expand Down Expand Up @@ -129,7 +140,16 @@ private static async Task<string[]> 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))
Expand Down Expand Up @@ -188,5 +208,27 @@ private static async Task<PackageReference[]> GetFileReferences(CancellationToke
.Select(g => new PackageReference(g.Key, new NuGetVersion(g.FirstOrDefault().Version), file, target))
.ToArray();
}

private static async Task<PackageReference[]> GetGlobalJsonFileReferences(CancellationToken ct, string file, FileType target, ICollection<(string PropertyName, string PackageId)> updateProperties)
{
if(file.IsNullOrEmpty())
{
return Array.Empty<PackageReference>();
}

// Parse the global.json file to find all the sdks
var json = await FileHelper.ReadFileContent(ct, file);
var globalJson = JsonConvert.DeserializeObject<GlobalJson>(json);

var references = globalJson
?.MSBuildSdks
?.Select(s => new PackageIdentity(s.Key, new NuGetVersion(s.Value)))
.ToArray() ?? Array.Empty<PackageIdentity>();

return references
.GroupBy(r => r.Id)
.Select(g => new PackageReference(g.Key, new NuGetVersion(g.FirstOrDefault().Version), file, target))
.ToArray();
}
}
}
Loading

0 comments on commit e4fb36c

Please sign in to comment.