Esempio n. 1
0
        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."
                        );
        }
Esempio n. 2
0
        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));
        }
Esempio n. 3
0
        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)
                        );
        }
Esempio n. 4
0
        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());
            }
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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."
                        );
        }
Esempio n. 7
0
        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."
                        );
        }
Esempio n. 8
0
        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"
                        );
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        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());
            }
        }
Esempio n. 11
0
        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());
            }
        }