示例#1
0
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            AvailableOptions opts     = (AvailableOptions)raw_options;
            IRegistryQuerier registry = RegistryManager.Instance(ksp).registry;

            var compatible = registry
                             .CompatibleModules(ksp.VersionCriteria())
                             .Where(m => !m.IsDLC);

            user.RaiseMessage("Modules compatible with KSP {0}", ksp.Version());
            user.RaiseMessage("");

            if (opts.detail)
            {
                foreach (CkanModule module in compatible)
                {
                    user.RaiseMessage("* {0} ({1}) - {2} - {3}", module.identifier, module.version, module.name, module.@abstract);
                }
            }
            else
            {
                foreach (CkanModule module in compatible)
                {
                    user.RaiseMessage("* {0} ({1}) - {2}", module.identifier, module.version, module.name);
                }
            }

            return(Exit.OK);
        }
示例#2
0
        /// <summary>
        /// Searches for the term in the list of compatible or incompatible modules for the ksp instance.
        /// Looks in name, identifier and description fields, and if given, restricts to authors matching the author term.
        /// </summary>
        /// <returns>List of matching modules.</returns>
        /// <param name="ksp">The KSP instance to perform the search for.</param>
        /// <param name="term">The search term. Case insensitive.</param>
        /// <param name="author">Name of author to find</param>
        /// <param name="searchIncompatible">True to look for incompatible modules, false (default) to look for compatible</param>
        public List <CkanModule> PerformSearch(CKAN.GameInstance ksp, string term, string author = null, bool searchIncompatible = false)
        {
            // Remove spaces and special characters from the search term.
            term   = String.IsNullOrWhiteSpace(term)   ? string.Empty : CkanModule.nonAlphaNums.Replace(term, "");
            author = String.IsNullOrWhiteSpace(author) ? string.Empty : CkanModule.nonAlphaNums.Replace(author, "");

            var registry = RegistryManager.Instance(ksp).registry;

            if (!searchIncompatible)
            {
                return(registry
                       .CompatibleModules(ksp.VersionCriteria())
                       // Look for a match in each string.
                       .Where(module => (module.SearchableName.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 ||
                                         module.SearchableIdentifier.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 ||
                                         module.SearchableAbstract.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 ||
                                         module.SearchableDescription.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1) &&
                              module.SearchableAuthors.Any((auth) => auth.IndexOf(author, StringComparison.OrdinalIgnoreCase) > -1))
                       .ToList());
            }
            else
            {
                return(registry
                       .IncompatibleModules(ksp.VersionCriteria())
                       // Look for a match in each string.
                       .Where(module => (module.SearchableName.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 ||
                                         module.SearchableIdentifier.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 ||
                                         module.SearchableAbstract.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 ||
                                         module.SearchableDescription.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1) &&
                              module.SearchableAuthors.Any((auth) => auth.IndexOf(author, StringComparison.OrdinalIgnoreCase) > -1))
                       .ToList());
            }
        }
示例#3
0
        /// <summary>
        /// Try to repair our registry.
        /// </summary>
        private int Registry(CKAN.GameInstance ksp)
        {
            RegistryManager manager = RegistryManager.Instance(ksp);

            manager.registry.Repair();
            manager.Save();
            User.RaiseMessage("Registry repairs attempted. Hope it helped.");
            return(Exit.OK);
        }
示例#4
0
文件: Upgrade.cs 项目: embix/CKAN
 /// <summary>
 /// Upgrade some modules by their identifier and (optional) version
 /// </summary>
 /// <param name="manager">Game instance manager to use</param>
 /// <param name="user">IUser object for output</param>
 /// <param name="ksp">Game instance to use</param>
 /// <param name="identsAndVersions">List of identifier[=version] to upgrade</param>
 public static void UpgradeModules(GameInstanceManager manager, IUser user, CKAN.GameInstance ksp, List <string> identsAndVersions)
 {
     UpgradeModules(manager, user, ksp,
                    (ModuleInstaller installer, NetAsyncModulesDownloader downloader, RegistryManager regMgr, ref HashSet <string> possibleConfigOnlyDirs) =>
                    installer.Upgrade(identsAndVersions, downloader,
                                      ref possibleConfigOnlyDirs, regMgr, true),
                    m => identsAndVersions.Add(m.identifier)
                    );
 }
示例#5
0
文件: Upgrade.cs 项目: embix/CKAN
 /// <summary>
 /// Upgrade some modules by their CkanModules
 /// </summary>
 /// <param name="manager">Game instance manager to use</param>
 /// <param name="user">IUser object for output</param>
 /// <param name="ksp">Game instance to use</param>
 /// <param name="modules">List of modules to upgrade</param>
 public static void UpgradeModules(GameInstanceManager manager, IUser user, CKAN.GameInstance ksp, bool ConfirmPrompt, List <CkanModule> modules)
 {
     UpgradeModules(manager, user, ksp,
                    (ModuleInstaller installer, NetAsyncModulesDownloader downloader, RegistryManager regMgr, ref HashSet <string> possibleConfigOnlyDirs) =>
                    installer.Upgrade(modules, downloader,
                                      ref possibleConfigOnlyDirs, regMgr, true, true, ConfirmPrompt),
                    m => modules.Add(m)
                    );
 }
示例#6
0
 public static CKAN.GameInstance GetGameInstance(GameInstanceManager manager)
 {
     CKAN.GameInstance inst = manager.CurrentInstance
                              ?? manager.GetPreferredInstance();
     if (inst == null)
     {
         throw new NoGameInstanceKraken();
     }
     return(inst);
 }
 public FakeConfiguration(CKAN.GameInstance instance, string autostart)
     : this(
         new List <Tuple <string, string, string> >
 {
     new Tuple <string, string, string>("test", instance.GameDir(), "KSP")
 },
         autostart
         )
 {
 }
示例#8
0
文件: Update.cs 项目: zxasqwsss/CKAN
        /// <summary>
        /// Updates the repository.
        /// </summary>
        /// <param name="ksp">The KSP instance to work on.</param>
        /// <param name="repository">Repository to update. If null all repositories are used.</param>
        private void UpdateRepository(CKAN.GameInstance ksp, string repository = null)
        {
            RegistryManager registry_manager = RegistryManager.Instance(ksp);

            var updated = repository == null
                ? CKAN.Repo.UpdateAllRepositories(registry_manager, ksp, manager.Cache, user) != CKAN.RepoUpdateResult.Failed
                : CKAN.Repo.Update(registry_manager, ksp, user, repository);

            user.RaiseMessage("Updated information on {0} compatible modules", registry_manager.registry.CompatibleModules(ksp.VersionCriteria()).Count());
        }
示例#9
0
        /// <summary>
        /// Update the registry
        /// </summary>
        /// <param name="ksp">Game instance to update</param>
        /// <param name="raw_options">Command line options object</param>
        /// <returns>
        /// Exit code for shell environment
        /// </returns>
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            UpdateOptions options = (UpdateOptions)raw_options;

            List <CkanModule> compatible_prior = null;

            if (options.list_changes)
            {
                // Get a list of compatible modules prior to the update.
                var registry = RegistryManager.Instance(ksp).registry;
                compatible_prior = registry.CompatibleModules(ksp.VersionCriteria()).ToList();
            }

            // If no repository is selected, select all.
            if (options.repo == null)
            {
                options.update_all = true;
            }

            try
            {
                if (options.update_all)
                {
                    UpdateRepository(ksp);
                }
                else
                {
                    UpdateRepository(ksp, options.repo);
                }
            }
            catch (ReinstallModuleKraken rmk)
            {
                Upgrade.UpgradeModules(manager, user, ksp, false, rmk.Modules);
            }
            catch (MissingCertificateKraken kraken)
            {
                // Handling the kraken means we have prettier output.
                user.RaiseMessage(kraken.ToString());
                return(Exit.ERROR);
            }

            if (options.list_changes)
            {
                var registry = RegistryManager.Instance(ksp).registry;
                PrintChanges(compatible_prior, registry.CompatibleModules(ksp.VersionCriteria()).ToList());
            }

            return(Exit.OK);
        }
示例#10
0
        internal static CkanModule LoadCkanFromFile(CKAN.GameInstance current_instance, string ckan_file)
        {
            CkanModule module = CkanModule.FromFile(ckan_file);

            // We'll need to make some registry changes to do this.
            RegistryManager registry_manager = RegistryManager.Instance(current_instance);

            // Remove this version of the module in the registry, if it exists.
            registry_manager.registry.RemoveAvailable(module);

            // Sneakily add our version in...
            registry_manager.registry.AddAvailable(module);

            return(module);
        }
示例#11
0
        /// <summary>
        /// Convert case insensitive mod names from the user to case sensitive identifiers
        /// </summary>
        /// <param name="ksp">Game instance forgetting the mods</param>
        /// <param name="modules">List of strings to convert, format 'identifier' or 'identifier=version'</param>
        public static void AdjustModulesCase(CKAN.GameInstance ksp, List <string> modules)
        {
            IRegistryQuerier registry = RegistryManager.Instance(ksp).registry;
            // Get the list of all compatible and incompatible mods
            List <CkanModule> mods = registry.CompatibleModules(ksp.VersionCriteria()).ToList();

            mods.AddRange(registry.IncompatibleModules(ksp.VersionCriteria()));
            for (int i = 0; i < modules.Count; ++i)
            {
                Match match = CkanModule.idAndVersionMatcher.Match(modules[i]);
                if (match.Success)
                {
                    // Handle name=version format
                    string ident   = match.Groups["mod"].Value;
                    string version = match.Groups["version"].Value;
                    modules[i] = $"{CaseInsensitiveExactMatch(mods, ident)}={version}";
                }
                else
                {
                    modules[i] = CaseInsensitiveExactMatch(mods, modules[i]);
                }
            }
        }
示例#12
0
 /// <summary>
 /// Execute an import command
 /// </summary>
 /// <param name="ksp">Game instance into which to import</param>
 /// <param name="options">Command line parameters from the user</param>
 /// <returns>
 /// Process exit code
 /// </returns>
 public int RunCommand(CKAN.GameInstance ksp, object options)
 {
     try
     {
         ImportOptions      opts     = options as ImportOptions;
         HashSet <FileInfo> toImport = GetFiles(opts);
         if (toImport.Count < 1)
         {
             user.RaiseMessage("Usage: ckan import path [path2, ...]");
             return(Exit.ERROR);
         }
         else
         {
             log.InfoFormat("Importing {0} files", toImport.Count);
             List <string>   toInstall = new List <string>();
             RegistryManager regMgr    = RegistryManager.Instance(ksp);
             ModuleInstaller inst      = new ModuleInstaller(ksp, manager.Cache, user);
             inst.ImportFiles(toImport, user, mod => toInstall.Add(mod.identifier), regMgr.registry, !opts.Headless);
             HashSet <string> possibleConfigOnlyDirs = null;
             if (toInstall.Count > 0)
             {
                 inst.InstallList(
                     toInstall,
                     new RelationshipResolverOptions(),
                     regMgr,
                     ref possibleConfigOnlyDirs
                     );
             }
             return(Exit.OK);
         }
     }
     catch (Exception ex)
     {
         user.RaiseError("Import error: {0}", ex.Message);
         return(Exit.ERROR);
     }
 }
示例#13
0
        private void ShowVersionTable(CKAN.GameInstance inst, List <CkanModule> modules)
        {
            var versions     = modules.Select(m => m.version.ToString()).ToList();
            var gameVersions = modules.Select(m =>
            {
                GameVersion minKsp = null, maxKsp = null;
                Registry.GetMinMaxVersions(new List <CkanModule>()
                {
                    m
                }, out _, out _, out minKsp, out maxKsp);
                return(GameVersionRange.VersionSpan(inst.game, minKsp, maxKsp));
            }).ToList();

            string[] headers           = new string[] { "Version", "Game Versions" };
            int      versionLength     = Math.Max(headers[0].Length, versions.Max(v => v.Length));
            int      gameVersionLength = Math.Max(headers[1].Length, gameVersions.Max(v => v.Length));

            user.RaiseMessage("");
            user.RaiseMessage(
                "{0}  {1}",
                headers[0].PadRight(versionLength),
                headers[1].PadRight(gameVersionLength)
                );
            user.RaiseMessage(
                "{0}  {1}",
                new string('-', versionLength),
                new string('-', gameVersionLength)
                );
            for (int row = 0; row < versions.Count; ++row)
            {
                user.RaiseMessage(
                    "{0}  {1}",
                    versions[row].PadRight(versionLength),
                    gameVersions[row].PadRight(gameVersionLength)
                    );
            }
        }
示例#14
0
文件: Upgrade.cs 项目: embix/CKAN
 /// <summary>
 /// The core of the module upgrading logic, with callbacks to
 /// support different input formats managed by the calling code.
 /// Handles transactions, creating commonly required objects,
 /// looping logic, prompting for TooManyModsProvideKraken resolution.
 /// </summary>
 /// <param name="manager">Game instance manager to use</param>
 /// <param name="user">IUser object for output</param>
 /// <param name="ksp">Game instance to use</param>
 /// <param name="attemptUpgradeCallback">Function to call to try to perform the actual upgrade, may throw TooManyModsProvideKraken</param>
 /// <param name="addUserChoiceCallback">Function to call when the user has requested a new module added to the change set in response to TooManyModsProvideKraken</param>
 private static void UpgradeModules(
     GameInstanceManager manager, IUser user, CKAN.GameInstance ksp,
     AttemptUpgradeAction attemptUpgradeCallback,
     System.Action <CkanModule> addUserChoiceCallback)
 {
     using (TransactionScope transact = CkanTransaction.CreateTransactionScope()) {
         var installer  = new ModuleInstaller(ksp, manager.Cache, user);
         var downloader = new NetAsyncModulesDownloader(user, manager.Cache);
         var regMgr     = RegistryManager.Instance(ksp);
         HashSet <string> possibleConfigOnlyDirs = null;
         bool             done = false;
         while (!done)
         {
             try
             {
                 attemptUpgradeCallback?.Invoke(installer, downloader, regMgr, ref possibleConfigOnlyDirs);
                 transact.Complete();
                 done = true;
             }
             catch (TooManyModsProvideKraken k)
             {
                 int choice = user.RaiseSelectionDialog(
                     k.Message,
                     k.modules.Select(m => $"{m.identifier} ({m.name})").ToArray());
                 if (choice < 0)
                 {
                     return;
                 }
                 else
                 {
                     addUserChoiceCallback?.Invoke(k.modules[choice]);
                 }
             }
         }
     }
 }
示例#15
0
        /// <summary>
        /// Scans the game instance. Detects installed mods to mark as auto-detected and checks the consistency
        /// </summary>
        /// <param name="inst">The instance to scan</param>
        /// <param name="user"></param>
        /// <param name="next_command">Changes the output message if set.</param>
        /// <returns>Exit.OK if instance is consistent, Exit.ERROR otherwise </returns>
        private static int Scan(CKAN.GameInstance inst, IUser user, string next_command = null)
        {
            try
            {
                inst.Scan();
                return(Exit.OK);
            }
            catch (InconsistentKraken kraken)
            {
                if (next_command == null)
                {
                    user.RaiseError(kraken.InconsistenciesPretty);
                    user.RaiseError("The repo has not been saved.");
                }
                else
                {
                    user.RaiseMessage("Preliminary scanning shows that the install is in a inconsistent state.");
                    user.RaiseMessage("Use ckan.exe scan for more details");
                    user.RaiseMessage("Proceeding with {0} in case it fixes it.\r\n", next_command);
                }

                return(Exit.ERROR);
            }
        }
示例#16
0
文件: Show.cs 项目: zxasqwsss/CKAN
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            ShowOptions options = (ShowOptions)raw_options;

            if (options.Modname == null)
            {
                // empty argument
                user.RaiseMessage("show <module> - module name argument missing, perhaps you forgot it?");
                return(Exit.BADOPT);
            }

            // Check installed modules for an exact match.
            var registry = RegistryManager.Instance(ksp).registry;
            var installedModuleToShow = registry.InstalledModule(options.Modname);

            if (installedModuleToShow != null)
            {
                // Show the installed module.
                return(ShowMod(installedModuleToShow));
            }

            // Module was not installed, look for an exact match in the available modules,
            // either by "name" (the user-friendly display name) or by identifier
            CkanModule moduleToShow = registry
                                      .CompatibleModules(ksp.VersionCriteria())
                                      .SingleOrDefault(
                mod => mod.name == options.Modname ||
                mod.identifier == options.Modname
                );

            if (moduleToShow == null)
            {
                // No exact match found. Try to look for a close match for this KSP version.
                user.RaiseMessage("{0} not found or installed.", options.Modname);
                user.RaiseMessage("Looking for close matches in mods compatible with KSP {0}.", ksp.Version());

                Search search  = new Search(user);
                var    matches = search.PerformSearch(ksp, options.Modname);

                // Display the results of the search.
                if (!matches.Any())
                {
                    // No matches found.
                    user.RaiseMessage("No close matches found.");
                    return(Exit.BADOPT);
                }
                else if (matches.Count() == 1)
                {
                    // If there is only 1 match, display it.
                    user.RaiseMessage("Found 1 close match: {0}", matches[0].name);
                    user.RaiseMessage("");

                    moduleToShow = matches[0];
                }
                else
                {
                    // Display the found close matches.
                    string[] strings_matches = new string[matches.Count];

                    for (int i = 0; i < matches.Count; i++)
                    {
                        strings_matches[i] = matches[i].name;
                    }

                    int selection = user.RaiseSelectionDialog("Close matches", strings_matches);

                    if (selection < 0)
                    {
                        return(Exit.BADOPT);
                    }

                    // Mark the selection as the one to show.
                    moduleToShow = matches[selection];
                }
            }

            return(ShowMod(moduleToShow));
        }
示例#17
0
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            SearchOptions options = (SearchOptions)raw_options;

            // Check the input.
            if (String.IsNullOrWhiteSpace(options.search_term) && String.IsNullOrWhiteSpace(options.author_term))
            {
                user.RaiseError("No search term?");

                return(Exit.BADOPT);
            }

            List <CkanModule> matching_compatible   = PerformSearch(ksp, options.search_term, options.author_term, false);
            List <CkanModule> matching_incompatible = new List <CkanModule>();

            if (options.all)
            {
                matching_incompatible = PerformSearch(ksp, options.search_term, options.author_term, true);
            }

            // Show how many matches we have.
            if (options.all && !String.IsNullOrWhiteSpace(options.author_term))
            {
                user.RaiseMessage("Found {0} compatible and {1} incompatible mods matching \"{2}\" by \"{3}\".",
                                  matching_compatible.Count().ToString(),
                                  matching_incompatible.Count().ToString(),
                                  options.search_term,
                                  options.author_term);
            }
            else if (options.all && String.IsNullOrWhiteSpace(options.author_term))
            {
                user.RaiseMessage("Found {0} compatible and {1} incompatible mods matching \"{2}\".",
                                  matching_compatible.Count().ToString(),
                                  matching_incompatible.Count().ToString(),
                                  options.search_term);
            }
            else if (!options.all && !String.IsNullOrWhiteSpace(options.author_term))
            {
                user.RaiseMessage("Found {0} compatible mods matching \"{1}\" by \"{2}\".",
                                  matching_compatible.Count().ToString(),
                                  options.search_term,
                                  options.author_term);
            }
            else if (!options.all && String.IsNullOrWhiteSpace(options.author_term))
            {
                user.RaiseMessage("Found {0} compatible mods matching \"{1}\".",
                                  matching_compatible.Count().ToString(),
                                  options.search_term);
            }

            // Present the results.
            if (!matching_compatible.Any() && (!options.all || !matching_incompatible.Any()))
            {
                return(Exit.OK);
            }

            if (options.detail)
            {
                user.RaiseMessage("Matching compatible mods:");
                foreach (CkanModule mod in matching_compatible)
                {
                    user.RaiseMessage("* {0} ({1}) - {2} by {3} - {4}",
                                      mod.identifier,
                                      mod.version,
                                      mod.name,
                                      mod.author == null ? "N/A" : String.Join(", ", mod.author),
                                      mod.@abstract);
                }

                if (matching_incompatible.Any())
                {
                    user.RaiseMessage("Matching incompatible mods:");
                    foreach (CkanModule mod in matching_incompatible)
                    {
                        Registry.GetMinMaxVersions(new List <CkanModule> {
                            mod
                        }, out _, out _, out var minKsp, out var maxKsp);
                        string GameVersion = Versioning.GameVersionRange.VersionSpan(ksp.game, minKsp, maxKsp).ToString();

                        user.RaiseMessage("* {0} ({1} - {2}) - {3} by {4} - {5}",
                                          mod.identifier,
                                          mod.version,
                                          GameVersion,
                                          mod.name,
                                          mod.author == null ? "N/A" : String.Join(", ", mod.author),
                                          mod.@abstract);
                    }
                }
            }
            else
            {
                List <CkanModule> matching = matching_compatible.Concat(matching_incompatible).ToList();
                matching.Sort((x, y) => string.Compare(x.identifier, y.identifier, StringComparison.Ordinal));

                foreach (CkanModule mod in matching)
                {
                    user.RaiseMessage(mod.identifier);
                }
            }

            return(Exit.OK);
        }
示例#18
0
        /// <summary>
        /// Uninstalls a module, if it exists.
        /// </summary>
        /// <param name="ksp">Game instance from which to remove</param>
        /// <param name="raw_options">Command line options object</param>
        /// <returns>
        /// Exit code for shell environment
        /// </returns>
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            RemoveOptions   options = (RemoveOptions)raw_options;
            RegistryManager regMgr  = RegistryManager.Instance(ksp);

            // Use one (or more!) regex to select the modules to remove
            if (options.regex)
            {
                log.Debug("Attempting Regex");
                // Parse every "module" as a grumpy regex
                var justins = options.modules.Select(s => new Regex(s));

                // Modules that have been selected by one regex
                List <string> selectedModules = new List <string>();

                // Get the list of installed modules
                // Try every regex on every installed module:
                // if it matches, select for removal
                foreach (string mod in regMgr.registry.InstalledModules.Select(mod => mod.identifier))
                {
                    if (justins.Any(re => re.IsMatch(mod)))
                    {
                        selectedModules.Add(mod);
                    }
                }

                // Replace the regular expressions with the selected modules
                // and continue removal as usual
                options.modules = selectedModules;
            }

            if (options.rmall)
            {
                log.Debug("Removing all mods");
                // Add the list of installed modules to the list that should be uninstalled
                options.modules.AddRange(
                    regMgr.registry.InstalledModules
                    .Where(mod => !mod.Module.IsDLC)
                    .Select(mod => mod.identifier)
                    );
            }

            if (options.modules != null && options.modules.Count > 0)
            {
                try
                {
                    HashSet <string> possibleConfigOnlyDirs = null;
                    var installer = ModuleInstaller.GetInstance(ksp, manager.Cache, user);
                    Search.AdjustModulesCase(ksp, options.modules);
                    installer.UninstallList(options.modules, ref possibleConfigOnlyDirs, regMgr);
                    user.RaiseMessage("");
                }
                catch (ModNotInstalledKraken kraken)
                {
                    user.RaiseMessage("I can't do that, {0} isn't installed.", kraken.mod);
                    user.RaiseMessage("Try `ckan list` for a list of installed mods.");
                    return(Exit.BADOPT);
                }
                catch (ModuleIsDLCKraken kraken)
                {
                    user.RaiseMessage($"CKAN can't remove expansion '{kraken.module.name}' for you.");
                    var res           = kraken?.module?.resources;
                    var storePagesMsg = new Uri[] { res?.store, res?.steamstore }
                    .Where(u => u != null)
                    .Aggregate("", (a, b) => $"{a}\r\n- {b}");
                    if (!string.IsNullOrEmpty(storePagesMsg))
                    {
                        user.RaiseMessage($"To remove this expansion, follow the instructions for the store page from which you purchased it:\r\n{storePagesMsg}");
                    }
                    return(Exit.BADOPT);
                }
                catch (CancelledActionKraken k)
                {
                    user.RaiseMessage("Remove aborted: {0}", k.Message);
                    return(Exit.ERROR);
                }
            }
            else
            {
                user.RaiseMessage("No mod selected, nothing to do");
                return(Exit.BADOPT);
            }

            return(Exit.OK);
        }
示例#19
0
文件: List.cs 项目: zxasqwsss/CKAN
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            ListOptions options = (ListOptions)raw_options;

            IRegistryQuerier registry = RegistryManager.Instance(ksp).registry;

            ExportFileType?exportFileType = null;

            if (!string.IsNullOrWhiteSpace(options.export))
            {
                exportFileType = GetExportFileType(options.export);

                if (exportFileType == null)
                {
                    user.RaiseError("Unknown export format: {0}", options.export);
                }
            }

            if (!(options.porcelain) && exportFileType == null)
            {
                user.RaiseMessage("\r\nKSP found at {0}\r\n", ksp.GameDir());
                user.RaiseMessage("KSP Version: {0}\r\n", ksp.Version());

                user.RaiseMessage("Installed Modules:\r\n");
            }

            if (exportFileType == null)
            {
                var installed = new SortedDictionary <string, ModuleVersion>(registry.Installed());

                foreach (KeyValuePair <string, ModuleVersion> mod in installed)
                {
                    ModuleVersion current_version = mod.Value;
                    string        modInfo         = string.Format("{0} {1}", mod.Key, mod.Value);
                    string        bullet          = "*";

                    if (current_version is ProvidesModuleVersion)
                    {
                        // Skip virtuals for now.
                        continue;
                    }
                    else if (current_version is UnmanagedModuleVersion)
                    {
                        // Autodetected dll
                        bullet = "A";
                    }
                    else
                    {
                        try
                        {
                            // Check if upgrades are available, and show appropriately.
                            log.DebugFormat("Check if upgrades are available for {0}", mod.Key);
                            CkanModule      latest  = registry.LatestAvailable(mod.Key, ksp.VersionCriteria());
                            CkanModule      current = registry.GetInstalledVersion(mod.Key);
                            InstalledModule inst    = registry.InstalledModule(mod.Key);

                            if (latest == null)
                            {
                                // Not compatible!
                                log.InfoFormat("Latest {0} is not compatible", mod.Key);
                                bullet = "X";
                                if (current == null)
                                {
                                    log.DebugFormat(" {0} installed version not found in registry", mod.Key);
                                }

                                // Check if mod is replaceable
                                if (current.replaced_by != null)
                                {
                                    ModuleReplacement replacement = registry.GetReplacement(mod.Key, ksp.VersionCriteria());
                                    if (replacement != null)
                                    {
                                        // Replaceable!
                                        bullet  = ">";
                                        modInfo = string.Format("{0} > {1} {2}", modInfo, replacement.ReplaceWith.name, replacement.ReplaceWith.version);
                                    }
                                }
                            }
                            else if (latest.version.IsEqualTo(current_version))
                            {
                                // Up to date
                                log.InfoFormat("Latest {0} is {1}", mod.Key, latest.version);
                                bullet = (inst?.AutoInstalled ?? false) ? "+" : "-";
                                // Check if mod is replaceable
                                if (current.replaced_by != null)
                                {
                                    ModuleReplacement replacement = registry.GetReplacement(latest.identifier, ksp.VersionCriteria());
                                    if (replacement != null)
                                    {
                                        // Replaceable!
                                        bullet  = ">";
                                        modInfo = string.Format("{0} > {1} {2}", modInfo, replacement.ReplaceWith.name, replacement.ReplaceWith.version);
                                    }
                                }
                            }
                            else if (latest.version.IsGreaterThan(mod.Value))
                            {
                                // Upgradable
                                bullet = "^";
                            }
                        }
                        catch (ModuleNotFoundKraken)
                        {
                            log.InfoFormat("{0} is installed, but no longer in the registry", mod.Key);
                            bullet = "?";
                        }
                    }

                    user.RaiseMessage("{0} {1}", bullet, modInfo);
                }
            }
            else
            {
                var stream = Console.OpenStandardOutput();
                new Exporter(exportFileType.Value).Export(registry, stream);
                stream.Flush();
            }

            if (!(options.porcelain) && exportFileType == null)
            {
                user.RaiseMessage("\r\nLegend: -: Up to date. +:Auto-installed. X: Incompatible. ^: Upgradable. >: Replaceable\r\n        A: Autodetected. ?: Unknown. *: Broken. ");
                // Broken mods are in a state that CKAN doesn't understand, and therefore can't handle automatically
            }

            return(Exit.OK);
        }
示例#20
0
文件: Upgrade.cs 项目: embix/CKAN
        /// <summary>
        /// Upgrade an installed module
        /// </summary>
        /// <param name="ksp">Game instance from which to remove</param>
        /// <param name="raw_options">Command line options object</param>
        /// <returns>
        /// Exit code for shell environment
        /// </returns>
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            UpgradeOptions options = (UpgradeOptions)raw_options;

            if (options.ckan_file != null)
            {
                options.modules.Add(MainClass.LoadCkanFromFile(ksp, options.ckan_file).identifier);
            }

            if (options.modules.Count == 0 && !options.upgrade_all)
            {
                // What? No files specified?
                User.RaiseMessage("Usage: ckan upgrade Mod [Mod2, ...]");
                User.RaiseMessage("  or   ckan upgrade --all");
                if (AutoUpdate.CanUpdate)
                {
                    User.RaiseMessage("  or   ckan upgrade ckan");
                }
                return(Exit.BADOPT);
            }

            if (!options.upgrade_all && options.modules[0] == "ckan" && AutoUpdate.CanUpdate)
            {
                User.RaiseMessage("Querying the latest CKAN version");
                AutoUpdate.Instance.FetchLatestReleaseInfo();
                var latestVersion  = AutoUpdate.Instance.latestUpdate.Version;
                var currentVersion = new ModuleVersion(Meta.GetVersion(VersionFormat.Short));

                if (latestVersion.IsGreaterThan(currentVersion))
                {
                    User.RaiseMessage("New CKAN version available - " + latestVersion);
                    var releaseNotes = AutoUpdate.Instance.latestUpdate.ReleaseNotes;
                    User.RaiseMessage(releaseNotes);
                    User.RaiseMessage("\r\n");

                    if (User.RaiseYesNoDialog("Proceed with install?"))
                    {
                        User.RaiseMessage("Upgrading CKAN, please wait..");
                        AutoUpdate.Instance.StartUpdateProcess(false);
                    }
                }
                else
                {
                    User.RaiseMessage("You already have the latest version.");
                }

                return(Exit.OK);
            }

            try
            {
                var regMgr   = RegistryManager.Instance(ksp);
                var registry = regMgr.registry;
                if (options.upgrade_all)
                {
                    var to_upgrade = new List <CkanModule>();

                    foreach (KeyValuePair <string, ModuleVersion> mod in registry.Installed(false))
                    {
                        try
                        {
                            // Check if upgrades are available
                            var latest = registry.LatestAvailable(mod.Key, ksp.VersionCriteria());

                            // This may be an unindexed mod. If so,
                            // skip rather than crash. See KSP-CKAN/CKAN#841.
                            if (latest == null || latest.IsDLC)
                            {
                                continue;
                            }

                            if (latest.version.IsGreaterThan(mod.Value))
                            {
                                // Upgradable
                                log.InfoFormat("New version {0} found for {1}",
                                               latest.version, latest.identifier);
                                to_upgrade.Add(latest);
                            }
                        }
                        catch (ModuleNotFoundKraken)
                        {
                            log.InfoFormat("{0} is installed, but no longer in the registry",
                                           mod.Key);
                        }
                    }
                    UpgradeModules(manager, User, ksp, true, to_upgrade);
                }
                else
                {
                    Search.AdjustModulesCase(ksp, options.modules);
                    UpgradeModules(manager, User, ksp, options.modules);
                }
                User.RaiseMessage("");
            }
            catch (CancelledActionKraken k)
            {
                User.RaiseMessage("Upgrade aborted: {0}", k.Message);
                return(Exit.ERROR);
            }
            catch (ModuleNotFoundKraken kraken)
            {
                User.RaiseMessage("Module {0} not found", kraken.module);
                return(Exit.ERROR);
            }
            catch (InconsistentKraken kraken)
            {
                User.RaiseMessage(kraken.ToString());
                return(Exit.ERROR);
            }
            catch (ModuleIsDLCKraken kraken)
            {
                User.RaiseMessage($"CKAN can't upgrade expansion '{kraken.module.name}' for you.");
                var res           = kraken?.module?.resources;
                var storePagesMsg = new Uri[] { res?.store, res?.steamstore }
                .Where(u => u != null)
                .Aggregate("", (a, b) => $"{a}\r\n- {b}");
                if (!string.IsNullOrEmpty(storePagesMsg))
                {
                    User.RaiseMessage($"To upgrade this expansion, download any updates from the store page from which you purchased it:\r\n{storePagesMsg}");
                }
                return(Exit.ERROR);
            }

            return(Exit.OK);
        }
示例#21
0
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            ShowOptions options = (ShowOptions)raw_options;

            if (options.modules == null || options.modules.Count < 1)
            {
                // empty argument
                user.RaiseMessage("show <module> - module name argument missing, perhaps you forgot it?");
                return(Exit.BADOPT);
            }

            int combined_exit_code = Exit.OK;
            // Check installed modules for an exact match.
            var registry = RegistryManager.Instance(ksp).registry;

            foreach (string modName in options.modules)
            {
                var installedModuleToShow = registry.InstalledModule(modName);
                if (installedModuleToShow != null)
                {
                    // Show the installed module.
                    combined_exit_code = CombineExitCodes(
                        combined_exit_code,
                        ShowMod(installedModuleToShow)
                        );
                    if (options.with_versions)
                    {
                        ShowVersionTable(ksp, registry.AvailableByIdentifier(installedModuleToShow.identifier).ToList());
                    }
                    user.RaiseMessage("");
                    continue;
                }

                // Module was not installed, look for an exact match in the available modules,
                // either by "name" (the user-friendly display name) or by identifier
                CkanModule moduleToShow = registry
                                          .CompatibleModules(ksp.VersionCriteria())
                                          .SingleOrDefault(
                    mod => mod.name == modName ||
                    mod.identifier == modName
                    );
                if (moduleToShow == null)
                {
                    // No exact match found. Try to look for a close match for this KSP version.
                    user.RaiseMessage(
                        "{0} not installed or compatible with {1} {2}.",
                        modName,
                        ksp.game.ShortName,
                        string.Join(", ", ksp.VersionCriteria().Versions.Select(v => v.ToString()))
                        );
                    user.RaiseMessage("Looking for close matches in compatible mods...");

                    Search search  = new Search(user);
                    var    matches = search.PerformSearch(ksp, modName);

                    // Display the results of the search.
                    if (!matches.Any())
                    {
                        // No matches found.
                        user.RaiseMessage("No close matches found.");
                        combined_exit_code = CombineExitCodes(combined_exit_code, Exit.BADOPT);
                        user.RaiseMessage("");
                        continue;
                    }
                    else if (matches.Count() == 1)
                    {
                        // If there is only 1 match, display it.
                        user.RaiseMessage("Found 1 close match: {0}", matches[0].name);
                        user.RaiseMessage("");

                        moduleToShow = matches[0];
                    }
                    else
                    {
                        // Display the found close matches.
                        int selection = user.RaiseSelectionDialog(
                            "Close matches:",
                            matches.Select(m => m.name).ToArray()
                            );
                        user.RaiseMessage("");
                        if (selection < 0)
                        {
                            combined_exit_code = CombineExitCodes(combined_exit_code, Exit.BADOPT);
                            continue;
                        }

                        // Mark the selection as the one to show.
                        moduleToShow = matches[selection];
                    }
                }

                combined_exit_code = CombineExitCodes(
                    combined_exit_code,
                    ShowMod(moduleToShow)
                    );
                if (options.with_versions)
                {
                    ShowVersionTable(ksp, registry.AvailableByIdentifier(moduleToShow.identifier).ToList());
                }
                user.RaiseMessage("");
            }
            return(combined_exit_code);
        }
示例#22
0
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            ReplaceOptions options = (ReplaceOptions)raw_options;

            if (options.ckan_file != null)
            {
                options.modules.Add(MainClass.LoadCkanFromFile(ksp, options.ckan_file).identifier);
            }

            if (options.modules.Count == 0 && !options.replace_all)
            {
                // What? No mods specified?
                User.RaiseMessage("Usage: ckan replace Mod [Mod2, ...]");
                User.RaiseMessage("  or   ckan replace --all");
                return(Exit.BADOPT);
            }

            // Prepare options. Can these all be done in the new() somehow?
            var replace_ops = new RelationshipResolverOptions
            {
                with_all_suggests  = options.with_all_suggests,
                with_suggests      = options.with_suggests,
                with_recommends    = !options.no_recommends,
                allow_incompatible = options.allow_incompatible
            };

            var regMgr     = RegistryManager.Instance(ksp);
            var registry   = regMgr.registry;
            var to_replace = new List <ModuleReplacement>();

            if (options.replace_all)
            {
                log.Debug("Running Replace all");
                var installed = new Dictionary <string, ModuleVersion>(registry.Installed());

                foreach (KeyValuePair <string, ModuleVersion> mod in installed)
                {
                    ModuleVersion current_version = mod.Value;

                    if ((current_version is ProvidesModuleVersion) || (current_version is UnmanagedModuleVersion))
                    {
                        continue;
                    }
                    else
                    {
                        try
                        {
                            log.DebugFormat("Testing {0} {1} for possible replacement", mod.Key, mod.Value);
                            // Check if replacement is available

                            ModuleReplacement replacement = registry.GetReplacement(mod.Key, ksp.VersionCriteria());
                            if (replacement != null)
                            {
                                // Replaceable
                                log.InfoFormat("Replacement {0} {1} found for {2} {3}",
                                               replacement.ReplaceWith.identifier, replacement.ReplaceWith.version,
                                               replacement.ToReplace.identifier, replacement.ToReplace.version);
                                to_replace.Add(replacement);
                            }
                        }
                        catch (ModuleNotFoundKraken)
                        {
                            log.InfoFormat("{0} is installed, but it or its replacement is not in the registry",
                                           mod.Key);
                        }
                    }
                }
            }
            else
            {
                foreach (string mod in options.modules)
                {
                    try
                    {
                        log.DebugFormat("Checking that {0} is installed", mod);
                        CkanModule modToReplace = registry.GetInstalledVersion(mod);
                        if (modToReplace != null)
                        {
                            log.DebugFormat("Testing {0} {1} for possible replacement", modToReplace.identifier, modToReplace.version);
                            try
                            {
                                // Check if replacement is available
                                ModuleReplacement replacement = registry.GetReplacement(modToReplace.identifier, ksp.VersionCriteria());
                                if (replacement != null)
                                {
                                    // Replaceable
                                    log.InfoFormat("Replacement {0} {1} found for {2} {3}",
                                                   replacement.ReplaceWith.identifier, replacement.ReplaceWith.version,
                                                   replacement.ToReplace.identifier, replacement.ToReplace.version);
                                    to_replace.Add(replacement);
                                }
                                if (modToReplace.replaced_by != null)
                                {
                                    log.InfoFormat("Attempt to replace {0} failed, replacement {1} is not compatible",
                                                   mod, modToReplace.replaced_by.name);
                                }
                                else
                                {
                                    log.InfoFormat("Mod {0} has no replacement defined for the current version {1}",
                                                   modToReplace.identifier, modToReplace.version);
                                }
                            }
                            catch (ModuleNotFoundKraken)
                            {
                                log.InfoFormat("{0} is installed, but its replacement {1} is not in the registry",
                                               mod, modToReplace.replaced_by.name);
                            }
                        }
                    }
                    catch (ModuleNotFoundKraken kraken)
                    {
                        User.RaiseMessage("Module {0} not found", kraken.module);
                    }
                }
            }
            if (to_replace.Count() != 0)
            {
                User.RaiseMessage("\r\nReplacing modules...\r\n");
                foreach (ModuleReplacement r in to_replace)
                {
                    User.RaiseMessage("Replacement {0} {1} found for {2} {3}",
                                      r.ReplaceWith.identifier, r.ReplaceWith.version,
                                      r.ToReplace.identifier, r.ToReplace.version);
                }

                bool ok = User.RaiseYesNoDialog("Continue?");

                if (!ok)
                {
                    User.RaiseMessage("Replacements canceled at user request.");
                    return(Exit.ERROR);
                }

                // TODO: These instances all need to go.
                try
                {
                    HashSet <string> possibleConfigOnlyDirs = null;
                    new ModuleInstaller(ksp, manager.Cache, User).Replace(to_replace, replace_ops, new NetAsyncModulesDownloader(User, manager.Cache), ref possibleConfigOnlyDirs, regMgr);
                    User.RaiseMessage("");
                }
                catch (DependencyNotSatisfiedKraken ex)
                {
                    User.RaiseMessage("Dependencies not satisfied for replacement, {0} requires {1} {2} but it is not listed in the index, or not available for your version of KSP.", ex.parent, ex.module, ex.version);
                }
            }
            else
            {
                User.RaiseMessage("No replacements found.");
                return(Exit.OK);
            }

            return(Exit.OK);
        }
示例#23
0
        /// <summary>
        /// Installs a module, if available
        /// </summary>
        /// <param name="ksp">Game instance into which to install</param>
        /// <param name="raw_options">Command line options object</param>
        /// <returns>
        /// Exit code for shell environment
        /// </returns>
        public int RunCommand(CKAN.GameInstance ksp, object raw_options)
        {
            InstallOptions options = (InstallOptions)raw_options;

            if (options.ckan_files != null)
            {
                // Oooh! We're installing from a CKAN file.
                foreach (string ckan_file in options.ckan_files)
                {
                    Uri ckan_uri;

                    // Check if the argument if a wellformatted Uri.
                    if (!Uri.IsWellFormedUriString(ckan_file, UriKind.Absolute))
                    {
                        // Assume it is a local file, check if the file exists.
                        if (File.Exists(ckan_file))
                        {
                            // Get the full path of the file.
                            ckan_uri = new Uri(Path.GetFullPath(ckan_file));
                        }
                        else
                        {
                            // We have no further ideas as what we can do with this Uri, tell the user.
                            user.RaiseError("Can not find file \"{0}\".", ckan_file);
                            user.RaiseError("Exiting.");
                            return(Exit.ERROR);
                        }
                    }
                    else
                    {
                        ckan_uri = new Uri(ckan_file);
                    }

                    string filename = String.Empty;

                    // If it is a local file, we already know the filename. If it is remote, create a temporary file and download the remote resource.
                    if (ckan_uri.IsFile)
                    {
                        filename = ckan_uri.LocalPath;
                        log.InfoFormat("Installing from local CKAN file \"{0}\"", filename);
                    }
                    else
                    {
                        log.InfoFormat("Installing from remote CKAN file \"{0}\"", ckan_uri);
                        filename = Net.Download(ckan_uri, null, user);

                        log.DebugFormat("Temporary file for \"{0}\" is at \"{1}\".", ckan_uri, filename);
                    }

                    // Parse the JSON file.
                    try
                    {
                        CkanModule m = MainClass.LoadCkanFromFile(ksp, filename);
                        options.modules.Add($"{m.identifier}={m.version}");
                    }
                    catch (Kraken kraken)
                    {
                        user.RaiseError(kraken.InnerException == null
                            ? kraken.Message
                            : $"{kraken.Message}: {kraken.InnerException.Message}");
                    }
                }

                // At times RunCommand() calls itself recursively - in this case we do
                // not want to be doing this again, so "consume" the option
                options.ckan_files = null;
            }
            else
            {
                Search.AdjustModulesCase(ksp, options.modules);
            }

            if (options.modules.Count == 0)
            {
                // What? No files specified?
                user.RaiseMessage(
                    "Usage: ckan install [--with-suggests] [--with-all-suggests] [--no-recommends] [--headless] Mod [Mod2, ...]");
                return(Exit.BADOPT);
            }

            // Prepare options. Can these all be done in the new() somehow?
            var install_ops = new RelationshipResolverOptions
            {
                with_all_suggests  = options.with_all_suggests,
                with_suggests      = options.with_suggests,
                with_recommends    = !options.no_recommends,
                allow_incompatible = options.allow_incompatible
            };

            if (user.Headless)
            {
                install_ops.without_toomanyprovides_kraken = true;
                install_ops.without_enforce_consistency    = true;
            }

            RegistryManager regMgr  = RegistryManager.Instance(ksp);
            List <string>   modules = options.modules;

            for (bool done = false; !done;)
            {
                // Install everything requested. :)
                try
                {
                    HashSet <string> possibleConfigOnlyDirs = null;
                    var installer = ModuleInstaller.GetInstance(ksp, manager.Cache, user);
                    installer.InstallList(modules, install_ops, regMgr, ref possibleConfigOnlyDirs);
                    user.RaiseMessage("");
                    done = true;
                }
                catch (DependencyNotSatisfiedKraken ex)
                {
                    user.RaiseError(ex.Message);
                    user.RaiseMessage("If you're lucky, you can do a `ckan update` and try again.");
                    user.RaiseMessage("Try `ckan install --no-recommends` to skip installation of recommended modules.");
                    user.RaiseMessage("Or `ckan install --allow-incompatible` to ignore module compatibility.");
                    return(Exit.ERROR);
                }
                catch (ModuleNotFoundKraken ex)
                {
                    if (ex.version == null)
                    {
                        user.RaiseError("Module {0} required but it is not listed in the index, or not available for your version of KSP.",
                                        ex.module);
                    }
                    else
                    {
                        user.RaiseError("Module {0} {1} required but it is not listed in the index, or not available for your version of KSP.",
                                        ex.module, ex.version);
                    }
                    user.RaiseMessage("If you're lucky, you can do a `ckan update` and try again.");
                    user.RaiseMessage("Try `ckan install --no-recommends` to skip installation of recommended modules.");
                    user.RaiseMessage("Or `ckan install --allow-incompatible` to ignore module compatibility.");
                    return(Exit.ERROR);
                }
                catch (BadMetadataKraken ex)
                {
                    user.RaiseError("Bad metadata detected for module {0}: {1}",
                                    ex.module, ex.Message);
                    return(Exit.ERROR);
                }
                catch (TooManyModsProvideKraken ex)
                {
                    // Request the user selects one of the mods.
                    string[] mods = new string[ex.modules.Count];

                    for (int i = 0; i < ex.modules.Count; i++)
                    {
                        mods[i] = String.Format("{0} ({1})", ex.modules[i].identifier, ex.modules[i].name);
                    }

                    string message = String.Format("Too many mods provide {0}. Please pick from the following:\r\n", ex.requested);

                    int result;

                    try
                    {
                        result = user.RaiseSelectionDialog(message, mods);
                    }
                    catch (Kraken e)
                    {
                        user.RaiseMessage(e.Message);

                        return(Exit.ERROR);
                    }

                    if (result < 0)
                    {
                        user.RaiseMessage(String.Empty); // Looks tidier.

                        return(Exit.ERROR);
                    }

                    // Add the module to the list.
                    modules.Add($"{ex.modules[result].identifier}={ex.modules[result].version}");
                    // DON'T return so we can loop around and try again
                }
                catch (FileExistsKraken ex)
                {
                    if (ex.owningModule != null)
                    {
                        user.RaiseError(
                            "Oh no! We tried to overwrite a file owned by another mod!\r\n" +
                            "Please try a `ckan update` and try again.\r\n\r\n" +
                            "If this problem re-occurs, then it maybe a packaging bug.\r\n" +
                            "Please report it at:\r\n\r\n" +
                            "https://github.com/KSP-CKAN/NetKAN/issues/new\r\n\r\n" +
                            "Please including the following information in your report:\r\n\r\n" +
                            "File           : {0}\r\n" +
                            "Installing Mod : {1}\r\n" +
                            "Owning Mod     : {2}\r\n" +
                            "CKAN Version   : {3}\r\n",
                            ex.filename, ex.installingModule, ex.owningModule,
                            Meta.GetVersion(VersionFormat.Full)
                            );
                    }
                    else
                    {
                        user.RaiseError(
                            "Oh no!\r\n\r\n" +
                            "It looks like you're trying to install a mod which is already installed,\r\n" +
                            "or which conflicts with another mod which is already installed.\r\n\r\n" +
                            "As a safety feature, CKAN will *never* overwrite or alter a file\r\n" +
                            "that it did not install itself.\r\n\r\n" +
                            "If you wish to install {0} via CKAN,\r\n" +
                            "then please manually uninstall the mod which owns:\r\n\r\n" +
                            "{1}\r\n\r\n" + "and try again.\r\n",
                            ex.installingModule, ex.filename
                            );
                    }

                    user.RaiseMessage("Your GameData has been returned to its original state.");
                    return(Exit.ERROR);
                }
                catch (InconsistentKraken ex)
                {
                    // The prettiest Kraken formats itself for us.
                    user.RaiseError(ex.InconsistenciesPretty);
                    user.RaiseMessage("Install canceled. Your files have been returned to their initial state.");
                    return(Exit.ERROR);
                }
                catch (CancelledActionKraken k)
                {
                    user.RaiseError("Installation aborted: {0}", k.Message);
                    return(Exit.ERROR);
                }
                catch (MissingCertificateKraken kraken)
                {
                    // Another very pretty kraken.
                    user.RaiseError(kraken.ToString());
                    return(Exit.ERROR);
                }
                catch (DownloadThrottledKraken kraken)
                {
                    user.RaiseError(kraken.ToString());
                    user.RaiseMessage("Try the authtoken command. See {0} for details.",
                                      kraken.infoUrl);
                    return(Exit.ERROR);
                }
                catch (DownloadErrorsKraken)
                {
                    user.RaiseError("One or more files failed to download, stopped.");
                    return(Exit.ERROR);
                }
                catch (ModuleDownloadErrorsKraken kraken)
                {
                    user.RaiseError(kraken.ToString());
                    return(Exit.ERROR);
                }
                catch (DirectoryNotFoundKraken kraken)
                {
                    user.RaiseError(kraken.Message);
                    return(Exit.ERROR);
                }
                catch (ModuleIsDLCKraken kraken)
                {
                    user.RaiseError("CKAN can't install expansion '{0}' for you.",
                                    kraken.module.name);
                    var res           = kraken?.module?.resources;
                    var storePagesMsg = new Uri[] { res?.store, res?.steamstore }
                    .Where(u => u != null)
                    .Aggregate("", (a, b) => $"{a}\r\n- {b}");
                    if (!string.IsNullOrEmpty(storePagesMsg))
                    {
                        user.RaiseMessage($"To install this expansion, purchase it from one of its store pages:\r\n{storePagesMsg}");
                    }
                    return(Exit.ERROR);
                }
            }

            return(Exit.OK);
        }