Skip to content

Commit

Permalink
Add filters. Deprecate bundles and install options.
Browse files Browse the repository at this point in the history
Updates the spec, the schema, and the code. Includes tests.

Closes KSP-CKAN#113 (deprecate things).
Closes KSP-CKAN#129 (add filter keywords).

This will require an update to CKAN-meta, which I've already got ready.
  • Loading branch information
pjf committed Oct 31, 2014
1 parent e1c3d89 commit e87b949
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 207 deletions.
34 changes: 0 additions & 34 deletions CKAN.schema
Original file line number Diff line number Diff line change
Expand Up @@ -179,40 +179,6 @@
},
"required" : [ "file", "install_to" ]
}
},
"bundles" : {
"description" : "Modules bundled with this mod",
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"file" : {
"description" : "Path to the bundled module",
"type" : "string"
},
"identifier" : {
"description" : "Identifier of the bundled mod",
"$ref" : "#/definitions/identifier"
},
"version" : {
"description" : "Version of bundled module",
"$ref" : "#/definitions/version"
},
"install_to" : {
"description" : "Where bundle should be installed to",
"$ref" : "#/definitions/install_to"
},
"license" : {
"description" : "The license(s) the bundled mod is used under",
"$ref" : "#/definitions/licenses"
},
"required" : {
"description" : "Is this module required for installation?",
"type" : "boolean"
}
},
"required" : [ "file", "identifier", "version", "install_to", "required", "license" ]
}
}
},
"required" : [
Expand Down
1 change: 1 addition & 0 deletions CKAN/CKAN/CKAN.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Compile Include="Registry\InstalledModule.cs" />
<Compile Include="Registry\Registry.cs" />
<Compile Include="Registry\RegistryManager.cs" />
<Compile Include="Types\ModuleInstallDescriptor.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
Expand Down
42 changes: 1 addition & 41 deletions CKAN/CKAN/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,6 @@ public class RelationshipDescriptor
public string version;
}

public abstract class InstallableDescriptor
{
public /* required */ string file;
public /* required */ string install_to;
}

public class BundledModuleDescriptor : InstallableDescriptor
{
public /* required */ string identifier;
public /* required */ string license;
public /* required */ bool required;
public /* required */ string version;
}

public class GitHubResourceDescriptor
{
public bool releases;
Expand All @@ -51,21 +37,6 @@ public class ResourcesDescriptor
public KerbalStuffResourceDescriptor kerbalstuff;
}

// [JsonObject(MemberSerialization.OptIn)]
public class ModuleInstallDescriptor : InstallableDescriptor
{
public string description; // Discouraged, maybe...
public bool optional; // Discouraged GH #113
public bool overwrite; // Discouraged GH #113
public string requires; // Discouraged GH #113

[JsonConverter(typeof (JsonSingleOrArrayConverter<string>))]
public List<string> filter;

[JsonConverter(typeof (JsonSingleOrArrayConverter<string>))]
public List<string> filter_regexp;
}

public enum License
{
public_domain,
Expand Down Expand Up @@ -182,6 +153,7 @@ public class Module
[JsonProperty("name")] public string name;

[JsonProperty("pre_depends")] public RelationshipDescriptor[] pre_depends;

[JsonProperty("provides")] public string[] provides;

[JsonProperty("recommends")] public RelationshipDescriptor[] recommends;
Expand Down Expand Up @@ -272,17 +244,6 @@ public bool IsCompatibleKSP(KSPVersion version)
}
}

public class BundledModule : Module
{
public BundledModule(BundledModuleDescriptor stanza)
{
// For now, we just copy across the fields from our stanza.
version = new Version(stanza.version);
identifier = stanza.identifier;
license = stanza.license;
}
}

public class CkanInvalidMetadataJson : Exception
{
}
Expand All @@ -307,7 +268,6 @@ public class CkanModule : Module
// private static JsonSchema metadata_schema;
// private static string metadata_schema_path = "CKAN.schema";
// private static bool metadata_schema_missing_warning_fired;
[JsonProperty("bundles")] public BundledModuleDescriptor[] bundles;
[JsonProperty("install")] public ModuleInstallDescriptor[] install;
[JsonProperty("spec_version")] public string spec_version;

Expand Down
47 changes: 4 additions & 43 deletions CKAN/CKAN/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,35 +393,6 @@ internal void Install(CkanModule module, string filename = null)
// Register our files.
registry.RegisterModule(new InstalledModule(module_files, module, DateTime.Now));

// Handle bundled mods, if we have them.
// TODO: Deprecate bundles!

if (module.bundles != null)
{
foreach (BundledModuleDescriptor stanza in module.bundles)
{
var bundled = new BundledModule(stanza);

Version ver = registry_manager.registry.InstalledVersion(bundled.identifier);

if (ver != null)
{
User.WriteLine(
"{0} {1} already installed, skipping bundled version {2}",
bundled.identifier, ver, bundled.version
);
continue;
}

// Not installed, so let's get about installing it!
var installed_files = new Dictionary<string, InstalledModuleFile>();

InstallComponent(stanza, filename, installed_files);

registry.RegisterModule(new InstalledModule(installed_files, bundled, DateTime.Now));
}
}

// Done! Save our registry changes!
// This is fine from a transaction standpoint, as we may not have an enclosing
// transaction, and if we do, they can always roll us back.
Expand Down Expand Up @@ -518,7 +489,7 @@ internal static ModuleInstallDescriptor GenerateDefaultInstall(string identifier
/// Modifies the supplied module_files to contain the files installed.
/// This method should be avoided, as it may be removed in the future.
/// </summary>
internal void InstallComponent(InstallableDescriptor stanza, string zip_filename,
internal void InstallComponent(ModuleInstallDescriptor stanza, string zip_filename,
Dictionary<string, InstalledModuleFile> module_files)
{

Expand Down Expand Up @@ -578,7 +549,7 @@ internal void InstallModule(CkanModule module, string zip_filename, Dictionary<s
///
/// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
/// </summary>
internal static List<InstallableFile> FindInstallableFiles(InstallableDescriptor stanza, ZipFile zipfile, KSP ksp)
internal static List<InstallableFile> FindInstallableFiles(ModuleInstallDescriptor stanza, ZipFile zipfile, KSP ksp)
{
string installDir;
bool makeDirs;
Expand Down Expand Up @@ -609,23 +580,13 @@ internal static List<InstallableFile> FindInstallableFiles(InstallableDescriptor
throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
}

// Is there a better way to extract a tree?
string wanted_filter = "^" + stanza.file + "(/|$)";

// O(N^2) solution, as we're walking the zipfile for each stanza.
// Surely there's a better way, although this is fast enough we may not care.

foreach (ZipEntry entry in zipfile)
{
// Skip things we don't want.
if (!Regex.IsMatch(entry.Name, wanted_filter))
{
continue;
}

// SKIP the file if it's a .CKAN file, these should never be copied to GameData.
if (Regex.IsMatch(entry.Name, ".CKAN", RegexOptions.IgnoreCase))
{
// Skips things not prescribed by our install stanza.
if (! stanza.IsWanted(entry.Name)) {
continue;
}

Expand Down
82 changes: 82 additions & 0 deletions CKAN/CKAN/Types/ModuleInstallDescriptor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;

namespace CKAN
{
public class ModuleInstallDescriptor
{
public /* required */ string file;
public /* required */ string install_to;

[JsonConverter(typeof (JsonSingleOrArrayConverter<string>))]
public List<string> filter;

[JsonConverter(typeof (JsonSingleOrArrayConverter<string>))]
public List<string> filter_regexp;

[OnDeserialized]
internal void DeSerialisationFixes(StreamingContext like_i_could_care)
{
// Make sure our required fields exist.
if (file == null || install_to == null)
{
throw new BadMetadataKraken(null, "Install stanzas must have a file and install_to");
}
}

/// <summary>
/// Returns true if the path provided should be installed by this stanza.
/// </summary>
public bool IsWanted(string path)
{
// Make sure our path always uses slashes we expect.
string normalised_path = path.Replace('\\', '/');

// Make sure our internal state is consistent. Is there a better way of doing this?
filter = filter ?? new List<string> ();
filter_regexp = filter_regexp ?? new List<string> ();

// We want everthing that matches our 'file', either as an exact match,
// or as a path leading up to it.
string wanted_filter = "^" + Regex.Escape(this.file) + "(/|$)";

// If it doesn't match our install path, ignore it.
if (! Regex.IsMatch(normalised_path, wanted_filter))
{
return false;
}

// Skip the file if it's a ckan file, these should never be copied to GameData.
if (Regex.IsMatch(normalised_path, ".ckan$", RegexOptions.IgnoreCase))
{
return false;
}

// Get all our path segments. If our filter matches of any them, skip.
// All these comparisons are case insensitive.
var path_segments = new List<string>(normalised_path.ToLower().Split('/'));

foreach (string filter_text in this.filter)
{
if (path_segments.Contains(filter_text.ToLower()))
{
return false;
}
}

// Finally, check our filter regexpes.
foreach (string regexp in this.filter_regexp)
{
if (Regex.IsMatch(normalised_path, regexp))
{
return false;
}
}

// I guess we want this file after all. ;)
return true;
}
}
}
2 changes: 1 addition & 1 deletion CKAN/Tests/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public static string DogeCoinFlag_101()
{
""file"": ""DogeCoinFlag-1.01/GameData/DogeCoinFlag"",
""install_to"": ""GameData"",
""filter"" : [ ""Thumbs.db"", ""INSTALL.md"" ],
""filter"" : [ ""Thumbs.db"", ""README.md"" ],
""filter_regexp"" : ""\\.bak$""
}
],
Expand Down
27 changes: 27 additions & 0 deletions NetKAN/CustomBiomesRSS.ckan
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"spec_version" : 1,
"$kref" : "#/ckan/github/NathanKell/RealSolarSystem",
"name" : "Custom Biomes (Real Solar System data)",
"identifier" : "CustomBiomesRSS",
"abstract" : "Custom biomes for the Real Solar System",
"license" : "CC-BY-NC-SA",
"release_status" : "stable",
"ksp_version" : "any",
"depends" : [
{ "name" : "RealSolarSystem" },
{ "name" : "CustomBiomes" }
],
"provides" : [ "CustomBiomesData" ],
"conflicts" : [ { "name" : "CustomBiomesData" } ],
"resources" : {
"homepage" : "http://forum.kerbalspaceprogram.com/threads/55145",
},
"install" : [
{
"file" : "CustomBiomes",
"install_to" : "GameData",
"comment" : "This regexp only installs PluginData, and nothing else",
"filter_regexp" : "^(?!CustomBiomes/PluginData/)"
}
]
}
13 changes: 13 additions & 0 deletions NetKAN/DeadlyReentry.ckan
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"spec_version" : 1,
"name" : "Deadly Reentry Continued",
"abstract" : "Makes re-entry much more dangerous",
"identifier" : "DeadlyReentry",
"$kref" : "#/ckan/github/NathanKell/DeadlyReentry",
"license" : "CC-BY-SA",
"release_status" : "stable",
"ksp_version" : "0.25",
"resources" : {
"homepage" : "http://forum.kerbalspaceprogram.com/threads/54954",
}
}
13 changes: 2 additions & 11 deletions NetKAN/RealSolarSystem.ckan
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"ksp_version" : "0.25",
"depends" : [
{ "name" : "RSSTextures" },
{ "name" : "ModuleManager", "min_version" : "2.5.0" }
{ "name" : "ModuleManager", "min_version" : "2.5.0" },
],
"recommends" : [
{ "name" : "CustomBiomesRSS" },
{ "name" : "RealismOverhaul" },
{ "name" : "Toolbar" }
],
Expand All @@ -24,14 +25,4 @@
"install_to" : "GameData"
}
],
"bundles" : [
{
"file" : "CustomBiomes",
"identifier" : "CustomBiomes",
"version" : "1.6.6",
"install_to" : "GameData",
"license" : "CC-BY-NC-SA",
"required" : false
}
]
}
Loading

0 comments on commit e87b949

Please sign in to comment.