public void DoesNotOverrideExistingVersionInfo() { // Arrange var avcVersion = new AvcVersion { version = new ModuleVersion("1.2.3") }; var mHttp = new Mock <IHttpService>(); var mModuleService = new Mock <IModuleService>(); mModuleService.Setup(i => i.GetInternalAvc(It.IsAny <CkanModule>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(avcVersion); var sut = new AvcTransformer(mHttp.Object, mModuleService.Object); var json = new JObject(); json["spec_version"] = 1; json["identifier"] = "AwesomeMod"; json["$vref"] = "#/ckan/ksp-avc"; json["download"] = "https://awesomemod.example/AwesomeMod.zip"; json["version"] = "9001"; // Act var result = sut.Transform(new Metadata(json), opts).First(); var transformedJson = result.Json(); // Assert Assert.That((string)transformedJson["version"], Is.EqualTo("9001"), "AvcTransformer should not override an existing version." ); }
private static Uri GetRemoteAvcUri(AvcVersion avc) { if (!Uri.IsWellFormedUriString(avc.Url, UriKind.Absolute)) { return(null); } var remoteUri = new Uri(avc.Url); Log.InfoFormat("Remote AVC version file at: {0}", remoteUri); return(CKAN.Net.GetRawUri(remoteUri)); }
public void OverridesExistingVersionInfo(string propertyName) { // Arrange var avcVersion = new AvcVersion(); switch (propertyName) { case "version": avcVersion.version = new Version("1.2.3"); break; case "ksp_version": avcVersion.ksp_version = new KSPVersion("1.2.3"); break; case "ksp_version_min": avcVersion.ksp_version_min = new KSPVersion("1.2.3"); break; case "ksp_version_max": avcVersion.ksp_version_max = new KSPVersion("1.2.3"); break; } var mHttp = new Mock <IHttpService>(); var mModuleService = new Mock <IModuleService>(); mModuleService.Setup(i => i.GetInternalAvc(It.IsAny <CkanModule>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(avcVersion); var sut = new AvcTransformer(mHttp.Object, mModuleService.Object); var json = new JObject(); json["spec_version"] = 1; json["identifier"] = "AwesomeMod"; json["$vref"] = "#/ckan/ksp-avc"; json["download"] = "https://awesomemod.example/AwesomeMod.zip"; json[propertyName] = "9001"; // Act var result = sut.Transform(new Metadata(json)); var transformedJson = result.Json(); // Assert Assert.That((string)transformedJson[propertyName], Is.EqualTo("1.2.3"), string.Format("AvcTransformer should override an existing {0}.", propertyName) ); }
public static void ApplyVersions(JObject json, AvcVersion avc) { ModuleService.ApplyVersions(json, avc.ksp_version, avc.ksp_version_min, avc.ksp_version_max); if (avc.version != null) { // 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()); } }
public IEnumerable <Metadata> Transform(Metadata metadata, TransformOptions opts) { 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); var url = new Uri(metadata.Kref.Id); AvcVersion remoteAvc = JsonConvert.DeserializeObject <AvcVersion>( githubSrc?.DownloadText(url) ?? httpSvc.DownloadText(CKAN.Net.GetRawUri(url)) ); json.SafeAdd("name", remoteAvc.Name); json.Remove("$kref"); 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); yield return(new Metadata(json)); } else { yield return(metadata); } }
public void PreferentiallyAddsRangedKspVersionInfo() { // Arrange var avcVersion = new AvcVersion { ksp_version = KspVersion.Parse("1.0.4"), ksp_version_min = KspVersion.Parse("0.90"), ksp_version_max = KspVersion.Parse("1.0.3") }; var mHttp = new Mock <IHttpService>(); var mModuleService = new Mock <IModuleService>(); mModuleService.Setup(i => i.GetInternalAvc(It.IsAny <CkanModule>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(avcVersion); var sut = new AvcTransformer(mHttp.Object, mModuleService.Object); var json = new JObject(); json["spec_version"] = 1; json["identifier"] = "AwesomeMod"; json["$vref"] = "#/ckan/ksp-avc"; json["download"] = "https://awesomemod.example/AwesomeMod.zip"; // Act var result = sut.Transform(new Metadata(json), opts).First(); var transformedJson = result.Json(); // Assert Assert.That((string)transformedJson["ksp_version_min"], Is.EqualTo("0.90"), "AvcTransformer should add the KSP min version specified in the AVC version file." ); Assert.That((string)transformedJson["ksp_version_max"], Is.EqualTo("1.0.3"), "AvcTransformer should add the KSP min version specified in the AVC version file." ); Assert.That(transformedJson["ksp_version"], Is.Null, "AvcTransformer should not add a KSP version if min or max versions are specified." ); }
public void AddsMissingVersionInfo() { // Arrange var avcVersion = new AvcVersion { version = new ModuleVersion("1.0.0"), ksp_version = GameVersion.Parse("1.0.4") }; var mHttp = new Mock <IHttpService>(); var mModuleService = new Mock <IModuleService>(); mModuleService.Setup(i => i.GetInternalAvc(It.IsAny <CkanModule>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(avcVersion); var sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null); var json = new JObject(); json["spec_version"] = 1; json["identifier"] = "AwesomeMod"; json["$vref"] = "#/ckan/ksp-avc"; json["download"] = "https://awesomemod.example/AwesomeMod.zip"; // Act var result = sut.Transform(new Metadata(json), opts).First(); var transformedJson = result.Json(); // Assert Assert.That((string)transformedJson["version"], Is.EqualTo("1.0.0"), "AvcTransformer should add the version specified in the AVC version file." ); Assert.That((string)transformedJson["ksp_version"], Is.EqualTo("1.0.4"), "AvcTransformer should add the game version specified in the AVC version file." ); }
public void CorrectlyCalculatesKspVersionInfo( string existingKsp, string existingKspMin, string existingKspMax, string avcKsp, string avcKspMin, string avcKspMax, string expectedKsp, string expectedKspMin, string expectedKspMax ) { // Arrange var json = new JObject(); json["spec_version"] = 1; json["identifier"] = "AwesomeMod"; json["$vref"] = "#/ckan/ksp-avc"; json["download"] = "https://awesomemod.example/AwesomeMod.zip"; if (!string.IsNullOrWhiteSpace(existingKsp)) { json["ksp_version"] = existingKsp; } if (!string.IsNullOrWhiteSpace(existingKspMin)) { json["ksp_version_min"] = existingKspMin; } if (!string.IsNullOrWhiteSpace(existingKspMax)) { json["ksp_version_max"] = existingKspMax; } var avcVersion = new AvcVersion(); if (!string.IsNullOrWhiteSpace(avcKsp)) { avcVersion.ksp_version = KspVersion.Parse(avcKsp); } if (!string.IsNullOrWhiteSpace(avcKspMin)) { avcVersion.ksp_version_min = KspVersion.Parse(avcKspMin); } if (!string.IsNullOrWhiteSpace(avcKspMax)) { avcVersion.ksp_version_max = KspVersion.Parse(avcKspMax); } var mHttp = new Mock <IHttpService>(); var mModuleService = new Mock <IModuleService>(); mModuleService.Setup(i => i.GetInternalAvc(It.IsAny <CkanModule>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(avcVersion); var sut = new AvcTransformer(mHttp.Object, mModuleService.Object); // Act var result = sut.Transform(new Metadata(json), opts).First(); var transformedJson = result.Json(); // Assert Assert.That((string)transformedJson["ksp_version"], Is.EqualTo(expectedKsp), "AvcTransformer should calculate ksp_version correctly" ); Assert.That((string)transformedJson["ksp_version_min"], Is.EqualTo(expectedKspMin), "AvcTransformer should calculate ksp_version_min correctly" ); Assert.That((string)transformedJson["ksp_version_max"], Is.EqualTo(expectedKspMax), "AvcTransformer should calculate ksp_version_max correctly" ); }
private static Uri GetRemoteAvcUri(AvcVersion avc) { if (!Uri.IsWellFormedUriString(avc.Url, UriKind.Absolute)) { return(null); } var remoteUri = new Uri(avc.Url); Log.InfoFormat("Remote AVC version file at: {0}", remoteUri); // Authors may use the URI of the GitHub file page instead of the URL to the actual raw file. // Detect that case and automatically transform the remote URL to one we can use. // This is hacky and fragile but it's basically what KSP-AVC itself does in its // FormatCompatibleUrl(string) method so we have to go along with the flow: // https://github.com/CYBUTEK/KSPAddonVersionChecker/blob/ff94000144a666c8ff637c71b802e1baee9c15cd/KSP-AVC/AddonInfo.cs#L199 // However, this implementation is more robust as it actually parses the URI rather than doing // basic string replacements. if (string.Compare(remoteUri.Host, "github.com", StringComparison.OrdinalIgnoreCase) == 0) { // We expect a non-raw URI to be in one of two forms: // 1. https://github.com/<USER>/<PROJECT>/blob/<BRANCH>/<PATH> // 2. https://github.com/<USER>/<PROJECT>/tree/<BRANCH>/<PATH> // // Therefore, we expect at least six segments in the path: // 1. "/" // 2. "<USER>/" // 3. "<PROJECT>/" // 4. "blob/" or "tree/" // 5. "<BRANCH>/" // 6+. "<PATH>" // // And that the forth segment (index 3) is either "blob/" or "tree/" var remoteUriBuilder = new UriBuilder(remoteUri) { // Replace host with raw host Host = "raw.githubusercontent.com" }; // Check that the path is what we expect var segments = remoteUri.Segments.ToList(); if (segments.Count < 6 || string.Compare(segments[3], "blob/", StringComparison.OrdinalIgnoreCase) != 0 && string.Compare(segments[3], "tree/", StringComparison.OrdinalIgnoreCase) != 0) { Log.WarnFormat("Remote non-raw GitHub URL is in an unknown format, using as is."); return(remoteUri); } // Remove "blob/" or "tree/" segment from raw URI segments.RemoveAt(3); remoteUriBuilder.Path = string.Join("", segments); Log.InfoFormat("Canonicalized non-raw GitHub URL to: {0}", remoteUriBuilder.Uri); return(remoteUriBuilder.Uri); } return(remoteUri); }
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"]; var existingKspMin = existingKspMinStr == null ? null : KspVersion.Parse(existingKspMinStr); var existingKspMax = existingKspMaxStr == null ? null : KspVersion.Parse(existingKspMaxStr); // Get the minimum and maximum KSP versions that are in the AVC file. // http://ksp.cybutek.net/kspavc/Documents/README.htm // KSP-AVC allows (requires?) KSP_VERSION to be set // when KSP_VERSION_MIN/_MAX are set, but CKAN treats // its equivalent properties as mutually exclusive. // Only fallback if neither min nor max are defined, // for open ranges. KspVersion avcKspMin, avcKspMax; if (avc.ksp_version_min == null && avc.ksp_version_max == null) { // Use specific KSP version if min/max don't exist avcKspMin = avcKspMax = avc.ksp_version; } else { avcKspMin = avc.ksp_version_min; avcKspMax = avc.ksp_version_max; } // 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>(); if (!KspVersion.IsNullOrAny(existingKspMin)) { kspMins.Add(existingKspMin); } if (!KspVersion.IsNullOrAny(avcKspMin)) { kspMins.Add(avcKspMin); } if (!KspVersion.IsNullOrAny(existingKspMax)) { kspMaxes.Add(existingKspMax); } if (!KspVersion.IsNullOrAny(avcKspMax)) { kspMaxes.Add(avcKspMax); } 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 (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 (kspMin != null) { json["ksp_version_min"] = kspMin.ToString(); } if (kspMax != null) { json["ksp_version_max"] = kspMax.ToString(); } } } if (avc.version != null) { // 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()); } }
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"]; var existingKspMin = existingKspMinStr == null ? null : KspVersion.Parse(existingKspMinStr); var existingKspMax = existingKspMaxStr == null ? null : KspVersion.Parse(existingKspMaxStr); // 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; // 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>(); if (!KspVersion.IsNullOrAny(existingKspMin)) { kspMins.Add(existingKspMin); } if (!KspVersion.IsNullOrAny(avcKspMin)) { kspMins.Add(avcKspMin); } if (!KspVersion.IsNullOrAny(existingKspMax)) { kspMaxes.Add(existingKspMax); } if (!KspVersion.IsNullOrAny(avcKspMax)) { kspMaxes.Add(avcKspMax); } 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 (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 (kspMin != null) { json["ksp_version_min"] = kspMin.ToString(); } if (kspMax != null) { json["ksp_version_max"] = kspMax.ToString(); } } } if (avc.version != null) { // 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()); } }