Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for global.json and *Version properties updates #71

Merged
merged 4 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
{
Document.Save(ct, path);

Check warning on line 37 in src/NvGet/Extensions/XmlDocumentReference.cs

View workflow job for this annotation

GitHub Actions / Build

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 37 in src/NvGet/Extensions/XmlDocumentReference.cs

View workflow job for this annotation

GitHub Actions / Build

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
jeromelaban marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
50 changes: 49 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 All @@ -25,7 +26,7 @@
string solutionPath,
FileType fileType,
ILogger log,
ICollection<(string PropertyName, string PackageId)>? updateProperties = default

Check warning on line 29 in src/NvGet/Helpers/SolutionHelper.cs

View workflow job for this annotation

GitHub Actions / Build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 29 in src/NvGet/Helpers/SolutionHelper.cs

View workflow job for this annotation

GitHub Actions / Build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
)
{
updateProperties ??= Array.Empty<(string PropertyName, string PackageId)>();
Expand Down Expand Up @@ -72,6 +73,16 @@
}
}

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 @@
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,33 @@
.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();
}
}

public class GlobalJson

Check warning on line 235 in src/NvGet/Helpers/SolutionHelper.cs

View workflow job for this annotation

GitHub Actions / Build

File may only contain a single type
{
[JsonProperty("msbuild-sdks")]
public Dictionary<string, string> MSBuildSdks { get; set; }
}
}
Loading
Loading