Beispiel #1
0
        public CkanModule GeneratorRandomModule(
            KSPVersion kspVersion = null,
            List <RelationshipDescriptor> conflicts = null,
            List <RelationshipDescriptor> depends   = null,
            List <RelationshipDescriptor> sugests   = null,
            List <String> provides = null,
            string identifier      = null,
            Version version        = null)
        {
            var mod = new CkanModule
            {
                name         = Generator.Next().ToString(CultureInfo.InvariantCulture),
                @abstract    = Generator.Next().ToString(CultureInfo.InvariantCulture),
                identifier   = identifier ?? Generator.Next().ToString(CultureInfo.InvariantCulture),
                spec_version = new Version(1.ToString(CultureInfo.InvariantCulture)),
                ksp_version  = kspVersion ?? new KSPVersion("0." + Generator.Next()),
                version      = version ?? new Version(Generator.Next().ToString(CultureInfo.InvariantCulture))
            };

            mod.ksp_version_max = mod.ksp_version_min = new KSPVersion(null);
            mod.conflicts       = conflicts;
            mod.depends         = depends;
            mod.suggests        = sugests;
            mod.provides        = provides;
            return(mod);
        }
        public bool Compatible(KSPVersion gameVersion, CkanModule module)
        {
            KSPVersion ksp_version = module.ksp_version;
            KSPVersion ksp_version_min = module.ksp_version_min;
            KSPVersion ksp_version_max = module.ksp_version_max;

            // Check the min and max versions.

            if (ksp_version_min.IsNotAny() && gameVersion < ksp_version_min)
            {
                return false;
            }

            if (ksp_version_max.IsNotAny() && gameVersion > ksp_version_max)
            {
                return false;
            }

            // We didn't hit the min/max guards. They may not have existed.

            // Note that since ksp_version is "any" if not specified, this
            // will work fine if there's no target, or if there were min/max
            // fields and we passed them successfully.

            return ksp_version.Targets(gameVersion);
        }
Beispiel #3
0
 public CkanModule GeneratorRandomModule(
     KSPVersion ksp_version = null,
     List<RelationshipDescriptor> conflicts = null,
     List<RelationshipDescriptor> depends = null,
     List<RelationshipDescriptor> sugests = null,
     List<String> provides = null,
     string identifier = null,
     Version version = null)
 {
     var mod = new CkanModule
     {
         name = Generator.Next().ToString(CultureInfo.InvariantCulture),
         @abstract = Generator.Next().ToString(CultureInfo.InvariantCulture),
         identifier = identifier??Generator.Next().ToString(CultureInfo.InvariantCulture),
         spec_version = new Version(1.ToString(CultureInfo.InvariantCulture)),
         ksp_version = ksp_version ?? new KSPVersion("0." + Generator.Next()),
         version = version ?? new Version(Generator.Next().ToString(CultureInfo.InvariantCulture))
     };
     mod.ksp_version_max = mod.ksp_version_min = new KSPVersion(null);
     mod.conflicts = conflicts;
     mod.depends = depends;
     mod.suggests = sugests;
     mod.provides = provides;
     return mod;
 }
Beispiel #4
0
 /// <summary>
 /// Attempts to convert the module_names to ckan modules via  CkanModule.FromIDandVersion and then calls RelationshipResolver.ctor(IEnumerable{CkanModule}, Registry, KSPVersion)"/>
 /// </summary>
 /// <param name="module_names"></param>
 /// <param name="options"></param>
 /// <param name="registry"></param>
 /// <param name="kspversion"></param>
 public RelationshipResolver(IEnumerable<string> module_names, RelationshipResolverOptions options, Registry registry,
     KSPVersion kspversion)
     : this(module_names.Select(name => CkanModule.FromIDandVersion(registry, name, kspversion)).ToList(),
             options,
             registry,
             kspversion)
 {
     // Does nothing, just calls the other overloaded constructor
 }
Beispiel #5
0
        /// <summary>
        /// Creates a new Relationship resolver.
        /// </summary>
        /// <param name="options"><see cref="RelationshipResolverOptions"/></param>
        /// <param name="registry">The registry to use</param>
        /// <param name="kspversion">The version of the install that the registry corresponds to</param>
        public RelationshipResolver(RelationshipResolverOptions options, Registry registry, KSPVersion kspversion)
        {
            this.registry = registry;
            this.kspversion = kspversion;
            this.options = options;

            installed_modules = new HashSet<Module>(registry.InstalledModules.Select(i_module => i_module.Module));
            var installed_relationship = new SelectionReason.Installed();
            foreach (var module in installed_modules)
            {
                reasons.Add(module, installed_relationship);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Return the most recent release of a module with a optional ksp version to target and a RelationshipDescriptor to satisfy. 
        /// </summary>
        /// <param name="ksp_version">If not null only consider mods which match this ksp version.</param>
        /// <param name="relationship">If not null only consider mods which satisfy the RelationshipDescriptor.</param>
        /// <returns></returns>
        public CkanModule Latest(KSPVersion ksp_version = null, RelationshipDescriptor relationship=null)
        {
            var available_versions = new List<Version>(module_version.Keys);
            CkanModule module;
            log.DebugFormat("Our dictionary has {0} keys", module_version.Keys.Count);
            log.DebugFormat("Choosing between {0} available versions", available_versions.Count);
            // Uh oh, nothing available. Maybe this existed once, but not any longer.
            if (available_versions.Count == 0)
            {
                return null;
            }

            // Sort most recent versions first.
            available_versions.Reverse();

            if (ksp_version == null && relationship == null)
            {
                module = module_version[available_versions.First()];

                log.DebugFormat("No KSP version restriction, {0} is most recent", module);
                return module;
            }
            if (relationship == null)
            {
                // Time to check if there's anything that we can satisfy.
                var version =
                    available_versions.FirstOrDefault(v => module_version[v].IsCompatibleKSP(ksp_version));
                if (version != null)
                    return module_version[version];

                log.DebugFormat("No version of {0} is compatible with KSP {1}",
                    module_version[available_versions[0]].identifier, ksp_version);

                return null;
            }
            if (ksp_version == null)
            {
                var version = available_versions.FirstOrDefault(relationship.version_within_bounds);
                return version == null ? null : module_version[version];
            }
            else
            {
                var version = available_versions.FirstOrDefault(v =>
                    relationship.version_within_bounds(v) &&
                    module_version[v].IsCompatibleKSP(ksp_version));
                return version == null ? null : module_version[version];
            }
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            string major = "0";
            string minor = "0";
            string patch = "0";

            JToken token = JToken.Load(reader);

            log.DebugFormat("Read Token: {0}, {1}", new Object[] { token.Type, token.ToString() });
            if (token.Type == JTokenType.String)
            {
                string[] tokenArray = token.ToString().Split('.');

                if (tokenArray.Length >= 0)
                {
                    major = tokenArray [0];
                }

                if (tokenArray.Length >= 1)
                {
                    minor = tokenArray [1];
                }

                if (tokenArray.Length >= 2)
                {
                    patch = tokenArray [2];
                }
            }
            else if (token.Type == JTokenType.Object)
            {
                major = (string)token ["MAJOR"];
                minor = (string)token ["MINOR"];
                patch = (string)token ["PATCH"];
            }
            else
            {
                throw new InvalidCastException("Trying to convert non-JSON object to Version object");
            }

            string version = string.Join(".", major, minor, patch);

            log.DebugFormat("  extracted version: {0}", version);
            KSPVersion result = new KSPVersion(version);

            log.DebugFormat("  generated result: {0}", result.ToString());
            return(result);
        }
Beispiel #8
0
        public bool Compatible(KSPVersion gameVersion, CkanModule module)
        {
            // If it's strictly compatible, then it's compatible.
            if (strict.Compatible(gameVersion, module))
                return true;

            // If we're in strict mode, and it's not strictly compatible, then it's
            // not compatible.
            if (module.ksp_version_strict)
                return false;

            // Otherwise, check if it's "generally recognise as safe".

            // If we're running KSP 1.0.4, then allow the mod to run if we would have
            // considered it compatible under 1.0.3 (as 1.0.4 was "just a hotfix").
            if (gameVersion.Equals("1.0.4"))
                return strict.Compatible(v103, module);

            return false;
        }
Beispiel #9
0
        public GUIMod(Module mod, IRegistryQuerier registry, KSPVersion current_ksp_version)
        {
            IsCKAN = mod is CkanModule;
            //Currently anything which could alter these causes a full reload of the modlist
            // If this is ever changed these could be moved into the properties
            Mod = mod;
            IsInstalled = registry.IsInstalled(mod.identifier, false);
            IsInstallChecked = IsInstalled;
            HasUpdate = registry.HasUpdate(mod.identifier, current_ksp_version);
            IsIncompatible = !mod.IsCompatibleKSP(current_ksp_version);
            IsAutodetected = registry.IsAutodetected(mod.identifier);
            Authors = mod.author == null ? "N/A" : String.Join(",", mod.author);

            var installed_version = registry.InstalledVersion(mod.identifier);
            Version latest_version = null;
            var ksp_version = mod.ksp_version;
            try
            {
                var latest_available = registry.LatestAvailable(mod.identifier, current_ksp_version);
                if (latest_available != null)
                    latest_version = latest_available.version;
            }
            catch (ModuleNotFoundKraken)
            {
                latest_version = installed_version;
            }

            InstalledVersion = installed_version != null ? installed_version.ToString() : "-";
            LatestVersion = latest_version != null ? latest_version.ToString() : "-";
            KSPversion = ksp_version != null ? ksp_version.ToString() : "-";

            Abstract = mod.@abstract;
            Homepage = mod.resources != null && mod.resources.homepage != null
                ? (object) mod.resources.homepage
                : "N/A";

            Identifier = mod.identifier;
        }
Beispiel #10
0
 /// <summary>
 /// <see cref = "IRegistryQuerier.LatestAvailableWithProvides" />
 /// </summary>
 public List<CkanModule> LatestAvailableWithProvides(string module, KSPVersion ksp_version, RelationshipDescriptor relationship_descriptor = null)
 {
     // This public interface calculates a cache of modules which
     // are compatible with the current version of KSP, and then
     // calls the private version below for heavy lifting.
     return LatestAvailableWithProvides(module, ksp_version,
         available_modules.Values.Select(pair => pair.Latest(ksp_version)).Where(mod => mod != null).ToArray(),
         relationship_descriptor);
 }
Beispiel #11
0
        /// <summary>
        /// <see cref = "IRegistryQuerier.LatestAvailable" />
        /// </summary>
        // TODO: Consider making this internal, because practically everything should
        // be calling LatestAvailableWithProvides()
        public CkanModule LatestAvailable(
            string module,
            KSPVersion ksp_version,
            RelationshipDescriptor relationship_descriptor =null)
        {
            log.DebugFormat("Finding latest available for {0}", module);

            // TODO: Check user's stability tolerance (stable, unstable, testing, etc)

            try
            {
                return available_modules[module].Latest(ksp_version,relationship_descriptor);
            }
            catch (KeyNotFoundException)
            {
                throw new ModuleNotFoundKraken(module);
            }
        }
Beispiel #12
0
        /// <summary>
        /// <see cref="IRegistryQuerier.Incompatible"/>
        /// </summary>
        public List<CkanModule> Incompatible(KSPVersion ksp_version)
        {
            var candidates = new List<string>(available_modules.Keys);
            var incompatible = new List<CkanModule>();

            // It's nice to see things in alphabetical order, so sort our keys first.
            candidates.Sort();

            // Now find what we can give our user.
            foreach (string candidate in candidates)
            {
                CkanModule available = LatestAvailable(candidate, ksp_version);

                if (available == null)
                {
                    incompatible.Add(LatestAvailable(candidate, null));
                }
            }

            return incompatible;
        }
Beispiel #13
0
        /// <summary>
        /// <see cref="IRegistryQuerier.Available"/>
        /// </summary>
        public List<CkanModule> Available(KSPVersion ksp_version)
        {
            var candidates = new List<string>(available_modules.Keys);
            var compatible = new List<CkanModule>();

            // It's nice to see things in alphabetical order, so sort our keys first.
            candidates.Sort();

            //Cache
            CkanModule[] modules_for_current_version = available_modules.Values.Select(pair => pair.Latest(ksp_version)).Where(mod => mod != null).ToArray();
            // Now find what we can give our user.
            foreach (string candidate in candidates)
            {
                CkanModule available = LatestAvailable(candidate, ksp_version);

                if (available != null)
                {
                    // we need to check that we can get everything we depend on
                    bool failedDepedency = false;

                    if (available.depends != null)
                    {
                        foreach (RelationshipDescriptor dependency in available.depends)
                        {
                            try
                            {
                                if (!LatestAvailableWithProvides(dependency.name, ksp_version, modules_for_current_version).Any())
                                {
                                    failedDepedency = true;
                                    break;
                                }
                            }
                            catch (KeyNotFoundException e)
                            {
                                log.ErrorFormat("Cannot find available version with provides for {0} in registry", dependency.name);
                                throw e;
                            }
                            catch (ModuleNotFoundKraken)
                            {
                                failedDepedency = true;
                                break;
                            }
                        }
                    }

                    if (!failedDepedency)
                    {
                        compatible.Add(available);
                    }
                }
            }

            return compatible;
        }
Beispiel #14
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
            JsonSerializer serializer)
        {
            string major = "0";
            string minor = "0";
            string patch = "0";

            JToken token = JToken.Load(reader);
            log.DebugFormat("Read Token: {0}, {1}", new Object[] {token.Type, token.ToString()});
            switch (token.Type)
            {
                case JTokenType.String:
                    var token_array = token.ToString().Split('.');

                    if (token_array.Length >= 0)
                    {
                        major = token_array[0];
                    }

                    if (token_array.Length >= 1)
                    {
                        minor = token_array[1];
                    }

                    if (token_array.Length >= 2)
                    {
                        patch = token_array[2];
                    }
                    break;
                case JTokenType.Object:
                    major = (string) token["MAJOR"];
                    minor = (string) token["MINOR"];
                    patch = (string) token["PATCH"];
                    break;
                default:
                    throw new InvalidCastException("Trying to convert non-JSON object to Version object");
            }

            //AVC uses -1 to indicate a wildcard.
            int integer;
            string version;
            if (int.TryParse(major, out integer) && integer == AVC_WILDCARD)
            {
                version = null;
            }
            else if (int.TryParse(minor, out integer) && integer == AVC_WILDCARD)
            {
                version = major;
            }
            else if (int.TryParse(patch, out integer) && integer == AVC_WILDCARD)
            {
                version = string.Join(".", major, minor);
            }
            else
            {
                version = string.Join(".", major, minor, patch);
            }

            log.DebugFormat("  extracted version: {0}", version);
            KSPVersion result = new KSPVersion(version);
            log.DebugFormat("  generated result: {0}", result);
            return result;
        }
Beispiel #15
0
 public bool HasUpdate(string identifier, KSPVersion version)
 {
     CkanModule newestVersion;
     try
     {
         newestVersion = LatestAvailable(identifier, version);
     }
     catch (ModuleNotFoundKraken)
     {
         return false;
     }
     if (newestVersion == null) return false;
     return IsInstalled(identifier) && newestVersion.version.IsGreaterThan(InstalledVersion(identifier));
 }
Beispiel #16
0
        public GUIMod(Module mod, IRegistryQuerier registry, KSPVersion current_ksp_version)
        {
            IsCKAN = mod is CkanModule;
            //Currently anything which could alter these causes a full reload of the modlist
            // If this is ever changed these could be moved into the properties
            Mod = mod;
            IsInstalled = registry.IsInstalled(mod.identifier, false);
            IsInstallChecked = IsInstalled;
            HasUpdate = registry.HasUpdate(mod.identifier, current_ksp_version);
            IsIncompatible = !mod.IsCompatibleKSP(current_ksp_version);
            IsAutodetected = registry.IsAutodetected(mod.identifier);
            Authors = mod.author == null ? "N/A" : String.Join(",", mod.author);

            var installed_version = registry.InstalledVersion(mod.identifier);
            Version latest_version = null;
            var ksp_version = mod.ksp_version;

            try
            {
                var latest_available = registry.LatestAvailable(mod.identifier, current_ksp_version);
                if (latest_available != null)
                    latest_version = latest_available.version;
            }
            catch (ModuleNotFoundKraken)
            {
                latest_version = installed_version;
            }

            InstalledVersion = installed_version != null ? installed_version.ToString() : "-";

            // Let's try to find the compatibility for this mod. If it's not in the registry at
            // all (because it's a DarkKAN mod) then this might fail.

            CkanModule latest_available_for_any_ksp = null;

            try
            {
                latest_available_for_any_ksp = registry.LatestAvailable(mod.identifier, null);
            }
            catch
            {
                // If we can't find the mod in the CKAN, but we've a CkanModule installed, then
                // use that.
                if (IsCKAN)
                    latest_available_for_any_ksp = (CkanModule) mod;

            }

            // If there's known information for this mod in any form, calculate the highest compatible
            // KSP.
            if (latest_available_for_any_ksp != null)
            {
                KSPCompatibility = KSPCompatibilityLong = latest_available_for_any_ksp.HighestCompatibleKSP();

                // If the mod we have installed is *not* the mod we have installed, or we don't know
                // what we have installed, indicate that an upgrade would be needed.
                if (installed_version == null || !latest_available_for_any_ksp.version.IsEqualTo(installed_version))
                {
                    KSPCompatibilityLong = string.Format("{0} (using mod version {1})",
                        KSPCompatibility, latest_available_for_any_ksp.version);
                }
            }
            else
            {
                // No idea what this mod is, sorry!
                KSPCompatibility = KSPCompatibilityLong = "unknown";
            }

            if (latest_version != null)
            {
                LatestVersion = latest_version.ToString();
            }
            else if (latest_available_for_any_ksp != null)
            {
                LatestVersion = latest_available_for_any_ksp.version.ToString();
            }
            else
            {
                LatestVersion = "-";
            }

            KSPversion = ksp_version != null ? ksp_version.ToString() : "-";

            Abstract = mod.@abstract;

            // If we have homepage provided use that, otherwise use the kerbalstuff page or the github repo so that users have somewhere to get more info than just the abstract.

            Homepage = "N/A";
            if (mod.resources != null)
            {
                if (mod.resources.homepage != null)
                {
                    Homepage = mod.resources.homepage.ToString();
                }
                else if (mod.resources.kerbalstuff != null)
                {
                    Homepage = mod.resources.kerbalstuff.ToString();
                }
                else if (mod.resources.repository != null)
                {
                    Homepage = mod.resources.repository.ToString();
                }
            }

            Identifier = mod.identifier;
        }
Beispiel #17
0
        public KSPVersion Version()
        {
            if (version != null)
            {
                return version;
            }

            return version = DetectVersion(GameDir());
        }
Beispiel #18
0
        public static Dictionary<GUIMod, string> ComputeConflictsFromModList(Registry registry,
            IEnumerable<KeyValuePair<GUIMod, GUIModChangeType>> change_set, KSPVersion ksp_version)
        {
            var modules_to_install = new HashSet<string>();
            var modules_to_remove = new HashSet<string>();
            var options = new RelationshipResolverOptions
            {
                without_toomanyprovides_kraken = true,
                procede_with_inconsistencies = true,
                without_enforce_consistency = true,
                with_recommends = false
            };

            foreach (var change in change_set)
            {
                switch (change.Value)
                {
                    case GUIModChangeType.None:
                        break;
                    case GUIModChangeType.Install:
                        modules_to_install.Add(change.Key.Identifier);
                        break;
                    case GUIModChangeType.Remove:
                        modules_to_remove.Add(change.Key.Identifier);
                        break;
                    case GUIModChangeType.Update:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }

            var installed =
                registry.Installed()
                    .Where(pair => pair.Value.CompareTo(new ProvidesVersion("")) != 0)
                    .Select(pair => pair.Key);

            //We wish to only check mods that would exist after the changes are made.
            var mods_to_check = installed.Union(modules_to_install).Except(modules_to_remove);
            var resolver = new RelationshipResolver(mods_to_check.ToList(), options, registry, ksp_version);
            return resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version),
                item => item.Value);
        }
Beispiel #19
0
        public GUIMod(Module mod, IRegistryQuerier registry, KSPVersion current_ksp_version)
        {
            IsCKAN = mod is CkanModule;
            //Currently anything which could alter these causes a full reload of the modlist
            // If this is ever changed these could be moved into the properties
            Mod = mod;
            IsInstalled = registry.IsInstalled(mod.identifier, false);
            IsInstallChecked = IsInstalled;
            HasUpdate = registry.HasUpdate(mod.identifier, current_ksp_version);
            IsIncompatible = !mod.IsCompatibleKSP(current_ksp_version);
            IsAutodetected = registry.IsAutodetected(mod.identifier);
            Authors = mod.author == null ? "N/A" : String.Join(",", mod.author);

            var installed_version = registry.InstalledVersion(mod.identifier);
            Version latest_version = null;
            var ksp_version = mod.ksp_version;

            try
            {
                var latest_available = registry.LatestAvailable(mod.identifier, current_ksp_version);
                if (latest_available != null)
                    latest_version = latest_available.version;
            }
            catch (ModuleNotFoundKraken)
            {
                latest_version = installed_version;
            }

            InstalledVersion = installed_version != null ? installed_version.ToString() : "-";

            // Let's try to find the compatibility for this mod. If it's not in the registry at
            // all (because it's a DarkKAN mod) then this might fail.

            CkanModule latest_available_for_any_ksp = null;

            try
            {
                latest_available_for_any_ksp = registry.LatestAvailable(mod.identifier, null);
            }
            catch
            {
                // If we can't find the mod in the CKAN, but we've a CkanModule installed, then
                // use that.
                if (IsCKAN)
                    latest_available_for_any_ksp = (CkanModule) mod;

            }

            // If there's known information for this mod in any form, calculate the highest compatible
            // KSP.
            if (latest_available_for_any_ksp != null)
            {
                KSPCompatibility = KSPCompatibilityLong = latest_available_for_any_ksp.HighestCompatibleKSP();

                // If the mod we have installed is *not* the mod we have installed, or we don't know
                // what we have installed, indicate that an upgrade would be needed.
                if (installed_version == null || !latest_available_for_any_ksp.version.IsEqualTo(installed_version))
                {
                    KSPCompatibilityLong = string.Format("{0} (using mod version {1})",
                        KSPCompatibility, latest_available_for_any_ksp.version);
                }
            }
            else
            {
                // No idea what this mod is, sorry!
                KSPCompatibility = KSPCompatibilityLong = "unknown";
            }

            if (latest_version != null)
            {
                LatestVersion = latest_version.ToString();
            }
            else if (latest_available_for_any_ksp != null)
            {
                LatestVersion = latest_available_for_any_ksp.version.ToString();
            }
            else
            {
                LatestVersion = "-";
            }

            KSPversion = ksp_version != null ? ksp_version.ToString() : "-";

            Abstract = mod.@abstract;

            // If we have homepage provided use that, otherwise use the kerbalstuff page or the github repo so that users have somewhere to get more info than just the abstract.

            Homepage = "N/A";
            if (mod.resources != null)
            {
                if (mod.resources.homepage != null)
                {
                    Homepage = mod.resources.homepage.ToString();
                }
                else if (mod.resources.kerbalstuff != null)
                {
                    Homepage = mod.resources.kerbalstuff.ToString();
                }
                else if (mod.resources.repository != null)
                {
                    Homepage = mod.resources.repository.ToString();
                }
            }

            Identifier = mod.identifier;

            if (mod.download_size == 0)
                DownloadSize = "N/A";
            else if (mod.download_size / 1024.0 < 1)
                DownloadSize = "1<KB";
            else
                DownloadSize = mod.download_size / 1024+"";

            Abbrevation = new string(mod.name.Split(' ').
                Where(s => s.Length > 0).Select(s => s[0]).ToArray());

            // The following two lines seem unnecessary. mod.download looks like it will always be null
            // because it is never set up to this point. If InMaybeCachedZip() is executed, a NullReferenceException
            // is thrown. So, simply set IsCached = false.

            //if (Main.Instance != null)
            //    IsCached = Main.Instance.CurrentInstance.Cache.IsMaybeCachedZip(mod.download);

            IsCached = false;
        }
Beispiel #20
0
 public bool Compatible(KSPVersion gameVersion, CkanModule module)
 {
     return true;
 }
Beispiel #21
0
 public GUIMod(CkanModule mod, IRegistryQuerier registry, KSPVersion current_ksp_version)
     : this((Module) mod, registry, current_ksp_version)
 {
 }
Beispiel #22
0
        /// <summary>
        /// Returns the latest version of a module that can be installed for
        /// the given KSP version. This is a *private* method that assumes
        /// the `available_for_current_version` list has been correctly
        /// calculated. Not for direct public consumption. ;)
        /// </summary>
        private List<CkanModule> LatestAvailableWithProvides(string module, KSPVersion ksp_version,
            IEnumerable<CkanModule> available_for_current_version, RelationshipDescriptor relationship_descriptor=null)
        {
            log.DebugFormat("Finding latest available with provides for {0}", module);

            // TODO: Check user's stability tolerance (stable, unstable, testing, etc)

            var modules = new List<CkanModule>();

            try
            {
                // If we can find the module requested for our KSP, use that.
                CkanModule mod = LatestAvailable(module, ksp_version, relationship_descriptor);
                if (mod != null)
                {
                    modules.Add(mod);
                }
            }
            catch (ModuleNotFoundKraken)
            {
                // It's cool if we can't find it, though.
            }

            // Walk through all our available modules, and see if anything
            // provides what we need.

            // Get our candidate module. We can assume this is non-null, as
            // if it *is* null then available_for_current_version is corrupted,
            // and something is terribly wrong.
            foreach (CkanModule candidate in available_for_current_version)
            {
                // Find everything this module provides (for our version of KSP)
                List<string> provides = candidate.provides;

                // If the module has provides, and any of them are what we're looking
                // for, the add it to our list.
                if (provides != null && provides.Any(provided => provided == module))
                {
                    modules.Add(candidate);
                }
            }
            return modules;
        }
        public override void Initialize()
        {
            var registry = Main.Instance.CurrentInstance.Registry;

            _kspVersion = Main.Instance.CurrentInstance.Version();

            foreach (var module in registry.Available(_kspVersion))
            {
                var latest = registry.LatestAvailable(module.identifier, _kspVersion);
                if (latest.resources != null)
                {
                    if (latest.resources.spacedock != null)
                    {
                        var ksId = int.Parse(latest.resources.spacedock.ToString().Split('/')[2]);
                        _spaceDockToCkanMap[ksId] = latest;
                    }
                }
            }

            var webBrowser = new WebBrowser
            {
                Dock = DockStyle.Fill,
                Url  = new Uri("http://spacedock.info", UriKind.Absolute)
            };

            webBrowser.DocumentCompleted += (sender, args) =>
            {
                var thumbnails = GetElementsByClass(webBrowser.Document, "thumbnail");
                foreach (var thumbnail in thumbnails)
                {
                    var         url           = "";
                    HtmlElement activeElement = null;
                    // Find url
                    foreach (HtmlElement child in thumbnail.Children)
                    {
                        if (child.InnerHtml.Contains("href"))
                        {
                            url = child.GetAttribute("href");
                            break;
                        }
                        if (child.InnerHtml.Contains("ksp-update") && activeElement == null)
                        {
                            activeElement = child;
                        }
                    }
                    var sdModId = int.Parse(url.Split('/')[2]);

                    var module = CkanModuleForSpaceDockId(sdModId);
                    if (module != null && activeElement != null)
                    {
                        activeElement.InnerHtml = "<span class='badge' title='This mod is listed in CKAN.'>CKAN</span>" + activeElement.InnerHtml;
                        if (IsModuleInstalled(module.identifier))
                        {
                            activeElement.InnerHtml += "<div style=\"margin-top: 32px;\" class=\"ksp-update\">Installed</div>";
                        }
                    }
                }

                HtmlElement downloadLink = webBrowser.Document.GetElementById("download-link-primary");
                if (downloadLink == null)
                {
                    return;
                }
                int modId = -1;

                var downloadUrl = downloadLink.GetAttribute("href");
                if (downloadUrl.StartsWith("#"))
                {
                    modId = int.Parse(downloadUrl.Substring(1));
                }
                else if (!int.TryParse(downloadUrl.Split('/')[2], out modId))
                {
                    modId = -1;
                }

                var ckanModule = CkanModuleForSpaceDockId(modId);
                if (ckanModule != null)
                {
                    downloadLink.SetAttribute("href", "#" + modId.ToString());

                    if (IsModuleInstalled(ckanModule.identifier))
                    {
                        downloadLink.InnerHtml = "Installed";
                    }
                    else if (IsModuleSelectedForInstall(ckanModule.identifier))
                    {
                        downloadLink.InnerHtml = "Selected for install";
                    }
                    else
                    {
                        downloadLink.InnerHtml = "Add to CKAN install";

                        webBrowser.Document.Body.MouseDown += (o, e) =>
                        {
                            switch (e.MouseButtonsPressed)
                            {
                            case MouseButtons.Left:
                                HtmlElement element = webBrowser.Document.GetElementFromPoint(e.ClientMousePosition);
                                if (element != null && element.Id == "download-link-primary")
                                {
                                    SelectModuleForInstall(ckanModule.identifier);
                                }
                                break;
                            }
                        };
                    }
                }
            };

            var tabPage = new TabPage
            {
                Name = "SpaceDockBrowserBrowserTabPage",
                Text = "SpaceDock"
            };

            tabPage.Controls.Add(webBrowser);

            Main.Instance.m_TabController.m_TabPages.Add("SpaceDockBrowser", tabPage);
            Main.Instance.m_TabController.ShowTab("SpaceDockBrowser", 1, false);
        }
Beispiel #24
0
 /// <summary>
 /// Is the mod installed and does it have a newer version compatible with version
 /// We can't update AD mods
 /// </summary>
 public static bool HasUpdate(this IRegistryQuerier querier, string identifier, KSPVersion version)
 {
     CkanModule newest_version;
     try
     {
         newest_version = querier.LatestAvailable(identifier, version);
     }
     catch (ModuleNotFoundKraken)
     {
         return false;
     }
     if (newest_version == null) return false;
     return !new List<string>(querier.InstalledDlls).Contains(identifier) && querier.IsInstalled(identifier, false) 
         && newest_version.version.IsGreaterThan(querier.InstalledVersion(identifier));
 }
Beispiel #25
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
                                        JsonSerializer serializer)
        {
            var major = "0";
            var minor = "0";
            var patch = "0";

            var token = JToken.Load(reader);

            Log.DebugFormat("Read Token: {0}, {1}", new object[] { token.Type, token.ToString() });
            switch (token.Type)
            {
            case JTokenType.String:
                var tokenArray = token.ToString().Split('.');

                if (tokenArray.Length > 0)
                {
                    major = tokenArray[0];
                }

                if (tokenArray.Length > 1)
                {
                    minor = tokenArray[1];
                }

                if (tokenArray.Length > 2)
                {
                    patch = tokenArray[2];
                }
                break;

            case JTokenType.Object:
                major = (string)token["MAJOR"];
                minor = (string)token["MINOR"];
                patch = (string)token["PATCH"];
                break;

            default:
                throw new InvalidCastException("Trying to convert non-JSON object to Version object");
            }

            //AVC uses -1 to indicate a wildcard.
            int    integer;
            string version;

            if (int.TryParse(major, out integer) && integer == AvcWildcard)
            {
                version = null;
            }
            else if (int.TryParse(minor, out integer) && integer == AvcWildcard)
            {
                version = major;
            }
            else if (int.TryParse(patch, out integer) && integer == AvcWildcard)
            {
                version = string.Join(".", major, minor);
            }
            else
            {
                version = string.Join(".", major, minor, patch);
            }

            Log.DebugFormat("  extracted version: {0}", version);
            var result = new KSPVersion(version);

            Log.DebugFormat("  generated result: {0}", result);
            return(result);
        }
Beispiel #26
0
 /// <summary>
 /// Creates a new resolver that will find a way to install all the modules specified.
 /// </summary>
 public RelationshipResolver(IEnumerable<CkanModule> modules, RelationshipResolverOptions options, Registry registry,
     KSPVersion kspversion)
     : this(options,registry,kspversion)
 {
     AddModulesToInstall(modules);
 }
Beispiel #27
0
        /// <summary>
        /// This function returns a changeset based on the selections of the user.
        /// Currently returns null if a conflict is detected.
        /// </summary>
        /// <param name="registry"></param>
        /// <param name="changeSet"></param>
        /// <param name="installer">A module installer for the current KSP install</param>
        /// <param name="version">The version of the current KSP install</param>
        public async Task<IEnumerable<KeyValuePair<GUIMod, GUIModChangeType>>> ComputeChangeSetFromModList(
            Registry registry, HashSet<KeyValuePair<GUIMod, GUIModChangeType>> changeSet, ModuleInstaller installer,
            KSPVersion version)
        {
            var modules_to_install = new HashSet<CkanModule>();
            var modules_to_remove = new HashSet<Module>();
            var options = new RelationshipResolverOptions
            {
                without_toomanyprovides_kraken = false,
                with_recommends = false
            };

            foreach (var change in changeSet)
            {
                switch (change.Value)
                {
                    case GUIModChangeType.None:
                        break;
                    case GUIModChangeType.Install:
                        modules_to_install.Add(change.Key.ToCkanModule());
                        break;
                    case GUIModChangeType.Remove:
                        modules_to_remove.Add(change.Key);
                        break;
                    case GUIModChangeType.Update:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
            var installed_modules =
                registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod);


            bool handled_all_to_many_provides = false;
            while (!handled_all_to_many_provides)
            {
                //Can't await in catch clause - doesn't seem to work in mono. Hence this flag
                TooManyModsProvideKraken kraken;
                try
                {
                    new RelationshipResolver(modules_to_install.ToList(), options, registry, version);
                    handled_all_to_many_provides = true;
                    continue;
                }
                catch (TooManyModsProvideKraken k)
                {
                    kraken = k;
                }
                catch (ModuleNotFoundKraken k)
                {
                    //We shouldn't need this. However the relationship provider will throw TMPs with incompatible mods.
                    user.RaiseError("Module {0} has not been found. This may be because it is not compatible " +
                                    "with the currently installed version of KSP", k.module);
                    return null;
                }
                //Shouldn't get here unless there is a kraken.
                var mod = await too_many_provides(kraken);
                if (mod != null)
                {
                    modules_to_install.Add(mod);
                }
                else
                {
                    //TODO Is could be a new type of Kraken.
                    throw kraken;
                }
            }


            foreach (var dependency in modules_to_remove.
                Select(mod => installer.FindReverseDependencies(mod.identifier)).
                SelectMany(reverse_dependencies => reverse_dependencies))
            {
                //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed
                Module module_by_version = registry.GetModuleByVersion(installed_modules[dependency].identifier,
                    installed_modules[dependency].version) ?? registry.InstalledModule(dependency).Module;
                changeSet.Add(
                    new KeyValuePair<GUIMod, GUIModChangeType>(
                        new GUIMod(module_by_version, registry, version), GUIModChangeType.Remove));
            }
            //May throw InconsistentKraken
            var resolver = new RelationshipResolver(options, registry, version);
            resolver.RemoveModsFromInstalledList(
                changeSet.Where(change => change.Value.Equals(GUIModChangeType.Remove)).Select(m => m.Key.ToModule()));
            resolver.AddModulesToInstall(modules_to_install.ToList());
            changeSet.UnionWith(
                resolver.ModList()
                    .Select(
                        mod =>
                            new KeyValuePair<GUIMod, GUIModChangeType>(new GUIMod(mod, registry, version),
                                GUIModChangeType.Install)));


            return changeSet;
        }