diff --git a/CKAN.schema b/CKAN.schema index fb1e16a93b..ae171af6bb 100644 --- a/CKAN.schema +++ b/CKAN.schema @@ -152,6 +152,14 @@ "description" : "Where file should be installed to", "$ref" : "#/definitions/install_to" }, + "filter" : { + "description" : "List of files and directories that should be filtered from the install", + "$ref" : "#/definitions/one_or_more_strings" + }, + "filter_regexp" : { + "description" : "List of regexps that should filter files from this install", + "$ref" : "#/definitions/one_or_more_strings" + }, "requires" : { "description" : "A required mod for this install part", "$ref" : "#/definitions/identifier" @@ -303,6 +311,17 @@ "uniqueItems" : true } ] + }, + "one_or_more_strings" : { + "description" : "One or more strings", + "oneOf" : [ + { "type" : "string" }, + { + "type" : "array", + "items" : { "type" : "string" }, + "uniqueItems" : true + } + ] } } } diff --git a/CKAN/CKAN/Module.cs b/CKAN/CKAN/Module.cs index 67626c2a0c..f9257c4874 100644 --- a/CKAN/CKAN/Module.cs +++ b/CKAN/CKAN/Module.cs @@ -51,12 +51,19 @@ public class ResourcesDescriptor public KerbalStuffResourceDescriptor kerbalstuff; } + // [JsonObject(MemberSerialization.OptIn)] public class ModuleInstallDescriptor : InstallableDescriptor { - public string description; - public bool optional; - public bool overwrite; - public string requires; + 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))] + public List filter; + + [JsonConverter(typeof (JsonSingleOrArrayConverter))] + public List filter_regexp; } public enum License diff --git a/CKAN/CKAN/ModuleInstaller.cs b/CKAN/CKAN/ModuleInstaller.cs index f3608aa63a..ba9bcd621a 100644 --- a/CKAN/CKAN/ModuleInstaller.cs +++ b/CKAN/CKAN/ModuleInstaller.cs @@ -610,7 +610,7 @@ internal static List FindInstallableFiles(InstallableDescriptor } // Is there a better way to extract a tree? - string filter = "^" + stanza.file + "(/|$)"; + 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. @@ -618,7 +618,7 @@ internal static List FindInstallableFiles(InstallableDescriptor foreach (ZipEntry entry in zipfile) { // Skip things we don't want. - if (!Regex.IsMatch(entry.Name, filter)) + if (!Regex.IsMatch(entry.Name, wanted_filter)) { continue; } diff --git a/CKAN/Tests/CKAN/Module.cs b/CKAN/Tests/CKAN/Module.cs index b48a218cc4..56e66df776 100644 --- a/CKAN/Tests/CKAN/Module.cs +++ b/CKAN/Tests/CKAN/Module.cs @@ -33,6 +33,18 @@ public void MetaData() Assert.AreEqual("https://github.com/KSP-KOS/KOS/issues", module.resources.bugtracker.ToString()); } + [Test] + public void FilterRead() + { + CkanModule module = CkanModule.FromJson(TestData.DogeCoinFlag_101()); + + // Assert known things about this mod. + Assert.IsNotNull(module.install[0].filter); + Assert.IsNotNull(module.install[0].filter_regexp); + + Assert.AreEqual(2, module.install[0].filter.Count); + } + } } diff --git a/CKAN/Tests/TestData.cs b/CKAN/Tests/TestData.cs index 715dc37c1d..51d954f942 100644 --- a/CKAN/Tests/TestData.cs +++ b/CKAN/Tests/TestData.cs @@ -78,7 +78,9 @@ public static string DogeCoinFlag_101() ""install"": [ { ""file"": ""DogeCoinFlag-1.01/GameData/DogeCoinFlag"", - ""install_to"": ""GameData"" + ""install_to"": ""GameData"", + ""filter"" : [ ""Thumbs.db"", ""INSTALL.md"" ], + ""filter_regexp"" : ""\\.bak$"" } ], ""resources"": { diff --git a/Spec.md b/Spec.md index 84594db58a..5fcf385702 100644 --- a/Spec.md +++ b/Spec.md @@ -239,7 +239,20 @@ mandatory directives: Paths will be preserved, but directories will *only* be created when installing to `GameData` or `Tutorial`. -An install directive may also include the following optional fields: +Optionally, an install directive may filter the files to install using: + +- `filter` : A string, or list of strings, of file parts that should not + be installed. These are treated as literal things which must match a + file name or directory. Examples of filters may be `Thumbs.db`, + or `Source`. Filters are considered case-insensitive. +- `filter_regexp` : A string, or list of strings, which are treated as + case-sensitive C# regular expressions whch are matched against the + full paths from the installing zip-file. If a file matches the regular + expression, it is not installed. + +An install directive may also include the following optional fields. +Use of these fields are *discouraged*, and they may become deprecated +in the future. - `depends`: Indicates this install directive should only be triggered if the required mod has already been installed.