Skip to content

Commit

Permalink
[modgen] Vérification des dernières versions de modgen + des générate…
Browse files Browse the repository at this point in the history
…urs au lancement
  • Loading branch information
JabX committed Sep 16, 2024
1 parent 6ff5738 commit 4116b9d
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 26 deletions.
2 changes: 2 additions & 0 deletions TopModel.Generator/ModgenDependency.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ namespace TopModel.Generator;
public record ModgenDependency(string ConfigKey, TopModelLockModule Version)
{
public string FullName => $"TopModel.Generator.{ConfigKey.ToFirstUpper()}";

public string? LatestVersion { get; set; }
}
55 changes: 31 additions & 24 deletions TopModel.Generator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NuGet.Common;
using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using TopModel.Core;
using TopModel.Core.Loaders;
using TopModel.Generator;
Expand Down Expand Up @@ -145,6 +141,16 @@ void HandleFile(FileInfo file)
Console.WriteLine($"========= TopModel.Generator v{version} =========");
Console.WriteLine();

var latestVersion = await NugetUtils.GetLatestVersionAsync("TopModel.Generator");
if (latestVersion != null && latestVersion.Version != version)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"Nouvelle version disponible : {latestVersion.Version}");
Console.WriteLine("Vous pouvez lancer la commande `dotnet tool update -g TopModel.Generator` pour effectuer la mise à jour.");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine();
}

if (excludedTags.Length > 0)
{
Console.Write("Tags");
Expand All @@ -161,6 +167,8 @@ void HandleFile(FileInfo file)
Console.Write(" update ");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine($"activé pour : {updateMode}.");

await NugetUtils.ClearAsync();
}

if (watchMode)
Expand Down Expand Up @@ -317,12 +325,6 @@ void HandleFile(FileInfo file)
continue;
}

var ct = CancellationToken.None;

var nugetCache = new SourceCacheContext();
var nugetRepository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
var nugetResource = await nugetRepository.GetResourceAsync<FindPackageByIdResource>();

var resolvedConfigKeys = new Dictionary<string, string>();

foreach (var configKey in config.Generators.Keys)
Expand All @@ -337,17 +339,15 @@ void HandleFile(FileInfo file)

if (!topModelLock.Modules.TryGetValue(configKey, out var moduleVersion))
{
var moduleVersions = await nugetResource.GetAllVersionsAsync(fullModuleName, nugetCache, NullLogger.Instance, ct);
moduleVersion = await NugetUtils.GetLatestVersionAsync(fullModuleName);

if (!moduleVersions.Any())
if (moduleVersion == null)
{
logger.LogError($"Aucun module de générateurs trouvé pour '{configKey}'.");
returnCode = 1;
continue;
}

var nugetVersion = moduleVersions.Last().Version;
moduleVersion = new() { Version = $"{nugetVersion.Major}.{nugetVersion.Minor}.{nugetVersion.Build}" };
topModelLock.Modules.Add(configKey, moduleVersion);
}

Expand Down Expand Up @@ -390,7 +390,7 @@ void HandleFile(FileInfo file)

logger.LogInformation($"({dep.ConfigKey}) Installation de {dep.FullName}@{depVersion} en cours...");

if (!await nugetResource.DoesPackageExistAsync(dep.FullName, new NuGetVersion(depVersion), nugetCache, NullLogger.Instance, ct))
if (!await NugetUtils.DoesPackageExistsAsync(dep.FullName, depVersion))
{
logger.LogError($"({dep.ConfigKey}) Le package {dep.FullName}@{depVersion} est introuvable.");
returnCode = 1;
Expand All @@ -399,10 +399,8 @@ void HandleFile(FileInfo file)

Directory.CreateDirectory(moduleFolder);

using var packageStream = new MemoryStream();
await nugetResource.CopyNupkgToStreamAsync(dep.FullName, new NuGetVersion(depVersion), packageStream, nugetCache, NullLogger.Instance, ct);
using var packageReader = new PackageArchiveReader(packageStream);
var nuspecReader = await packageReader.GetNuspecReaderAsync(ct);
using var packageReader = await NugetUtils.DownloadPackageAsync(dep.FullName, depVersion);
var nuspecReader = await packageReader.GetNuspecReaderAsync(CancellationToken.None);

var dependencies = nuspecReader.GetDependencyGroups()
.Single(dg => dg.TargetFramework.ToString() == framework)
Expand All @@ -423,18 +421,15 @@ void HandleFile(FileInfo file)
var newDeps = new List<PackageDependency>();
foreach (var otherDep in dependencies)
{
using var packageStreamDep = new MemoryStream();
await nugetResource.CopyNupkgToStreamAsync(otherDep.Id, otherDep.VersionRange.MinVersion, packageStreamDep, nugetCache, NullLogger.Instance, ct);

using var packageReaderDep = new PackageArchiveReader(packageStreamDep);
using var packageReaderDep = await NugetUtils.DownloadPackageAsync(otherDep.Id, otherDep.VersionRange.MinVersion!.ToString());
var file = packageReaderDep.GetFiles().SingleOrDefault(f => f.StartsWith($"lib/{framework}") && f.EndsWith(".dll") && !f.EndsWith(".resources.dll"));
if (file != null)
{
packageReaderDep.ExtractFile(file, Path.Combine(moduleFolder, file.Split('/').Last()), NullLogger.Instance);

installedDependencies.Add(otherDep.Id);

var nuspecReaderDep = await packageReaderDep.GetNuspecReaderAsync(ct);
var nuspecReaderDep = await packageReaderDep.GetNuspecReaderAsync(CancellationToken.None);
if (nuspecReaderDep.GetDependencyGroups().Any())
{
newDeps.AddRange(nuspecReaderDep.GetDependencyGroups()
Expand Down Expand Up @@ -480,8 +475,20 @@ void HandleFile(FileInfo file)

topModelLock.Write();

foreach (var dep in deps)
{
dep.LatestVersion = (await NugetUtils.GetLatestVersionAsync(dep.FullName))?.Version;
}

logger.LogInformation($"Générateurs utilisés :{Environment.NewLine} {string.Join($"{Environment.NewLine} ", resolvedConfigKeys.Select(rck => $"- {rck.Key}: {rck.Value}"))}");

var depsToUpdate = deps.Where(dep => dep.LatestVersion != null && dep.LatestVersion != dep.Version.Version);
if (depsToUpdate.Any())
{
logger.LogWarning($"Il existe une mise à jour pour les générateurs suivants :{Environment.NewLine} {string.Join($"{Environment.NewLine} ", depsToUpdate.Select(dep => $"- {dep.ConfigKey}: {dep.Version.Version} -> {dep.LatestVersion}"))}");
logger.LogWarning($"Vous pouvez lancer la commande `modgen --update {(depsToUpdate.Count() == 1 ? depsToUpdate.Single().ConfigKey : "all")}` pour effectuer la mise à jour.");
}

if (schemaMode || hasInstalled)
{
logger.LogInformation("Génération du schéma de configuration...");
Expand Down
2 changes: 0 additions & 2 deletions TopModel.Generator/TopModel.Generator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="NuGet.Commands" Version="6.11.0" />
<PackageReference Include="NuGet.ProjectModel" Version="6.11.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>

Expand Down
3 changes: 3 additions & 0 deletions TopModel.Utils/ModuleLatestVersion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace TopModel.Utils;

public record ModuleLatestVersion(string Version, DateTime CheckDate);
107 changes: 107 additions & 0 deletions TopModel.Utils/NugetUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System.Text.Json;
using NuGet.Common;
using NuGet.Packaging;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;

namespace TopModel.Utils;

public static class NugetUtils
{
private static readonly string CacheFile = Path.Combine(NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp), "topmodel-cache.json");
private static readonly CancellationToken Ct = CancellationToken.None;
private static readonly SourceCacheContext NugetCache = new();
private static readonly Dictionary<string, ModuleLatestVersion> Versions = [];

private static bool cantCheckVersion;
private static FindPackageByIdResource? nugetResource;

static NugetUtils()
{
if (File.Exists(CacheFile))
{
Versions = JsonSerializer.Deserialize<Dictionary<string, ModuleLatestVersion>>(File.ReadAllText(CacheFile))!;
}
}

public static async Task ClearAsync()
{
Versions.Clear();
await WriteAsync();
}

public static async Task<bool> DoesPackageExistsAsync(string id, string version)
{
var nugetResource = await GetNugetResourceAsync();
return await nugetResource.DoesPackageExistAsync(id, new NuGetVersion(version), NugetCache, NullLogger.Instance, Ct);
}

public static async Task<PackageArchiveReader> DownloadPackageAsync(string id, string version)
{
var nugetResource = await GetNugetResourceAsync();
var packageStream = new MemoryStream();
await nugetResource.CopyNupkgToStreamAsync(id, new NuGetVersion(version), packageStream, NugetCache, NullLogger.Instance, Ct);
return new PackageArchiveReader(packageStream);
}

public static async Task<TopModelLockModule?> GetLatestVersionAsync(string id)
{
if (cantCheckVersion)
{
return null;
}

if (Versions.TryGetValue(id, out var cachedVersion))
{
if (cachedVersion.CheckDate.AddHours(6) < DateTime.UtcNow)
{
Versions.Remove(id);
}
else
{
return new TopModelLockModule { Version = cachedVersion.Version };
}
}

try
{
var nugetResource = await GetNugetResourceAsync();
var moduleVersions = await nugetResource.GetAllVersionsAsync(id, NugetCache, NullLogger.Instance, Ct);

if (!moduleVersions.Any())
{
return null;
}

var nugetVersion = moduleVersions.Last().Version;
var version = new TopModelLockModule { Version = $"{nugetVersion.Major}.{nugetVersion.Minor}.{nugetVersion.Build}" };

Versions[id] = new(version.Version, DateTime.UtcNow);
await WriteAsync();
return version;
}
catch (FatalProtocolException)
{
// Si on a pas internet par exemple.
cantCheckVersion = true;
return null;
}
}

private static async Task<FindPackageByIdResource> GetNugetResourceAsync()
{
if (nugetResource == null)
{
var nugetRepository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
nugetResource = await nugetRepository.GetResourceAsync<FindPackageByIdResource>();
}

return nugetResource;
}

private static async Task WriteAsync()
{
await File.WriteAllTextAsync(CacheFile, JsonSerializer.Serialize(Versions));
}
}
1 change: 1 addition & 0 deletions TopModel.Utils/TopModel.Utils.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageReference Include="NuGet.Commands" Version="6.11.0" />
<PackageReference Include="YamlDotNet" Version="16.0.0" />
</ItemGroup>

Expand Down

0 comments on commit 4116b9d

Please sign in to comment.