diff --git a/Core/ModuleInstaller.cs b/Core/ModuleInstaller.cs index 99dcb9ae7c..ea529be30b 100644 --- a/Core/ModuleInstaller.cs +++ b/Core/ModuleInstaller.cs @@ -514,7 +514,7 @@ public static List FindInstallableFiles(CkanModule module, ZipF else { files.AddRange(ModuleInstallDescriptor - .DefaultInstallStanza(module.identifier) + .DefaultInstallStanza(ksp.game, module.identifier) .FindInstallableFiles(zipfile, ksp)); } } diff --git a/Core/Types/CkanModule.cs b/Core/Types/CkanModule.cs index 0e23b32bc9..22191d2bc2 100644 --- a/Core/Types/CkanModule.cs +++ b/Core/Types/CkanModule.cs @@ -10,6 +10,7 @@ using log4net; using Newtonsoft.Json; using CKAN.Versioning; +using CKAN.Games; namespace CKAN { @@ -683,7 +684,7 @@ public override string ToString() return string.Format("{0} {1}", identifier, version); } - public string DescribeInstallStanzas() + public string DescribeInstallStanzas(IGame game) { List descriptions = new List(); if (install != null) @@ -695,7 +696,7 @@ public string DescribeInstallStanzas() } else { - descriptions.Add(ModuleInstallDescriptor.DefaultInstallStanza(identifier).DescribeMatch()); + descriptions.Add(ModuleInstallDescriptor.DefaultInstallStanza(game, identifier).DescribeMatch()); } return string.Join(", ", descriptions); } diff --git a/Core/Types/ModuleInstallDescriptor.cs b/Core/Types/ModuleInstallDescriptor.cs index 6fbe0cd14a..257b03255a 100644 --- a/Core/Types/ModuleInstallDescriptor.cs +++ b/Core/Types/ModuleInstallDescriptor.cs @@ -211,12 +211,12 @@ public override int GetHashCode() /// /// { "find": "ident", "install_to": "GameData" } /// - public static ModuleInstallDescriptor DefaultInstallStanza(string ident) + public static ModuleInstallDescriptor DefaultInstallStanza(IGame game, string ident) { return new ModuleInstallDescriptor() { find = ident, - install_to = "GameData", + install_to = game.PrimaryModDirectoryRelative, }; } diff --git a/Netkan/Validators/InstallValidator.cs b/Netkan/Validators/InstallValidator.cs index 6e8a414568..a437bd7282 100644 --- a/Netkan/Validators/InstallValidator.cs +++ b/Netkan/Validators/InstallValidator.cs @@ -14,6 +14,10 @@ public void Validate(Metadata metadata) foreach (JObject stanza in json["install"]) { string install_to = (string)stanza["install_to"]; + if (string.IsNullOrEmpty(install_to)) + { + throw new Kraken("install stanza missing `install_to`"); + } if (metadata.SpecVersion < v1p2 && install_to.StartsWith("GameData/")) { throw new Kraken("spec_version v1.2+ required for GameData with path"); diff --git a/Netkan/Validators/InstallsFilesValidator.cs b/Netkan/Validators/InstallsFilesValidator.cs index 4f3f02c749..6fbc333440 100644 --- a/Netkan/Validators/InstallsFilesValidator.cs +++ b/Netkan/Validators/InstallsFilesValidator.cs @@ -3,6 +3,7 @@ using CKAN.NetKAN.Model; using CKAN.NetKAN.Services; using CKAN.Extensions; +using CKAN.Games; namespace CKAN.NetKAN.Validators { @@ -29,7 +30,7 @@ public void Validate(Metadata metadata) { throw new Kraken(string.Format( "Module contains no files matching: {0}", - mod.DescribeInstallStanzas() + mod.DescribeInstallStanzas(new KerbalSpaceProgram()) )); } diff --git a/Spec.md b/Spec.md index b41815de2f..d98c7f4886 100644 --- a/Spec.md +++ b/Spec.md @@ -326,15 +326,14 @@ In addition, any number of optional directives *may* be provided: If no install sections are provided, a CKAN client *must* find the top-most directory in the archive that matches the module identifier, -and install that with a target of `GameData`. - -A typical install directive only has `file` and `install_to` sections: +and install that with a target of `GameData`. In other words, the +default install section is: ```json - "install" : [ + "install": [ { - "file" : "GameData/ExampleMod", - "install_to" : "GameData" + "find": "", + "install_to": "GameData" } ] ``` diff --git a/Tests/Core/ModuleInstaller.cs b/Tests/Core/ModuleInstaller.cs index 8a41c48625..3e54f89812 100644 --- a/Tests/Core/ModuleInstaller.cs +++ b/Tests/Core/ModuleInstaller.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using CKAN; +using CKAN.Games; using Tests.Core.Configuration; using Tests.Data; @@ -73,13 +74,13 @@ public void GenerateDefaultInstall() string filename = TestData.DogeCoinFlagZip(); using (var zipfile = new ZipFile(filename)) { - ModuleInstallDescriptor stanza = ModuleInstallDescriptor.DefaultInstallStanza("DogeCoinFlag"); + ModuleInstallDescriptor stanza = ModuleInstallDescriptor.DefaultInstallStanza(new KerbalSpaceProgram(), "DogeCoinFlag"); Assert.AreEqual("GameData", stanza.install_to); Assert.AreEqual("DogeCoinFlag", stanza.find); // Same again, but screwing up the case (we see this *all the time*) - ModuleInstallDescriptor stanza2 = ModuleInstallDescriptor.DefaultInstallStanza("DogecoinFlag"); + ModuleInstallDescriptor stanza2 = ModuleInstallDescriptor.DefaultInstallStanza(new KerbalSpaceProgram(), "DogecoinFlag"); Assert.AreEqual("GameData", stanza2.install_to); Assert.AreEqual("DogecoinFlag", stanza2.find); @@ -362,7 +363,7 @@ public void CorruptZip_242() using (var zipfile = new ZipFile(corrupt_dogezip)) { // GenerateDefault Install - ModuleInstallDescriptor.DefaultInstallStanza("DogeCoinFlag"); + ModuleInstallDescriptor.DefaultInstallStanza(new KerbalSpaceProgram(), "DogeCoinFlag"); // FindInstallableFiles CkanModule dogemod = TestData.DogeCoinFlag_101_module();