Skip to content

Commit

Permalink
Handle KSP-AVC krefs
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Aug 26, 2018
1 parent e825bde commit c31e7c4
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 72 deletions.
1 change: 1 addition & 0 deletions Netkan/CKAN-netkan.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<Compile Include="Sources\Spacedock\SpacedockMod.cs" />
<Compile Include="Sources\Spacedock\SpacedockUser.cs" />
<Compile Include="Transformers\AvcTransformer.cs" />
<Compile Include="Transformers\AvcKrefTransformer.cs" />
<Compile Include="Transformers\CurseTransformer.cs" />
<Compile Include="Transformers\DownloadAttributeTransformer.cs" />
<Compile Include="Transformers\EpochTransformer.cs" />
Expand Down
19 changes: 18 additions & 1 deletion Netkan/Sources/Avc/AvcVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ namespace CKAN.NetKAN.Sources.Avc
{
public class AvcVersion
{
// Right now we only support KSP versioning info.
[JsonProperty("NAME")]
public string Name;

[JsonProperty("DOWNLOAD")]
public string Download;

[JsonProperty("GITHUB")]
public AvcVersionGithubRef Github;

[JsonProperty("URL")]
public string Url;
Expand All @@ -21,5 +28,15 @@ public class AvcVersion

[JsonConverter(typeof(JsonAvcToKspVersion))]
public KspVersion ksp_version_max;

}

public class AvcVersionGithubRef
{
[JsonProperty("USERNAME")]
public string Username;

[JsonProperty("REPOSITORY")]
public string Repository;
}
}
59 changes: 59 additions & 0 deletions Netkan/Transformers/AvcKrefTransformer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using CKAN.NetKAN.Extensions;
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Sources.Avc;
using log4net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CKAN.NetKAN.Transformers
{
/// <summary>
/// An <see cref="ITransformer"/> that looks up data from a KSP-AVC URL.
/// </summary>
internal sealed class AvcKrefTransformer : ITransformer
{
private static readonly ILog Log = LogManager.GetLogger(typeof(AvcKrefTransformer));

public string Name { get { return "avc-kref"; } }

public AvcKrefTransformer() { }

public Metadata Transform(Metadata metadata)
{
if (metadata.Kref?.Source == "ksp-avc")
{
var json = metadata.Json();

Log.InfoFormat("Executing KSP-AVC $kref transformation with {0}", metadata.Kref);
Log.DebugFormat("Input metadata:{0}{1}", Environment.NewLine, json);

AvcVersion remoteAvc = JsonConvert.DeserializeObject<AvcVersion>(
Net.DownloadText(new Uri(metadata.Kref.Id))
);

json.SafeAdd("name", remoteAvc.Name);
json.SafeAdd("download", remoteAvc.Download);

// Set .resources.repository based on GITHUB properties
if (remoteAvc.Github?.Username != null && remoteAvc.Github?.Repository != null)
{
// Make sure resources exist.
if (json["resources"] == null)
json["resources"] = new JObject();
var resourcesJson = (JObject)json["resources"];
resourcesJson.SafeAdd("repository", $"https://github.com/{remoteAvc.Github.Username}/{remoteAvc.Github.Repository}");
}

// Use standard KSP-AVC logic to set version and the ksp_version_* properties
AvcTransformer.ApplyVersions(json, remoteAvc);

Log.DebugFormat("Transformed metadata:{0}{1}", Environment.NewLine, json);

return new Metadata(json);
}

return metadata;
}
}
}
148 changes: 77 additions & 71 deletions Netkan/Transformers/AvcTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using CKAN.Versioning;
using log4net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CKAN.NetKAN.Transformers
{
Expand Down Expand Up @@ -83,97 +84,102 @@ public Metadata Transform(Metadata metadata)
}
}

// Get the minimum and maximum KSP versions that already exist in the metadata.
// Use specific KSP version if min/max don't exist.
var existingKspMinStr = (string)json["ksp_version_min"] ?? (string)json["ksp_version"];
var existingKspMaxStr = (string)json["ksp_version_max"] ?? (string)json["ksp_version"];
ApplyVersions(json, avc);

var existingKspMin = existingKspMinStr == null ? null : KspVersion.Parse(existingKspMinStr);
var existingKspMax = existingKspMaxStr == null ? null : KspVersion.Parse(existingKspMaxStr);
// It's cool if we don't have version info at all, it's optional in the AVC spec.

// Get the minimum and maximum KSP versions that are in the AVC file.
// Use specific KSP version if min/max don't exist.
var avcKspMin = avc.ksp_version_min ?? avc.ksp_version;
var avcKspMax = avc.ksp_version_max ?? avc.ksp_version;
Log.DebugFormat("Transformed metadata:{0}{1}", Environment.NewLine, json);
}

// Now calculate the minimum and maximum KSP versions between both the existing metadata and the
// AVC file.
var kspMins = new List<KspVersion>();
var kspMaxes = new List<KspVersion>();
return new Metadata(json);
}
else
{
return metadata;
}
}

if (existingKspMin != null)
kspMins.Add(existingKspMin);
public static void ApplyVersions(JObject json, AvcVersion avc)
{
// Get the minimum and maximum KSP versions that already exist in the metadata.
// Use specific KSP version if min/max don't exist.
var existingKspMinStr = (string)json["ksp_version_min"] ?? (string)json["ksp_version"];
var existingKspMaxStr = (string)json["ksp_version_max"] ?? (string)json["ksp_version"];

if (avcKspMin != null)
kspMins.Add(avcKspMin);
var existingKspMin = existingKspMinStr == null ? null : KspVersion.Parse(existingKspMinStr);
var existingKspMax = existingKspMaxStr == null ? null : KspVersion.Parse(existingKspMaxStr);

if (existingKspMax != null)
kspMaxes.Add(existingKspMax);
// Get the minimum and maximum KSP versions that are in the AVC file.
// Use specific KSP version if min/max don't exist.
var avcKspMin = avc.ksp_version_min ?? avc.ksp_version;
var avcKspMax = avc.ksp_version_max ?? avc.ksp_version;

if (avcKspMax != null)
kspMaxes.Add(avcKspMax);
// Now calculate the minimum and maximum KSP versions between both the existing metadata and the
// AVC file.
var kspMins = new List<KspVersion>();
var kspMaxes = new List<KspVersion>();

var kspMin = kspMins.Any() ? kspMins.Min() : null;
var kspMax = kspMaxes.Any() ? kspMaxes.Max() : null;
if (existingKspMin != null)
kspMins.Add(existingKspMin);

if (kspMin != null || kspMax != null)
{
// If we have either a minimum or maximum KSP version, remove all existing KSP version
// information from the metadata.
json.Remove("ksp_version");
json.Remove("ksp_version_min");
json.Remove("ksp_version_max");
if (avcKspMin != null)
kspMins.Add(avcKspMin);

if (kspMin != null && kspMax != null)
{
// If we have both a minimum and maximum KSP version...
if (kspMin.CompareTo(kspMax) == 0)
{
// ...and they are equal, then just set ksp_version
json["ksp_version"] = kspMin.ToString();
}
else
{
// ...otherwise set both ksp_version_min and ksp_version_max
json["ksp_version_min"] = kspMin.ToString();
json["ksp_version_max"] = kspMax.ToString();
}
}
else
{
// If we have only one or the other then set which ever is applicable
if (existingKspMax != null)
kspMaxes.Add(existingKspMax);

if (kspMin != null)
json["ksp_version_min"] = kspMin.ToString();
if (avcKspMax != null)
kspMaxes.Add(avcKspMax);

if (kspMax != null)
json["ksp_version_max"] = kspMax.ToString();
}
}
var kspMin = kspMins.Any() ? kspMins.Min() : null;
var kspMax = kspMaxes.Any() ? kspMaxes.Max() : null;

if (kspMin != null || kspMax != null)
{
// If we have either a minimum or maximum KSP version, remove all existing KSP version
// information from the metadata.
json.Remove("ksp_version");
json.Remove("ksp_version_min");
json.Remove("ksp_version_max");

if (avc.version != null)
if (kspMin != null && kspMax != null)
{
// If we have both a minimum and maximum KSP version...
if (kspMin.CompareTo(kspMax) == 0)
{
// In practice, the version specified in .version files tends to be unreliable, with authors
// forgetting to update it when new versions are released. Therefore if we have a version
// specified from another source such as SpaceDock, curse or a GitHub tag, don't overwrite it
// unless x_netkan_trust_version_file is true.
if ((bool?)json["x_netkan_trust_version_file"] ?? false)
{
json.Remove("version");
}
json.SafeAdd("version", avc.version.ToString());
// ...and they are equal, then just set ksp_version
json["ksp_version"] = kspMin.ToString();
}
else
{
// ...otherwise set both ksp_version_min and ksp_version_max
json["ksp_version_min"] = kspMin.ToString();
json["ksp_version_max"] = kspMax.ToString();
}
}
else
{
// If we have only one or the other then set which ever is applicable

// It's cool if we don't have version info at all, it's optional in the AVC spec.
if (kspMin != null)
json["ksp_version_min"] = kspMin.ToString();

Log.DebugFormat("Transformed metadata:{0}{1}", Environment.NewLine, json);
if (kspMax != null)
json["ksp_version_max"] = kspMax.ToString();
}

return new Metadata(json);
}
else

if (avc.version != null)
{
return metadata;
// In practice, the version specified in .version files tends to be unreliable, with authors
// forgetting to update it when new versions are released. Therefore if we have a version
// specified from another source such as SpaceDock, curse or a GitHub tag, don't overwrite it
// unless x_netkan_trust_version_file is true.
if ((bool?)json["x_netkan_trust_version_file"] ?? false)
{
json.Remove("version");
}
json.SafeAdd("version", avc.version.ToString());
}
}

Expand Down
1 change: 1 addition & 0 deletions Netkan/Transformers/NetkanTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ bool prerelease
new GithubTransformer(new GithubApi(githubToken), prerelease),
new HttpTransformer(),
new JenkinsTransformer(http),
new AvcKrefTransformer(),
new InternalCkanTransformer(http, moduleService),
new AvcTransformer(http, moduleService),
new VersionEditTransformer(),
Expand Down

0 comments on commit c31e7c4

Please sign in to comment.