Skip to content

Commit

Permalink
Check swinfo deps after multi-host merge
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Sep 2, 2024
1 parent ec33132 commit 9cda6a5
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Netkan/Processors/Inflator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Inflator(string? cacheDir,
IModuleService moduleService = new ModuleService(game);
IFileService fileService = new FileService(cache);
http = new CachingHttpService(cache, overwriteCache);
ckanValidator = new CkanValidator(http, moduleService, game);
ckanValidator = new CkanValidator(http, moduleService, game, githubToken);
transformer = new NetkanTransformer(http, fileService, moduleService,
githubToken, gitlabToken, prerelease, game, netkanValidator);
}
Expand Down
4 changes: 3 additions & 1 deletion Netkan/Services/IModuleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

using CKAN.NetKAN.Sources.Avc;
using CKAN.NetKAN.Sources.SpaceWarp;
using CKAN.NetKAN.Sources.Github;

namespace CKAN.NetKAN.Services
{
Expand All @@ -21,7 +22,8 @@ internal interface IModuleService
IEnumerable<InstallableFile> GetCrafts(CkanModule module, ZipFile zip, GameInstance inst);

SpaceWarpInfo? ParseSpaceWarpJson(string? json);
SpaceWarpInfo? GetSpaceWarpInfo(CkanModule module, ZipFile zip, GameInstance inst, string? internalFilePath = null);
SpaceWarpInfo? GetInternalSpaceWarpInfo(CkanModule module, ZipFile zip, GameInstance inst, string? internalFilePath = null);
SpaceWarpInfo? GetSpaceWarpInfo(CkanModule module, ZipFile zip, GameInstance inst, IGithubApi githubApi, IHttpService httpSvc, string? internalFilePath = null);

IEnumerable<ZipEntry> FileSources(CkanModule module, ZipFile zip, GameInstance inst);
IEnumerable<string> FileDestinations(CkanModule module, string filePath);
Expand Down
33 changes: 28 additions & 5 deletions Netkan/Services/ModuleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using CKAN.NetKAN.Sources.Avc;
using CKAN.NetKAN.Sources.SpaceWarp;
using CKAN.Games;
using CKAN.NetKAN.Sources.Github;

namespace CKAN.NetKAN.Services
{
Expand Down Expand Up @@ -345,17 +346,39 @@ public static void ApplyVersions(JObject json,
public SpaceWarpInfo? ParseSpaceWarpJson(string? json)
=> json == null ? null : JsonConvert.DeserializeObject<SpaceWarpInfo>(json, ignoreJsonErrors);

public SpaceWarpInfo? GetSpaceWarpInfo(CkanModule module,
public SpaceWarpInfo? GetInternalSpaceWarpInfo(CkanModule module,
ZipFile zip,
GameInstance inst,
string? internalFilePath = null)
=> GetInternalSpaceWarpInfos(module, zip, inst, internalFilePath).FirstOrDefault();

private IEnumerable<SpaceWarpInfo> GetInternalSpaceWarpInfos(CkanModule module,
ZipFile zip,
GameInstance inst,
string? internalFilePath = null)
=> (string.IsNullOrWhiteSpace(internalFilePath)
? GetFilesBySuffix(module, zip, SpaceWarpInfoFilename, inst)
: ModuleInstaller.FindInstallableFiles(module, zip, inst)
.Where(instF => instF.source.Name == internalFilePath))
.Where(instF => instF.source.Name == internalFilePath))
.Select(instF => instF.source)
.Select(entry => ParseSpaceWarpJson(
new StreamReader(zip.GetInputStream(entry)).ReadToEnd()))
.FirstOrDefault();
.Select(entry => ParseSpaceWarpJson(new StreamReader(zip.GetInputStream(entry)).ReadToEnd()))
.OfType<SpaceWarpInfo>();

public SpaceWarpInfo? GetSpaceWarpInfo(CkanModule module,
ZipFile zip,
GameInstance inst,
IGithubApi githubApi,
IHttpService httpSvc,
string? internalFilePath = null)
=> GetInternalSpaceWarpInfos(module, zip, inst, internalFilePath)
.Select(swinfo => swinfo.version_check != null
&& Uri.IsWellFormedUriString(swinfo.version_check.OriginalString, UriKind.Absolute)
&& ParseSpaceWarpJson(githubApi?.DownloadText(swinfo.version_check)
?? httpSvc.DownloadText(swinfo.version_check))
is SpaceWarpInfo remoteSwinfo
&& remoteSwinfo.version == swinfo.version
? remoteSwinfo
: swinfo)
.FirstOrDefault();
}
}
23 changes: 1 addition & 22 deletions Netkan/Transformers/SpaceWarpInfoTransformer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;

using ICSharpCode.SharpZipLib.Zip;
using log4net;
Expand Down Expand Up @@ -36,7 +35,7 @@ public IEnumerable<Metadata> Transform(Metadata metadata, TransformOptions? opts
CkanModule mod = CkanModule.FromJson(moduleJson.ToString());
GameInstance inst = new GameInstance(game, "/", "dummy", new NullUser());
ZipFile zip = new ZipFile(httpSvc.DownloadModule(metadata));
var swinfo = modSvc.GetSpaceWarpInfo(mod, zip, inst, metadata.Vref.Id);
var swinfo = modSvc.GetInternalSpaceWarpInfo(mod, zip, inst, metadata.Vref.Id);
if (swinfo != null)
{
log.Info("Found swinfo.json file");
Expand Down Expand Up @@ -83,26 +82,6 @@ public IEnumerable<Metadata> Transform(Metadata metadata, TransformOptions? opts
ModuleService.ApplyVersions(json, null, minVer?.WithoutBuild,
maxVer?.WithoutBuild);
}
var moduleDeps = (mod.depends?.OfType<ModuleRelationshipDescriptor>()
.Select(r => r.name)
?? Enumerable.Empty<string>())
.ToHashSet();
var missingDeps = (swinfo.dependencies
?.Select(dep => dep.id)
.OfType<string>()
.Where(depId => !moduleDeps.Contains(
// Remove up to last period
Identifier.Sanitize(
depId[(depId.LastIndexOf('.') + 1)..], ""),
// Case insensitive
StringComparer.InvariantCultureIgnoreCase))
?? Enumerable.Empty<string>())
.ToList();
if (missingDeps.Any())
{
log.WarnFormat("Dependencies from swinfo.json missing from module: {0}",
string.Join(", ", missingDeps));
}
log.DebugFormat("Transformed metadata:{0}{1}",
Environment.NewLine, json);
yield return new Metadata(json);
Expand Down
9 changes: 6 additions & 3 deletions Netkan/Validators/CkanValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Sources.Github;
using CKAN.Games;

namespace CKAN.NetKAN.Validators
Expand All @@ -10,10 +11,11 @@ internal sealed class CkanValidator : IValidator
{
private readonly List<IValidator> _validators;

public CkanValidator(IHttpService downloader,
public CkanValidator(IHttpService downloader,
IModuleService moduleService,
IGame game)
{
IGame game,
string? githubToken) {
var ghApi = new GithubApi(downloader, githubToken);
_validators = new List<IValidator>
{
new IsCkanModuleValidator(),
Expand All @@ -32,6 +34,7 @@ public CkanValidator(IHttpService downloader,
new ModuleManagerDependsValidator(downloader, moduleService, game),
new PluginsValidator(downloader, moduleService, game),
new CraftsInShipsValidator(downloader, moduleService, game),
new SpaceWarpInfoValidator(downloader, ghApi, moduleService, game),
};
}

Expand Down
67 changes: 67 additions & 0 deletions Netkan/Validators/SpaceWarpInfoValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.Linq;

using ICSharpCode.SharpZipLib.Zip;
using log4net;

using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
using CKAN.Games;
using CKAN.NetKAN.Sources.Github;
using CKAN.NetKAN.Sources.SpaceWarp;

namespace CKAN.NetKAN.Validators
{
internal sealed class SpaceWarpInfoValidator : IValidator
{
public SpaceWarpInfoValidator(IHttpService httpSvc,
IGithubApi githubApi,
IModuleService modSvc,
IGame game)
{
this.httpSvc = httpSvc;
this.githubApi = githubApi;
this.modSvc = modSvc;
this.game = game;
}

public void Validate(Metadata metadata)
{
var moduleJson = metadata.Json();
CkanModule mod = CkanModule.FromJson(moduleJson.ToString());
GameInstance inst = new GameInstance(game, "/", "dummy", new NullUser());
if (httpSvc.DownloadModule(metadata) is string file
&& new ZipFile(file) is ZipFile zip
&& modSvc.GetSpaceWarpInfo(mod, zip, inst, githubApi, httpSvc) is SpaceWarpInfo swinfo)
{
var moduleDeps = (mod.depends?.OfType<ModuleRelationshipDescriptor>()
.Select(r => r.name)
?? Enumerable.Empty<string>())
.ToHashSet();
var missingDeps = (swinfo.dependencies
?.Select(dep => dep.id)
.OfType<string>()
.Where(depId => !moduleDeps.Contains(
// Remove up to last period
Identifier.Sanitize(
depId[(depId.LastIndexOf('.') + 1)..], ""),
// Case insensitive
StringComparer.InvariantCultureIgnoreCase))
?? Enumerable.Empty<string>())
.ToList();
if (missingDeps.Any())
{
log.WarnFormat("Dependencies from swinfo.json missing from module: {0}",
string.Join(", ", missingDeps));
}
}
}

private readonly IHttpService httpSvc;
private readonly IGithubApi githubApi;
private readonly IModuleService modSvc;
private readonly IGame game;

private static readonly ILog log = LogManager.GetLogger(typeof(SpaceWarpInfoValidator));
}
}
2 changes: 1 addition & 1 deletion Netkan/Validators/VrefValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void Validate(Metadata metadata)
GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser());
using (var zipfile = new ZipFile(zipFilePath))
{
bool hasSWInfo = _moduleService.GetSpaceWarpInfo(mod, zipfile, inst) != null;
bool hasSWInfo = _moduleService.GetInternalSpaceWarpInfo(mod, zipfile, inst) != null;
if (hasSWVref && !hasSWInfo)
{
Log.Warn("$vref is space-warp, swinfo.json file missing");
Expand Down
8 changes: 4 additions & 4 deletions Tests/NetKAN/Validators/CkanValidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void DoesNotThrowOnValidCkan()
mModuleService.Setup(i => i.HasInstallableFiles(It.IsAny<CkanModule>(), It.IsAny<string>()))
.Returns(true);

var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram(), null);
var json = (JObject)ValidCkan.DeepClone();

// Act
Expand All @@ -64,7 +64,7 @@ public void DoesThrowWhenMissingProperty(string propertyName)
mModuleService.Setup(i => i.HasInstallableFiles(It.IsAny<CkanModule>(), It.IsAny<string>()))
.Returns(true);

var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram(), null);
var json = (JObject)ValidCkan.DeepClone();
json.Remove(propertyName);

Expand All @@ -87,7 +87,7 @@ public void DoesThrowWhenIdentifiersDoNotMatch()
mModuleService.Setup(i => i.HasInstallableFiles(It.IsAny<CkanModule>(), It.IsAny<string>()))
.Returns(true);

var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram(), null);
var json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AmazingMod";
Expand Down Expand Up @@ -117,7 +117,7 @@ public void DoesThrowWhenNoInstallableFiles()
netkan["spec_version"] = 1;
netkan["identifier"] = "AwesomeMod";

var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram(), null);
var json = (JObject)ValidCkan.DeepClone();

// Act
Expand Down

0 comments on commit 9cda6a5

Please sign in to comment.